]> andersk Git - moira.git/blob - clients/moira/cluster.c
missing include of ctype.h
[moira.git] / clients / moira / cluster.c
1 #if (!defined(lint) && !defined(SABER))
2   static char rcsid_module_c[] = "$Header$";
3 #endif lint
4
5 /*      This is the file cluster.c for the MOIRA Client, which allows a nieve
6  *      user to quickly and easily maintain most parts of the MOIRA database.
7  *      It Contains: 
8  *      
9  *      Created:        4/22/88
10  *      By:             Chris D. Peterson
11  *
12  *      $Source$
13  *      $Author$
14  *      $Header$
15  *      
16  *      Copyright 1988 by the Massachusetts Institute of Technology.
17  *
18  *      For further information on copyright and distribution 
19  *      see the file mit-copyright.h
20  */
21
22 /* BTW: for anyone who cares MCD is short for Machine, Cluster, Data. */
23
24 #include <stdio.h>
25 #include <strings.h>
26 #include <moira.h>
27 #include <moira_site.h>
28 #include <menu.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #ifdef POSIX
34 #include <sys/utsname.h>
35 #endif
36 #include <netdb.h>
37 #include <ctype.h>
38
39 #include "mit-copyright.h"
40 #include "defs.h"
41 #include "f_defs.h"
42 #include "globals.h"
43
44 #define MACHINE  0
45 #define CLUSTER  1
46 #define DATA     2
47 #define MAP      3
48 #define SUBNET   4
49 #define CNAME    5
50
51 #define M_DEFAULT_TYPE     DEFAULT_NONE
52
53 #define C_DEFAULT_DESCRIPT DEFAULT_NONE
54 #define C_DEFAULT_LOCATION DEFAULT_NONE
55
56 #define CD_DEFAULT_LABEL   DEFAULT_NONE
57 #define CD_DEFAULT_DATA    DEFAULT_NONE
58
59 #define S_DEFAULT_LOW   "18.0.0.10"
60 #define S_DEFAULT_HIGH  "18.0.2.252"
61
62 static char *states[] = { "Reserved (0)",
63                           "Active (1)",
64                           "None (2)",
65                           "Deleted (3)" };
66
67 static char *MacState(state)
68 int state;
69 {
70     char buf[BUFSIZ];
71
72     if (state < 0 || state > 3) {
73         sprintf(buf, "Unknown (%d)", state);
74         return(buf);
75     }
76     return(states[state]);
77 }
78
79
80
81 /* -------------------- Set Defaults -------------------- */
82
83 /*      Function Name: SetMachineDefaults
84  *      Description: sets machine defaults.
85  *      Arguments: info - an array to put the defaults into.
86  *                 name - Canonacalized name of the machine.
87  *      Returns: info - the array.
88  */
89
90 static char **
91 SetMachineDefaults(info, name)
92 char ** info, *name;
93 {
94     info[M_NAME] = Strsave(name);
95     info[M_VENDOR] = Strsave(M_DEFAULT_TYPE);
96     info[M_MODEL] = Strsave(M_DEFAULT_TYPE);
97     info[M_OS] = Strsave(M_DEFAULT_TYPE);
98     info[M_LOC] = Strsave(M_DEFAULT_TYPE);
99     info[M_CONTACT] = Strsave(M_DEFAULT_TYPE);
100     info[M_USE] = Strsave("0");
101     info[M_STAT] = Strsave("1");
102     info[8] = Strsave("NONE");
103     info[9] = Strsave("unique");
104     info[10] = Strsave("NONE");
105     info[11] = Strsave("NONE");
106     info[12] = Strsave("");
107     info[13] = Strsave("");
108     info[14] = info[15] = info[16] = NULL;
109     return(info);
110 }
111
112 /*      Function Name: SetClusterDefaults
113  *      Description: sets Cluster defaults.
114  *      Arguments: info - an array to put the defaults into.
115  *                 name - name of the Cluster.
116  *      Returns: info - the array.
117  */
118
119 static char **
120 SetClusterDefaults(info, name)
121 char ** info, *name;
122 {
123     info[C_NAME] = Strsave(name);
124     info[C_DESCRIPT] = Strsave(C_DEFAULT_DESCRIPT);
125     info[C_LOCATION] = Strsave(C_DEFAULT_LOCATION);
126     info[C_MODBY] = info[C_MODTIME] = info[C_MODWITH] = info[C_END] = NULL;
127     return(info);
128 }
129
130 /*      Function Name: SetSubnetDefaults
131  *      Description: sets Subnet defaults.
132  *      Arguments: info - an array to put the defaults into.
133  *                 name - name of the Subnet.
134  *      Returns: info - the array.
135  */
136
137 static char **
138 SetSubnetDefaults(info, name)
139 char ** info, *name;
140 {
141     char buf[256];
142
143     info[C_NAME] = Strsave(name);
144     info[SN_DESC] = Strsave("");
145     sprintf(buf, "%d", ntohl(inet_addr("18.255.0.0")));
146     info[SN_ADDRESS] = Strsave(buf);
147     sprintf(buf, "%d", ntohl(inet_addr("255.255.0.0")));
148     info[SN_MASK] = Strsave(buf);
149     sprintf(buf, "%d", ntohl(inet_addr(S_DEFAULT_LOW)));
150     info[SN_LOW] = Strsave(buf);
151     sprintf(buf, "%d", ntohl(inet_addr(S_DEFAULT_HIGH)));
152     info[SN_HIGH] = Strsave(buf);
153     info[SN_PREFIX] = Strsave("");
154     info[SN_ACE_TYPE] = Strsave("LIST");
155     info[SN_ACE_NAME] = Strsave("network_acl");
156     info[SN_MODBY] = info[SN_MODTIME] = info[SN_MODWITH] = info[SN_END] = NULL;
157     return(info);
158 }
159
160 /* -------------------- General Functions -------------------- */
161
162 static char aliasbuf[256];
163
164 static char *
165 PrintAliases(info)
166 char **info;
167 {
168     if (strlen(aliasbuf) == 0)
169       sprintf(aliasbuf, "Aliases:  %s", info[0]);
170     else {
171         strcat(aliasbuf, ", ");
172         strcat(aliasbuf, info[0]);
173     }
174 }
175
176
177 /*      Function Name: PrintMachInfo
178  *      Description: This function Prints out the Machine info in 
179  *                   a coherent form.
180  *      Arguments: info - array of information about a machine.
181  *      Returns: The name of the Machine
182  */
183
184 static char *
185 PrintMachInfo(info)
186 char ** info;
187 {
188     char buf[BUFSIZ], tbuf[256];
189     char *args[3];
190     struct qelem *elem = NULL;
191     int stat;
192
193     Put_message("");
194     sprintf(buf, "Machine:  %s", info[M_NAME]);
195     Put_message(buf);
196     args[0] = "*";
197     args[1] = info[M_NAME];
198     if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, (char *)&elem))
199         != 0) {
200         if (stat != MR_NO_MATCH)
201           com_err(program_name, stat, " looking up aliases");
202     } else {
203         aliasbuf[0] = 0;
204         Loop(QueueTop(elem), (void *) PrintAliases);
205         FreeQueue(elem);
206         Put_message(aliasbuf);
207     }
208     sprintf(buf, "Address:  %-16s  Subnet:    %s",
209             info[M_ADDR], info[M_SUBNET]);
210     Put_message(buf);
211     sprintf(buf, "Status:   %-16s  Changed:   %s",
212             MacState(atoi(info[M_STAT])), info[M_STAT_CHNG]);
213     Put_message(buf);
214     sprintf(tbuf, "%s %s", info[M_OWNER_TYPE],
215             strcmp(info[M_OWNER_TYPE], "NONE") ? info[M_OWNER_NAME] : "");
216     sprintf(buf, "Owner:    %-16s  Last poll: %s", tbuf, info[M_INUSE]);
217     Put_message(buf);
218     Put_message("");
219
220     sprintf(buf, "Vendor:   %-16s  Model: %-24s  OS: %s",
221             info[M_VENDOR], info[M_MODEL], info[M_OS]);
222     Put_message(buf);
223     sprintf(buf, "Location: %-16s  Contact:   %s  Use code: %s",
224             info[M_LOC], info[M_CONTACT], info[M_USE]);
225     Put_message(buf);
226     sprintf(buf, "Admn cmt: %s", info[M_ACOMMENT]);
227     Put_message(buf);
228     sprintf(buf, "Op cmt:   %s", info[M_OCOMMENT]);
229     Put_message(buf);
230     Put_message("");
231     sprintf(buf, "Created  by %s on %s", info[M_CREATOR], info[M_CREATED]);
232     Put_message(buf);
233     sprintf(buf, MOD_FORMAT, info[M_MODBY], info[M_MODTIME], info[M_MODWITH]);
234     Put_message(buf);
235     return(info[M_NAME]);
236 }
237
238 /*      Function Name: PrintCname
239  *      Description: Prints the Data on a host alias
240  *      Arguments: info a pointer to the data array.
241  *      Returns: The name of the alias.
242  */
243
244 static char *
245 PrintCname(info)
246 char ** info;
247 {
248     char buf[BUFSIZ];
249
250     sprintf(buf, "Alias: %-32s Canonical Name: %s", info[0], info[1]);
251     Put_message(buf);
252     return(info[0]);
253 }
254
255 /*      Function Name: PrintClusterInfo
256  *      Description: This function Prints out the cluster info 
257  *                   in a coherent form.
258  *      Arguments: info - array of information about a cluster.
259  *      Returns: The name of the cluster.
260  */
261
262 static char *
263 PrintClusterInfo(info)
264 char ** info;
265 {
266     char buf[BUFSIZ];
267
268     Put_message("");
269     sprintf(buf, "Cluster:     %s", info[C_NAME]);
270     Put_message(buf);
271     sprintf(buf, "Description: %s", info[C_DESCRIPT]);
272     Put_message(buf);
273     sprintf(buf, "Location:    %s", info[C_LOCATION]);
274     Put_message(buf);
275     sprintf(buf, MOD_FORMAT, info[C_MODBY], info[C_MODTIME], info[C_MODWITH]);
276     Put_message(buf);
277     return(info[C_NAME]);
278 }
279
280 /*      Function Name: PrintClusterData
281  *      Description: Prints the Data on a cluster
282  *      Arguments: info a pointer to the data array.
283  *      Returns: The name of the cluster.
284  */
285
286 static char *
287 PrintClusterData(info)
288 char ** info;
289 {
290     char buf[BUFSIZ];
291
292     Put_message("");
293     sprintf(buf, "Cluster: %-20s Label: %-15s Data: %s",
294             info[CD_NAME], info[CD_LABEL], info[CD_DATA]);
295     Put_message(buf);
296     return(info[CD_NAME]);
297 }
298
299 /*      Function Name: PrintMCMap
300  *      Description: Prints the data about a machine to cluster mapping.
301  *      Arguments: info a pointer to the data array.
302  *      Returns: none
303  */
304
305 static char *
306 PrintMCMap(info)
307 char ** info;
308 {
309     char buf[BUFSIZ];
310     sprintf(buf, "Cluster: %-30s Machine: %-20s",
311             info[MAP_CLUSTER], info[MAP_MACHINE]);
312     Put_message(buf);
313     return("");                 /* Used by QueryLoop(). */
314 }
315
316 /*      Function Name: PrintSubnetInfo
317  *      Description: This function Prints out the subnet info 
318  *                   in a coherent form.
319  *      Arguments: info - array of information about a subnet.
320  *      Returns: The name of the subnet.
321  */
322
323 static char *
324 PrintSubnetInfo(info)
325 char ** info;
326 {
327     char buf[BUFSIZ];
328     struct in_addr addr, mask, low, high;
329
330     Put_message("");
331     sprintf(buf, "Subnet:     %s", info[SN_NAME]);
332     Put_message(buf);
333     sprintf(buf, "Description: %s", info[SN_DESC]);
334     Put_message(buf);
335     addr.s_addr = htonl(atoi(info[SN_ADDRESS]));
336     mask.s_addr = htonl(atoi(info[SN_MASK]));
337     low.s_addr = htonl(atoi(info[SN_LOW]));
338     high.s_addr = htonl(atoi(info[SN_HIGH]));
339     /* screwy sequence is here because inet_ntoa returns a pointer to
340        a static buf.  If it were all one sprintf, the last value would
341        appear 4 times. */
342     sprintf(buf, "Address %s, Mask ", inet_ntoa(addr));
343     strcat(buf, inet_ntoa(mask));
344     strcat(buf, ", High ");
345     strcat(buf, inet_ntoa(high));
346     strcat(buf, ", Low ");
347     strcat(buf, inet_ntoa(low));
348     Put_message(buf);
349     sprintf(buf, "Hostname prefix: %s", info[SN_PREFIX]);
350     Put_message(buf);
351     sprintf(buf, "Owner: %s %s", info[SN_ACE_TYPE],
352             strcmp(info[SN_ACE_TYPE],"NONE") ? info[SN_ACE_NAME] : "");
353     Put_message(buf);
354     sprintf(buf,MOD_FORMAT,info[SN_MODBY],info[SN_MODTIME],info[SN_MODWITH]);
355     Put_message(buf);
356     return(info[SN_NAME]);
357 }
358
359 /*      Function Name: GetMCInfo.
360  *      Description: This function stores info about a machine.
361  *                   type - type of data we are trying to retrieve.
362  *                   name1 - the name of argv[0] for the call.
363  *                   name2 - the name of argv[1] for the call.
364  *      Returns: the top element of a queue containing the data or NULL.
365  */
366
367 struct qelem *
368 GetMCInfo(type, name1, name2)
369 int type;
370 char * name1, *name2;
371 {
372
373     int stat;
374     struct qelem * elem = NULL;
375     char * args[5];
376
377     switch (type) {
378     case MACHINE:
379         args[0] = name1;
380         args[1] = args[2] = args[3] = "*";
381         if ( (stat = do_mr_query("get_host", 4, args,
382                                   StoreInfo, (char *)&elem)) != 0) {
383             if (stat == MR_NO_MATCH) {
384                 char buf[128];
385                 sprintf(buf, "Machine '%s' is not in the database.", name1);
386                 Put_message(buf);
387             } else
388               com_err(program_name, stat, " in get_machine.");
389             return(NULL);
390         }
391         break;
392     case CNAME:
393         args[0] = name1;
394         args[1] = name2;
395         if ( (stat = do_mr_query("get_hostalias", 2, args,
396                                   StoreInfo, (char *)&elem)) != 0) {
397             com_err(program_name, stat, " in get_hostalias.");
398             return(NULL);
399         }
400         break;
401     case SUBNET:
402         if ( (stat = do_mr_query("get_subnet", 1, &name1,
403                                  StoreInfo, (char *)&elem)) != 0) {
404             if (stat == MR_NO_MATCH) {
405                 char buf[128];
406                 sprintf(buf, "Subnet '%s' is not in the database.", name1);
407                 Put_message(buf);
408             } else
409               com_err(program_name, stat, " in get_subnet.");
410             return(NULL);
411         }
412         break;
413     case CLUSTER:
414         if ( (stat = do_mr_query("get_cluster",  1, &name1,
415                                   StoreInfo, (char *)&elem)) != 0) {
416             com_err(program_name, stat, " in get_cluster.");
417             return(NULL);
418         }
419         break;
420     case MAP:
421         args[MAP_MACHINE] = name1;
422         args[MAP_CLUSTER] = name2;
423         if ( (stat = do_mr_query("get_machine_to_cluster_map", 2, args,
424                                   StoreInfo, (char *)&elem)) != 0) {
425             com_err(program_name, stat, " in get_machine_to_cluster_map.");
426             return(NULL);
427         }
428         break;
429     case DATA:
430         args[CD_NAME] = name1;
431         args[CD_LABEL] = name2;
432         if ( (stat = do_mr_query("get_cluster_data", 2, args,
433                                   StoreInfo, (char *)&elem)) != 0) {
434             com_err(program_name, stat, " in get_cluster_data.");
435             return(NULL);
436         }
437     }
438     return(QueueTop(elem));
439 }
440
441 /*      Function Name: AskMCDInfo.
442  *      Description: This function askes the user for information about a 
443  *                   machine and saves it into a structure.
444  *      Arguments: info - a pointer the information to ask about
445  *                 type - type of information - MACHINE
446  *                                              CLUSTER
447  *                                              DATA
448  *                 name - T/F : change the name of this type.
449  *      Returns: none.
450  */
451
452 char **
453 AskMCDInfo(info, type, name)
454 char ** info;
455 int type;
456 Bool name;
457 {
458     char temp_buf[BUFSIZ], *newname, *oldnewname;
459
460     switch (type) {
461     case MACHINE:
462         sprintf(temp_buf, "Setting the information for the Machine %s.",
463                 info[M_NAME]);
464         break;
465     case SUBNET:
466         sprintf(temp_buf, "Setting the information for the Subnet %s.",
467                 info[SN_NAME]);
468         break;
469     case CLUSTER:
470         sprintf(temp_buf, "Setting the information for the Cluster %s.",
471                 info[C_NAME]);
472         break;
473     case DATA:
474         sprintf(temp_buf, "Setting the Data for the Cluster %s.",
475                 info[CD_NAME]);
476         break;
477     }
478     Put_message(temp_buf);
479
480     if (name) {
481         switch (type) {
482         case MACHINE:
483             newname = Strsave(info[M_NAME]);
484             if (GetValueFromUser("The new name for this machine? ", &newname) ==
485                 SUB_ERROR)
486               return(NULL);
487             oldnewname = Strsave(newname);
488             newname = canonicalize_hostname(newname);
489             if (strcasecmp(newname, oldnewname) && *oldnewname != '"') {
490                 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'\n",
491                         oldnewname, newname);
492                 Put_message(temp_buf);
493             }
494             free(oldnewname);
495             break;
496         case SUBNET:
497             newname = Strsave(info[SN_NAME]);
498             if (GetValueFromUser("The new name for this subnet? ",
499                                  &newname) == SUB_ERROR)
500               return(NULL);
501             break;
502         case CLUSTER:
503             newname = Strsave(info[C_NAME]);
504             if (GetValueFromUser("The new name for this cluster? ",
505                                  &newname) == SUB_ERROR)
506               return(NULL);
507             break;
508         default:
509             Put_message("Unknown type in AskMCDInfo, programmer botch");
510             return(NULL);
511         }
512     }
513
514     switch(type) {
515     case MACHINE:
516         if (GetValueFromUser("Machine's Vendor", &info[M_VENDOR]) == SUB_ERROR)
517           return(NULL);
518         if (GetValueFromUser("Machine's Model", &info[M_MODEL]) == SUB_ERROR)
519           return(NULL);
520         if (GetValueFromUser("Machine's Operating System", &info[M_OS]) ==
521             SUB_ERROR)
522           return(NULL);
523         if (GetValueFromUser("Location of Machine", &info[M_LOC]) == SUB_ERROR)
524           return(NULL);
525         if (GetValueFromUser("Contact for Machine", &info[M_CONTACT]) ==
526             SUB_ERROR)
527           return(NULL);
528         if (GetValueFromUser("Machine's Use Code", &info[M_USE]) == SUB_ERROR)
529           return(NULL);
530         while (1) {
531             int i;
532             if (GetValueFromUser("Machine's Status (? for help)",
533                                  &info[M_STAT]) == SUB_ERROR)
534               return(NULL);
535             if (isdigit(info[M_STAT][0])) break;
536             Put_message("Valid status numbers:");
537             for (i = 0; i < 4; i++) Put_message(states[i]);
538         }
539         if (name) {
540             free(info[8]);
541             info[8] = info[M_SUBNET];
542             info[9] = info[M_ADDR];
543             info[10] = info[M_OWNER_TYPE];
544             info[11] = info[M_OWNER_NAME];
545             info[12] = info[M_ACOMMENT];
546             info[13] = info[M_OCOMMENT];
547         }
548         if (GetValueFromUser("Machine's subnet (or 'none')", &info[8])
549             == SUB_ERROR)
550           return(NULL);
551         if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')",
552                              &info[9]) == SUB_ERROR)
553           return(NULL);
554         if (GetTypeFromUser("Machine's Owner Type", "ace_type", &info[10]) ==
555             SUB_ERROR)
556           return(NULL);
557         if (strcmp(info[10], "NONE") &&
558             GetValueFromUser("Owner's Name", &info[11]) == SUB_ERROR)
559           return(NULL);
560         if (GetValueFromUser("Administrative Comment", &info[12]) == SUB_ERROR)
561           return(NULL);
562         if (GetValueFromUser("Operational Comment", &info[13]) == SUB_ERROR)
563           return(NULL);
564         info[14] = NULL;
565         FreeAndClear(&info[15], TRUE);
566         FreeAndClear(&info[16], TRUE);
567         break;
568     case SUBNET:
569         if (GetValueFromUser("Subnet Description", &info[SN_DESC]) == SUB_ERROR)
570           return(NULL);
571         if (GetAddressFromUser("Subnet Address", &info[SN_ADDRESS]) == SUB_ERROR)
572           return(NULL);
573         if (GetAddressFromUser("Subnet Mask", &info[SN_MASK]) == SUB_ERROR)
574           return(NULL);
575         if (atoi(info[SN_LOW]) == ntohl(inet_addr(S_DEFAULT_LOW))) {
576             struct in_addr low;
577             unsigned long mask, addr;
578
579             addr = atoi(info[SN_ADDRESS]);
580             mask = atoi(info[SN_MASK]);
581             low.s_addr = atoi(info[SN_LOW]);
582             low.s_addr = (low.s_addr & ~mask) | (addr & mask);
583             free(info[SN_LOW]);
584             sprintf(temp_buf, "%d", low.s_addr);
585             info[SN_LOW] = strsave(temp_buf);
586         }
587         if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) == SUB_ERROR)
588           return(NULL);
589         if (atoi(info[SN_HIGH]) == ntohl(inet_addr(S_DEFAULT_HIGH))) {
590             struct in_addr high;
591             unsigned long mask, addr;
592
593             addr = atoi(info[SN_ADDRESS]);
594             mask = atoi(info[SN_MASK]);
595             high.s_addr = atoi(info[SN_HIGH]);
596             high.s_addr = (high.s_addr & ~mask) | (addr & mask);
597             free(info[SN_HIGH]);
598             sprintf(temp_buf, "%d", high.s_addr);
599             info[SN_HIGH] = strsave(temp_buf);
600         }
601         if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) == SUB_ERROR)
602           return(NULL);
603         if (GetValueFromUser("Hostname prefix", &info[SN_PREFIX]) == SUB_ERROR)
604           return(NULL);
605         if (GetTypeFromUser("Owner Type", "ace_type", &info[SN_ACE_TYPE]) == SUB_ERROR)
606           return(NULL);
607         if (strcmp(info[SN_ACE_TYPE], "NONE") &&
608             GetValueFromUser("Owner Name", &info[SN_ACE_NAME]) == SUB_ERROR)
609           return(NULL);
610         FreeAndClear(&info[SN_MODTIME], TRUE);
611         FreeAndClear(&info[SN_MODBY], TRUE);
612         FreeAndClear(&info[SN_MODWITH], TRUE);
613         break;
614     case CLUSTER:
615         if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) ==
616             SUB_ERROR)
617           return(NULL);
618         if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) ==
619             SUB_ERROR)
620           return(NULL);
621         FreeAndClear(&info[C_MODTIME], TRUE);
622         FreeAndClear(&info[C_MODBY], TRUE);
623         FreeAndClear(&info[C_MODWITH], TRUE);
624         break;
625     case DATA:
626         if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) ==
627             SUB_ERROR)
628           return(NULL);
629         if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR)
630           return(NULL);
631         break;
632     }
633
634 /* 
635  * Slide the newname into the #2 slot, this screws up all future references 
636  * to this list.
637  */
638     if (name)                   
639         SlipInNewName(info, newname);
640
641     return(info);
642 }
643
644 /* -----------  Machine Menu ----------- */
645
646 /*      Function Name: ShowMachineInfo
647  *      Description: This function shows the information about a machine.
648  *      Arguments: argc, argv - the name of the machine in argv[1].
649  *      Returns: DM_NORMAL.
650  */
651
652 /* ARGSUSED */
653 int
654 ShowMachineInfo(argc, argv)
655 int argc;
656 char **argv;
657 {
658     struct qelem *top;
659     char *tmpname;
660
661     tmpname = canonicalize_hostname(strsave(argv[1]));
662     top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
663     Loop(top, ( (void *) PrintMachInfo) );
664     FreeQueue(top);
665     return(DM_NORMAL);
666 }
667
668 /*      Function Name: ShowMachineQuery
669  *      Description: This function shows the information about a machine.
670  *              or group of machines, which may be selected through a
671  *              number of criteria. 
672  *      Arguments: argc, argv - the name of the machine in argv[1],
673  *              the address of the machine in argv[2],
674  *              the location of the machine in argv[3],
675  *              and the contact name in argv[4].
676  *           any of these may be wildcards.
677  *      Returns: DM_NORMAL.
678  */
679
680 /* ARGSUSED */
681 int
682 ShowMachineQuery(argc, argv)
683 int argc;
684 char **argv;
685 {
686     int stat;
687     struct qelem *top, *elem = NULL;
688     char *args[5];
689
690     if (!strcmp(argv[1], "") && !strcmp(argv[2], "") &&
691         !strcmp(argv[3], "") && !strcmp(argv[4], "")) {
692         Put_message("You must specify at least one parameter of the query.");
693         return(DM_NORMAL);
694     }
695
696     if (*argv[1])
697       args[0] = canonicalize_hostname(strsave(argv[1]));
698     else
699       args[0] = "*";
700     if (*argv[2])
701       args[1] = argv[2];
702     else
703       args[1] = "*";
704     if (*argv[3])
705       args[2] = argv[3];
706     else
707       args[2] = "*";
708     if (*argv[4])
709       args[3] = argv[4];
710     else
711       args[3] = "*";
712
713     if ((stat = do_mr_query("get_host", 4, args, StoreInfo,
714                             (char *)&elem)) != 0) {
715         if (stat == MR_NO_MATCH)
716           Put_message("No machine(s) found matching query in the database.");
717         else
718           com_err(program_name, stat, " in get_machine.");
719         return(DM_NORMAL);
720     }
721     top = QueueTop(elem);
722     Loop(top, ( (void *) PrintMachInfo) );
723     FreeQueue(top);
724     return(DM_NORMAL);
725 }
726
727 /*      Function Name: AddMachine
728  *      Description: This function adds a new machine to the database.
729  *      Arguments: argc, argv - the name of the machine in argv[1].
730  *      Returns: DM_NORMAL.
731  */
732
733 /* ARGSUSED */
734 int
735 AddMachine(argc, argv)
736 int argc;
737 char **argv;
738 {
739     char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
740     int stat;
741
742     if (!ValidName(argv[1]))    /* Checks for wildcards. */
743         return(DM_NORMAL);
744 /* 
745  * Check to see if this machine already exists. 
746  */
747     name =  canonicalize_hostname(strsave(argv[1]));
748
749     xargs[0] = name;
750     xargs[1] = xargs[2] = xargs[3] = "*";
751     if ( (stat = do_mr_query("get_host", 4, xargs, NullFunc, NULL)) == 0) {
752         sprintf(buf, "The machine '%s' already exists.", name);
753         Put_message(buf);
754         free(name);
755         return(DM_NORMAL);
756     }
757     else if (stat != MR_NO_MATCH) {
758         com_err(program_name, stat,
759                 " while checking machine '%s' in AddMachine.", name);
760         free(name);
761         return(DM_NORMAL);
762     }
763
764     if ((args = AskMCDInfo(SetMachineDefaults(info, name), MACHINE, FALSE)) ==
765         NULL) {
766         Put_message("Aborted.");
767         return(DM_NORMAL);
768     }
769
770 /*
771  * Actually create the new Machine.
772  */
773     
774     if ( (stat = do_mr_query("add_host", CountArgs(args), 
775                               args, Scream, NULL)) != 0)
776         com_err(program_name, stat, " in AddMachine.");
777
778     FreeInfo(info);
779     free(name);
780     return(DM_NORMAL);
781 }
782
783 /*      Function Name: RealUpdateMachine
784  *      Description: Performs the actual update of the machine data.
785  *      Arguments: info - the information on the machine to update.
786  *                 junk - an UNUSED Boolean.
787  *      Returns: none.
788  */
789
790 /* ARGSUSED */
791 static void
792 RealUpdateMachine(info, junk)
793 char ** info;
794 Bool junk;
795 {
796     register int stat;
797     char ** args = AskMCDInfo(info, MACHINE, TRUE);
798     if (args == NULL) {
799         Put_message("Aborted.");
800         return;
801     }
802     if ( (stat = do_mr_query("update_host", CountArgs(args), 
803                               args, Scream, NULL)) != 0)
804         com_err(program_name, stat, " in UpdateMachine.");
805     else
806         Put_message("Machine sucessfully updated.");
807 }
808
809 /*      Function Name: UpdateMachine
810  *      Description: This function adds a new machine to the database.
811  *      Arguments: argc, argv - the name of the machine in argv[1].
812  *      Returns: DM_NORMAL.
813  */
814
815 /* ARGSUSED */
816 int
817 UpdateMachine(argc, argv)
818 int argc;
819 char **argv;
820 {
821     struct qelem *top;
822     char *tmpname;
823
824     tmpname = canonicalize_hostname(strsave(argv[1]));
825     top = GetMCInfo( MACHINE,  tmpname, (char *) NULL);
826     QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
827
828     FreeQueue(top);
829     free(tmpname);
830     return(DM_NORMAL);
831 }
832
833 /*      Function Name: CheckAndRemoveFromCluster
834  *      Description: This func tests to see if a machine is in a cluster.
835  *                   and if so then removes it
836  *      Arguments: name - name of the machine (already Canonocalized).
837  *                 ask_user- query the user before removing if from clusters?
838  *      Returns: MR_ERROR if machine left in a cluster, or mr_error.
839  */
840
841 int 
842 CheckAndRemoveFromCluster(name, ask_user)
843 char * name;
844 Bool ask_user;
845 {
846     register int stat, ret_value;
847     Bool delete_it;
848     char *args[10], temp_buf[BUFSIZ], *ptr;
849     struct qelem *top, *elem = NULL;
850     
851     ret_value = SUB_NORMAL;     /* initialize ret_value. */
852     args[0] = name;
853     args[1] = "*";
854     stat = do_mr_query("get_machine_to_cluster_map", 2, args, 
855                         StoreInfo, (char *)&elem);
856     if (stat && stat != MR_NO_MATCH) {
857         com_err(program_name, stat, " in get_machine_to_cluster_map.");
858         return(DM_NORMAL);
859     }
860     if (stat == MR_SUCCESS) {
861         elem = top = QueueTop(elem);
862         if (ask_user) {
863             sprintf(temp_buf, "%s is assigned to the following clusters.",
864                     name);
865             Put_message(temp_buf);
866             Loop(top, (void *) PrintMCMap);
867             ptr = "Remove this machine from ** ALL ** these clusters?";
868             if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
869                 delete_it = TRUE;
870             else {
871                 Put_message("Aborting...");
872                 FreeQueue(top);
873                 return(SUB_ERROR);
874             }
875         }
876         else
877             delete_it = TRUE;
878
879         if (delete_it) {
880             while (elem != NULL) {
881                 char **info = (char **) elem->q_data;
882                 if ( (stat = do_mr_query( "delete_machine_from_cluster",
883                                           2, info, Scream, NULL)) != 0) {
884                     ret_value = SUB_ERROR;
885                     com_err(program_name, stat, 
886                             " in delete_machine_from_cluster.");
887                     sprintf(temp_buf, 
888                             "Machine %s ** NOT ** removed from cluster %s.",
889                             info[MAP_MACHINE], info[MAP_CLUSTER]);
890                     Put_message(temp_buf);
891                 }
892                 elem = elem->q_forw;
893             }
894         }
895     }
896     return(ret_value);
897 }
898
899 /*      Function Name: RealDeleteMachine
900  *      Description: Actually Deletes the Machine.
901  *      Arguments: info - nescessary information stored as an array of char *'s
902  *                 one_machine - a boolean, true if there is only one item in
903  *                               the query.
904  *      Returns: none.
905  */
906
907 static void
908 RealDeleteMachine(info, one_machine)
909 char ** info;
910 Bool one_machine;
911 {
912     register int stat;
913     char temp_buf[BUFSIZ];
914
915     sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ",
916             info[M_NAME]);
917     if(!one_machine || Confirm(temp_buf)) {
918         if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR) {
919             if ( (stat = do_mr_query("delete_host", 1,
920                                       &info[M_NAME], Scream, NULL)) != 0) {
921                 com_err(program_name, stat, " in DeleteMachine.");
922                 sprintf(temp_buf, "%s ** NOT ** deleted.", 
923                         info[M_NAME]);
924                 Put_message(temp_buf);
925             }
926             else {
927                 sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
928                 Put_message(temp_buf);
929             }
930         }
931     }
932 }
933
934 /*      Function Name: DeleteMachine
935  *      Description: This function removes a machine from the data base.
936  *      Arguments: argc, argv - the machines name int argv[1].
937  *      Returns: DM_NORMAL.
938  */
939
940 /* Perhaps we should remove the cluster if it has no machine now. */
941
942 /* ARGSUSED */
943 int
944 DeleteMachine(argc, argv)
945 int argc;
946 char **argv;
947 {
948     struct qelem *top;
949     char *tmpname;
950
951     tmpname = canonicalize_hostname(strsave(argv[1]));
952     top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
953     QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
954     FreeQueue(top);
955     free(tmpname);
956     return(DM_NORMAL);
957 }
958
959
960 char *partial_canonicalize_hostname(s)
961 char *s;
962 {
963     char buf[256], *cp;
964     static char *def_domain = NULL;
965     struct hostent *hp;
966 #ifdef POSIX
967     struct utsname name;
968 #endif
969
970     if (!def_domain) {
971 #ifdef POSIX
972         (void) uname(&name);
973         strncpy(buf, name.nodename, sizeof(buf));
974 #else
975         gethostname(buf, sizeof(buf));
976 #endif
977         hp = gethostbyname(buf);
978         cp = strchr(hp->h_name, '.');
979         if (cp)
980           def_domain = strsave(++cp);
981         else
982           def_domain = "";
983     }
984
985     if (strchr(s, '.') || strchr(s, '*'))
986       return(s);
987     sprintf(buf, "%s.%s", s, def_domain);
988     free(s);
989     return(strsave(buf));
990 }
991
992
993 /*      Function Name: ShowCname
994  *      Description: This function shows machine aliases
995  *      Arguments: argc, argv - the alias argv[1], the real name in argv[2]
996  *      Returns: DM_NORMAL.
997  */
998
999 /* ARGSUSED */
1000 int
1001 ShowCname(argc, argv)
1002 int argc;
1003 char **argv;
1004 {
1005     struct qelem *top;
1006     char *tmpalias, *tmpname;
1007
1008     tmpalias = partial_canonicalize_hostname(strsave(argv[1]));
1009     tmpname = canonicalize_hostname(strsave(argv[2]));
1010     top = GetMCInfo(CNAME, tmpalias, tmpname);
1011     Put_message("");            /* blank line on screen */
1012     Loop(top, ( (void *) PrintCname) );
1013     FreeQueue(top);
1014     return(DM_NORMAL);
1015 }
1016
1017
1018 /* ARGSUSED */
1019 int 
1020 AddCname(argc, argv)
1021 int argc;
1022 char ** argv;
1023 {
1024     int stat;
1025     char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1026     Bool add_it, one_machine, one_cluster;
1027     struct qelem * melem, *mtop, *celem, *ctop;
1028
1029     args[0] = partial_canonicalize_hostname(strsave(argv[1]));
1030     args[1] = canonicalize_hostname(strsave(argv[2]));
1031     stat = do_mr_query("add_hostalias", 2, args, Scream, NULL);
1032     switch (stat) {
1033     case MR_SUCCESS:
1034         break;
1035     case MR_EXISTS:
1036         Put_message("That alias name is already in use.");
1037         break;
1038     case MR_PERM:
1039         Put_message("Permission denied.  (Regular users can only add two aliases to a host.");
1040         break;
1041     default:
1042         com_err(program_name, stat, " in add_hostalias");
1043     }
1044     return(DM_NORMAL);
1045 }
1046
1047
1048 /* ARGSUSED */
1049 int 
1050 DeleteCname(argc, argv)
1051 int argc;
1052 char ** argv;
1053 {
1054     int stat;
1055     char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1056     Bool add_it, one_machine, one_cluster;
1057     struct qelem * melem, *mtop, *celem, *ctop;
1058
1059     args[0] = partial_canonicalize_hostname(strsave(argv[1]));
1060     args[1] = canonicalize_hostname(strsave(argv[2]));
1061     stat = do_mr_query("delete_hostalias", 2, args, Scream, NULL);
1062     if (stat)
1063       com_err(program_name, stat, " in delete_hostalias");
1064     return(DM_NORMAL);
1065 }
1066
1067
1068 /*      Function Name: AddMachineToCluster
1069  *      Description: This function adds a machine to a cluster
1070  *      Arguments: argc, argv - The machine name is argv[1].
1071  *                              The cluster name in argv[2].
1072  *      Returns: DM_NORMAL.
1073  */
1074
1075 /* ARGSUSED */
1076 int 
1077 AddMachineToCluster(argc, argv)
1078 int argc;
1079 char ** argv;
1080 {
1081     int stat;
1082     char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1083     Bool add_it, one_machine, one_cluster;
1084     struct qelem * melem, *mtop, *celem, *ctop;
1085
1086     machine = canonicalize_hostname(strsave(argv[1]));
1087     if (strcasecmp(machine, argv[1]) && *argv[1] != '"') {
1088         sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1089                 argv[1], machine);
1090         Put_message(temp_buf);
1091     }
1092     cluster = argv[2];
1093
1094     celem = ctop = GetMCInfo(CLUSTER,  cluster, (char *) NULL);
1095     melem = mtop = GetMCInfo(MACHINE,  machine, (char *) NULL);
1096     free(machine);
1097
1098     one_machine = (QueueCount(mtop) == 1);
1099     one_cluster = (QueueCount(ctop) == 1);
1100
1101     /* No good way to use QueryLoop() here, sigh */
1102
1103     while (melem != NULL) {
1104         char ** minfo = (char **) melem->q_data;
1105         while (celem != NULL) {
1106             char ** cinfo = (char **) celem->q_data;
1107             if (one_machine && one_cluster) 
1108                 add_it = TRUE;
1109             else {
1110                 sprintf(temp_buf,"Add machine %s to cluster %s (y/n/q) ?",
1111                         minfo[M_NAME], cinfo[C_NAME]);
1112                 switch (YesNoQuitQuestion(temp_buf, FALSE)) {
1113                 case TRUE:
1114                     add_it = TRUE;
1115                     break;
1116                 case FALSE:
1117                     add_it = FALSE;
1118                     break;
1119                 default:
1120                     Put_message("Aborting...");
1121                     FreeQueue(ctop);
1122                     FreeQueue(mtop);
1123                     return(DM_NORMAL);
1124                 }
1125             }
1126             if (add_it) {
1127                 args[0] = minfo[M_NAME];
1128                 args[1] = cinfo[C_NAME];
1129                 stat = do_mr_query("add_machine_to_cluster", 2, args,
1130                                     Scream, NULL);
1131                 switch (stat) {
1132                 case MR_SUCCESS:
1133                     break;
1134                 case MR_EXISTS:
1135                     sprintf(temp_buf, "%s is already in cluster %s",
1136                             minfo[M_NAME], cinfo[C_NAME]);
1137                     Put_message(temp_buf);
1138                     break;
1139                 default:
1140                     com_err(program_name, stat, " in AddMachineToCluster.");
1141                     break;
1142                 }
1143             }
1144             celem = celem->q_forw;
1145         }
1146         celem = ctop;           /* reset cluster element. */
1147         melem = melem->q_forw;
1148     }
1149     FreeQueue(ctop);
1150     FreeQueue(mtop);                
1151     return(DM_NORMAL);
1152 }
1153
1154 /*      Function Name: RealRemoveMachineFromCluster
1155  *      Description: This function actually removes the machine from its 
1156  *                   cluster.
1157  *      Arguments: info - all information nescessary to perform the removal.
1158  *                 one_map - True if there is only one case, and we should
1159  *                           confirm.
1160  *      Returns: none.
1161  */
1162
1163 static void
1164 RealRemoveMachineFromCluster(info, one_map)
1165 char ** info;
1166 Bool one_map;
1167 {
1168     char temp_buf[BUFSIZ];
1169     register int stat;
1170
1171     sprintf(temp_buf, "Remove %s from the cluster %s", 
1172             info[MAP_MACHINE], info[MAP_CLUSTER]);
1173     if (!one_map || Confirm(temp_buf)) {
1174         if ( (stat = do_mr_query("delete_machine_from_cluster", 2, 
1175                                   info, Scream, NULL)) != 0 )
1176             com_err(program_name, stat, " in delete_machine_from_cluster");
1177         else {
1178             sprintf(temp_buf, "%s has been removed from the cluster %s.",
1179                     info[MAP_MACHINE], info[MAP_CLUSTER]);
1180             Put_message(temp_buf);
1181         }
1182     }
1183     else
1184         Put_message("Machine not removed.");
1185 }
1186
1187 /*      Function Name: RemoveMachineFromCluster
1188  *      Description: Removes this machine form a specific cluster.
1189  *      Arguments: argc, argv - Name of machine in argv[1].
1190  *                              Name of cluster in argv[2].
1191  *      Returns: none.
1192  */
1193
1194 /* ARGSUSED */
1195 int
1196 RemoveMachineFromCluster(argc, argv)
1197 int argc;
1198 char ** argv;
1199 {
1200     struct qelem *elem = NULL;
1201     char buf[BUFSIZ], * args[10];
1202     register int stat;
1203
1204     args[MAP_MACHINE] = canonicalize_hostname(strsave(argv[1]));
1205     if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"') {
1206         sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
1207                 argv[1], args[MAP_MACHINE]);
1208         Put_message(buf);
1209     }
1210     args[MAP_CLUSTER] = argv[2];
1211     args[MAP_END] = NULL;
1212
1213     stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
1214                         StoreInfo, (char *)&elem);
1215     if (stat == MR_NO_MATCH) {
1216         sprintf(buf, "The machine %s is not is the cluster %s.",
1217                 args[MAP_MACHINE], args[MAP_CLUSTER]);
1218         Put_message(buf);
1219         free(args[MAP_MACHINE]);
1220         return(DM_NORMAL);
1221     }
1222     if (stat != MR_SUCCESS)
1223         com_err(program_name, stat, " in delete_machine_from_cluster");
1224
1225     elem = QueueTop(elem);
1226     QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster,
1227               "Remove this machine from this cluster");
1228
1229     FreeQueue(elem);
1230     free(args[MAP_MACHINE]);
1231     return(DM_NORMAL);
1232 }
1233
1234 /* ---------- Subnet Menu -------- */
1235
1236 /*      Function Name: ShowSubnetInfo
1237  *      Description: Gets information about a subnet given its name.
1238  *      Arguments: argc, argc - the name of the subnet in in argv[1].
1239  *      Returns: DM_NORMAL.
1240  */
1241
1242 /* ARGSUSED */
1243 int
1244 ShowSubnetInfo(argc, argv)
1245 int argc;
1246 char ** argv;
1247 {
1248     struct qelem *top;
1249
1250     top = GetMCInfo(SUBNET, argv[1], (char *) NULL);
1251     Loop(top, (void *) PrintSubnetInfo);
1252     FreeQueue(top);
1253     return(DM_NORMAL);
1254 }
1255
1256 /*      Function Name: AddSubnet
1257  *      Description: Creates a new subnet.
1258  *      Arguments: argc, argv - the name of the new subnet is argv[1].
1259  *      Returns: DM_NORMAL.
1260  */
1261
1262 /* ARGSUSED */
1263 int
1264 AddSubnet(argc, argv)
1265 int argc;
1266 char ** argv;
1267 {
1268     char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1269     int stat;
1270 /* 
1271  * Check to see if this subnet already exists. 
1272  */
1273     if (!ValidName(name))
1274         return(DM_NORMAL);
1275
1276     if ( (stat = do_mr_query("get_subnet", 1, &name, 
1277                               NullFunc, NULL)) == MR_SUCCESS) {
1278         Put_message("This subnet already exists.");
1279         return(DM_NORMAL);
1280     }
1281     else if (stat != MR_NO_MATCH) {
1282         com_err(program_name, stat, " in AddSubnet.");
1283         return(DM_NORMAL);
1284     }
1285     if ((args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE)) ==
1286         NULL) {
1287         Put_message("Aborted.");
1288         FreeInfo(info);
1289         return(DM_NORMAL);
1290     }
1291
1292 /*
1293  * Actually create the new Subnet.
1294  */
1295     if ( (stat = do_mr_query("add_subnet", CountArgs(args), 
1296                               args, Scream, NULL)) != 0)
1297         com_err(program_name, stat, " in AddSubnet.");
1298
1299     FreeInfo(info);
1300     return(DM_NORMAL);
1301 }
1302
1303 /*      Function Name: RealUpdateSubnet
1304  *      Description: This function actually performs the subnet update.
1305  *      Arguments: info - all information nesc. for updating the subnet.
1306  *                 junk - an UNUSED boolean.
1307  *      Returns: none.
1308  */
1309
1310 /* ARGSUSED */
1311 static void
1312 RealUpdateSubnet(info, junk)
1313 char ** info;
1314 Bool junk;
1315 {
1316     register int stat;
1317     char ** args = AskMCDInfo(info, SUBNET, TRUE);
1318     if (args == NULL) {
1319         Put_message("Aborted.");
1320         return;
1321     }
1322     if ( (stat = do_mr_query("update_subnet", CountArgs(args), 
1323                               args, Scream, NULL)) != 0)
1324         com_err(program_name, stat, " in UpdateSubnet.");
1325     else
1326         Put_message("Subnet successfully updated.");
1327 }
1328
1329 /*      Function Name: UpdateSubnet
1330  *      Description: This Function Updates a subnet
1331  *      Arguments: name of the subnet in argv[1].
1332  *      Returns: DM_NORMAL.
1333  */
1334
1335 /* ARGSUSED */
1336 int 
1337 UpdateSubnet(argc, argv)
1338 int argc;
1339 char ** argv;
1340 {
1341     struct qelem *top;    
1342     top = GetMCInfo( SUBNET, argv[1], (char *) NULL );
1343     QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet");
1344
1345     FreeQueue(top);
1346     return(DM_NORMAL);
1347 }
1348
1349 /*      Function Name: RealDeleteSubnet
1350  *      Description: Actually performs the subnet deletion.
1351  *      Arguments: info - all information about this subnet.
1352  *                 one_subnet - If true then there was only one subnet in
1353  *                               the queue, and we should confirm.
1354  *      Returns: none.
1355  */
1356
1357 static void
1358 RealDeleteSubnet(info, one_subnet)
1359 char ** info;
1360 Bool one_subnet;
1361 {
1362     register int stat;
1363     char temp_buf[BUFSIZ];
1364     
1365     sprintf(temp_buf, 
1366             "Are you sure the you want to delete the subnet %s (y/n) ?", 
1367             info[C_NAME]);
1368     if (!one_subnet || Confirm(temp_buf)) {
1369         if ( (stat = do_mr_query("delete_subnet", 1,
1370                                  &info[C_NAME], Scream, NULL)) != 0) {
1371             com_err(program_name, stat, " in delete_subnet.");
1372             sprintf(temp_buf, "Subnet %s ** NOT ** deleted.", 
1373                     info[C_NAME]);
1374             Put_message(temp_buf);
1375         }
1376         else {
1377             sprintf(temp_buf, "subnet %s sucesfully deleted.", 
1378                     info[C_NAME]);
1379             Put_message(temp_buf);
1380         }
1381     }
1382 }
1383
1384 /*      Function Name: DeleteSubnet
1385  *      Description: This function removes a subnet from the database.
1386  *      Arguments: argc, argv - the name of the subnet is stored in argv[1].
1387  *      Returns: DM_NORMAL.
1388  */
1389
1390 /* ARGSUSED */
1391 int
1392 DeleteSubnet(argc, argv)
1393 int argc;
1394 char ** argv;
1395 {
1396     struct qelem *top;
1397
1398     top = GetMCInfo( SUBNET, argv[1], (char *) NULL );
1399     QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet");
1400
1401     FreeQueue(top);
1402     return(DM_NORMAL);
1403 }
1404     
1405 /* ---------- Cluster Menu -------- */
1406
1407 /*      Function Name: ShowClusterInfo
1408  *      Description: Gets information about a cluser given its name.
1409  *      Arguments: argc, argc - the name of the cluster in in argv[1].
1410  *      Returns: DM_NORMAL.
1411  */
1412
1413 /* ARGSUSED */
1414 int
1415 ShowClusterInfo(argc, argv)
1416 int argc;
1417 char ** argv;
1418 {
1419     struct qelem *top;
1420
1421     top = GetMCInfo(CLUSTER, argv[1], (char *) NULL);
1422     Loop(top, (void *) PrintClusterInfo);
1423     FreeQueue(top);
1424     return(DM_NORMAL);
1425 }
1426
1427 /*      Function Name: AddCluster
1428  *      Description: Creates a new cluster.
1429  *      Arguments: argc, argv - the name of the new cluster is argv[1].
1430  *      Returns: DM_NORMAL.
1431  */
1432
1433 /* ARGSUSED */
1434 int
1435 AddCluster(argc, argv)
1436 int argc;
1437 char ** argv;
1438 {
1439     char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1440     int stat;
1441 /* 
1442  * Check to see if this cluster already exists. 
1443  */
1444     if (!ValidName(name))
1445         return(DM_NORMAL);
1446
1447     if ( (stat = do_mr_query("get_cluster", 1, &name, 
1448                               NullFunc, NULL)) == MR_SUCCESS) {
1449         Put_message("This cluster already exists.");
1450         return(DM_NORMAL);
1451     }
1452     else if (stat != MR_NO_MATCH) {
1453         com_err(program_name, stat, " in AddCluster.");
1454         return(DM_NORMAL);
1455     }
1456     if ((args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)) ==
1457         NULL) {
1458         Put_message("Aborted.");
1459         FreeInfo(info);
1460         return(DM_NORMAL);
1461     }
1462
1463 /*
1464  * Actually create the new Cluster.
1465  */
1466     if ( (stat = do_mr_query("add_cluster", CountArgs(args), 
1467                               args, Scream, NULL)) != 0)
1468         com_err(program_name, stat, " in AddCluster.");
1469
1470     FreeInfo(info);
1471     return(DM_NORMAL);
1472 }
1473
1474 /*      Function Name: RealUpdateCluster
1475  *      Description: This function actually performs the cluster update.
1476  *      Arguments: info - all information nesc. for updating the cluster.
1477  *                 junk - an UNUSED boolean.
1478  *      Returns: none.
1479  */
1480
1481 /* ARGSUSED */
1482 static void
1483 RealUpdateCluster(info, junk)
1484 char ** info;
1485 Bool junk;
1486 {
1487     register int stat;
1488     char ** args = AskMCDInfo(info, CLUSTER, TRUE);
1489     if (args == NULL) {
1490         Put_message("Aborted.");
1491         return;
1492     }
1493     if ( (stat = do_mr_query("update_cluster", CountArgs(args), 
1494                               args, Scream, NULL)) != 0)
1495         com_err(program_name, stat, " in UpdateCluster.");
1496     else
1497         Put_message("Cluster successfully updated.");
1498 }
1499
1500 /*      Function Name: UpdateCluster
1501  *      Description: This Function Updates a cluster
1502  *      Arguments: name of the cluster in argv[1].
1503  *      Returns: DM_NORMAL.
1504  */
1505
1506 /* ARGSUSED */
1507 int 
1508 UpdateCluster(argc, argv)
1509 int argc;
1510 char ** argv;
1511 {
1512     struct qelem *top;    
1513     top = GetMCInfo( CLUSTER, argv[1], (char *) NULL );
1514     QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
1515
1516     FreeQueue(top);
1517     return(DM_NORMAL);
1518 }
1519
1520 /*      Function Name: CheckAndRemoveMachine
1521  *      Description: This function checks and removes all machines from a
1522  *                   cluster.
1523  *      Arguments: name - name of the cluster.
1524  *                 ask_first - if TRUE, then we will query the user, before
1525  *                             deletion.
1526  *      Returns: SUB_ERROR if all machines not removed.
1527  */
1528
1529 int
1530 CheckAndRemoveMachines(name, ask_first)
1531 char * name;
1532 Bool ask_first;
1533 {
1534     register int stat, ret_value;
1535     Bool delete_it;
1536     char *args[10], temp_buf[BUFSIZ], *ptr;
1537     struct qelem *top, *elem = NULL;
1538     
1539     ret_value = SUB_NORMAL;
1540     args[MAP_MACHINE] = "*";
1541     args[MAP_CLUSTER] = name;
1542     stat = do_mr_query("get_machine_to_cluster_map", 2, args, 
1543                         StoreInfo, (char *)&elem);
1544     if (stat && stat != MR_NO_MATCH) {
1545         com_err(program_name, stat, " in get_machine_to_cluster_map.");
1546         return(DM_NORMAL);
1547     }
1548     if (stat == 0) {
1549         elem = top = QueueTop(elem);
1550         if (ask_first) {
1551             sprintf(temp_buf,
1552                     "The cluster %s has the following machines in it:",
1553                     name);
1554             Put_message(temp_buf);
1555             while (elem != NULL) {
1556                 char **info = (char **) elem->q_data;
1557                 Print(1, &info[MAP_MACHINE], (char *) NULL);
1558                 elem = elem->q_forw;
1559             }
1560             ptr = "Remove ** ALL ** these machines from this cluster?";
1561
1562             if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1563                 delete_it = TRUE;
1564             else {
1565                 Put_message("Aborting...");
1566                 FreeQueue(top);
1567                 return(SUB_ERROR);
1568             }
1569         }
1570         else
1571             delete_it = TRUE;
1572
1573         if (delete_it) {
1574             elem = top;
1575             while (elem != 0) {
1576                 char **info = (char **) elem->q_data;
1577                 if ( (stat = do_mr_query("delete_machine_from_cluster",
1578                                           2, info, Scream, NULL)) != 0) {
1579                     ret_value = SUB_ERROR;
1580                     com_err(program_name, stat, 
1581                             " in delete_machine_from_cluster.");
1582                     sprintf(temp_buf, 
1583                             "Machine %s ** NOT ** removed from cluster %s.",
1584                             info[MAP_MACHINE], info[MAP_CLUSTER]);
1585                     Put_message(temp_buf);
1586                 }
1587                 elem = elem->q_forw;
1588             }
1589         }
1590     }
1591     return(ret_value);
1592 }
1593
1594 /*      Function Name: RealDeleteCluster
1595  *      Description: Actually performs the cluster deletion.
1596  *      Arguments: info - all information about this cluster.
1597  *                 one_cluster - If true then there was only one cluster in
1598  *                               the queue, and we should confirm.
1599  *      Returns: none.
1600  */
1601
1602 static void
1603 RealDeleteCluster(info, one_cluster)
1604 char ** info;
1605 Bool one_cluster;
1606 {
1607     register int stat;
1608     char temp_buf[BUFSIZ];
1609     
1610     sprintf(temp_buf, 
1611             "Are you sure the you want to delete the cluster %s (y/n) ?", 
1612             info[C_NAME]);
1613     if (!one_cluster || Confirm(temp_buf)) {
1614         if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR) {
1615             if ( (stat = do_mr_query("delete_cluster", 1,
1616                                       &info[C_NAME], Scream, NULL)) != 0) {
1617                 com_err(program_name, stat, " in delete_cluster.");
1618                 sprintf(temp_buf, "Cluster %s ** NOT ** deleted.", 
1619                         info[C_NAME]);
1620                 Put_message(temp_buf);
1621             }
1622             else {
1623                 sprintf(temp_buf, "cluster %s sucesfully deleted.", 
1624                         info[C_NAME]);
1625                 Put_message(temp_buf);
1626             }
1627         }
1628     }
1629 }
1630
1631 /*      Function Name: DeleteCluster
1632  *      Description: This function removes a cluster from the database.
1633  *      Arguments: argc, argv - the name of the cluster is stored in argv[1].
1634  *      Returns: DM_NORMAL.
1635  */
1636
1637 /* ARGSUSED */
1638 int
1639 DeleteCluster(argc, argv)
1640 int argc;
1641 char ** argv;
1642 {
1643     struct qelem *top;
1644
1645     top = GetMCInfo( CLUSTER, argv[1], (char *) NULL );
1646     QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
1647
1648     FreeQueue(top);
1649     return(DM_NORMAL);
1650 }
1651     
1652 /* ----------- Cluster Data Menu -------------- */
1653
1654 /*      Function Name: ShowClusterData
1655  *      Description: This function shows the services for one cluster.
1656  *      Arguments: argc, argv - The name of the cluster is argv[1].
1657  *                              The label of the data in argv[2].
1658  *      Returns: DM_NORMAL.
1659  */
1660
1661 /* ARGSUSED */
1662 int
1663 ShowClusterData(argc, argv)
1664 int argc; 
1665 char ** argv; 
1666
1667     struct qelem *elem, *top;
1668     char **info;
1669
1670     top = elem = GetMCInfo(DATA, argv[1], argv[2]);
1671     while (elem != NULL) {
1672         info = (char **) elem->q_data;
1673         PrintClusterData(info);
1674         elem = elem->q_forw;
1675     }
1676     FreeQueue(top);
1677     return(DM_NORMAL);
1678 }
1679
1680 /*      Function Name: AddClusterData
1681  *      Description: This function adds some data to the cluster.
1682  *      Arguments: argv, argc:   argv[1] - the name of the cluster.
1683  *                               argv[2] - the label of the data.
1684  *                               argv[3] - the data.
1685  *      Returns: DM_NORMAL.
1686  */
1687
1688 /* ARGSUSED */
1689 int
1690 AddClusterData(argc, argv)
1691 int argc; 
1692 char ** argv; 
1693
1694     int stat;
1695
1696     if( (stat = do_mr_query("add_cluster_data", 3, argv + 1,
1697                              Scream, (char *) NULL)) != 0)
1698         com_err(program_name, stat, " in AddClusterData.");
1699     return(DM_NORMAL);
1700 }
1701
1702 /*      Function Name: RealRemoveClusterData
1703  *      Description: actually removes the cluster data.
1704  *      Arguments: info - all info necessary to remove the cluster, in an array
1705  *                        of strings.
1706  *                 one_item - if true then the queue has only one elem and we
1707  *                            should confirm.
1708  *      Returns: none.
1709  */
1710
1711 static void
1712 RealRemoveClusterData(info, one_item)
1713 char ** info;
1714 Bool one_item;
1715 {
1716     register int stat;
1717     char * temp_ptr;
1718
1719     Put_message(" ");
1720     temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1721     PrintClusterData(info);
1722     if (!one_item || Confirm(temp_ptr)) {
1723         if( (stat = do_mr_query("delete_cluster_data", 3, info,
1724                                  Scream, (char *) NULL)) != 0) {
1725             com_err(program_name, stat, " in DeleteClusterData.");
1726             Put_message("Data not removed.");
1727         }
1728         else
1729             Put_message("Removal sucessful.");
1730     }
1731 }
1732
1733 /*      Function Name: RemoveClusterData
1734  *      Description: This function removes data on a given cluster.
1735  *      Arguments: argv, argc:   argv[1] - the name of the cluster.
1736  *                               argv[2] - the label of the data.
1737  *                               argv[3] - the data.
1738  *      Returns: DM_NORMAL.
1739  */
1740
1741 /* ARGSUSED */
1742 int 
1743 RemoveClusterData(argc, argv)
1744 int argc; 
1745 char ** argv; 
1746 {
1747     struct qelem *top;
1748
1749     top = GetMCInfo(DATA, argv[1], argv[2]);
1750     QueryLoop(top, PrintClusterData, RealRemoveClusterData, 
1751               "Remove data from cluster");
1752
1753     FreeQueue(top);
1754     return(DM_NORMAL);
1755 }
1756
1757 /*      Function Name: MachineToClusterMap
1758  *      Description: This Retrieves the mapping between machine and cluster
1759  *      Arguments: argc, argv - argv[1] -> machine name or wildcard.
1760  *                              argv[2] -> cluster name or wildcard.
1761  *      Returns: none.
1762  */
1763
1764 /* ARGSUSED */
1765 int 
1766 MachineToClusterMap(argc,argv)
1767 int argc;
1768 char **argv;
1769 {
1770     struct qelem *elem, *top;
1771     char *tmpname, temp_buf[256];
1772
1773     tmpname = canonicalize_hostname(strsave(argv[1]));
1774     if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"') {
1775         sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1776                 argv[1], tmpname);
1777         Put_message(temp_buf);
1778     }
1779     top = elem = GetMCInfo(MAP, tmpname, argv[2]);
1780   
1781     Put_message("");            /* blank line on screen */
1782     while (elem != NULL) {
1783         char ** info = (char **) elem->q_data;
1784         PrintMCMap(info);
1785         elem = elem->q_forw;
1786     }
1787
1788     FreeQueue(top);
1789     free(tmpname);
1790     return(DM_NORMAL);
1791 }
This page took 2.614854 seconds and 5 git commands to generate.