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