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