]> andersk Git - moira.git/blob - clients/moira/cluster.c
Change strings.h to string.h (we weren't using any BSD-isms anyway!)
[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             free(info[8]);
551             info[8] = info[M_SUBNET];
552             info[9] = info[M_ADDR];
553             info[10] = info[M_OWNER_TYPE];
554             info[11] = info[M_OWNER_NAME];
555             info[12] = info[M_ACOMMENT];
556             info[13] = info[M_OCOMMENT];
557
558         if(name)
559           if (GetValueFromUser("Machine's network (or 'none')", &info[8])
560             == SUB_ERROR)
561             return(NULL);
562         if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')",
563                              &info[9]) == SUB_ERROR)
564           return(NULL);
565         if (GetTypeFromUser("Machine's owner type", "ace_type", &info[10]) ==
566             SUB_ERROR)
567           return(NULL);
568         if (strcmp(info[10], "NONE") &&
569             GetValueFromUser("Owner's Name", &info[11]) == SUB_ERROR)
570           return(NULL);
571         if (GetValueFromUser("Administrative comment", &info[12]) == SUB_ERROR)
572           return(NULL);
573         if (GetValueFromUser("Operational comment", &info[13]) == SUB_ERROR)
574           return(NULL);
575         info[14] = NULL;
576         FreeAndClear(&info[15], TRUE);
577         FreeAndClear(&info[16], TRUE);
578         break;
579     case SUBNET:
580         if (GetValueFromUser("Network description", &info[SN_DESC]) == SUB_ERROR)
581           return(NULL);
582         if (GetAddressFromUser("Network address", &info[SN_ADDRESS]) == SUB_ERROR)
583           return(NULL);
584         if (GetAddressFromUser("Network mask", &info[SN_MASK]) == SUB_ERROR)
585           return(NULL);
586         if (atoi(info[SN_LOW]) == ntohl(inet_addr(S_DEFAULT_LOW))) {
587             struct in_addr low;
588             unsigned long mask, addr;
589
590             addr = atoi(info[SN_ADDRESS]);
591             mask = atoi(info[SN_MASK]);
592             low.s_addr = atoi(info[SN_LOW]);
593             low.s_addr = (low.s_addr & ~mask) | (addr & mask);
594             free(info[SN_LOW]);
595             sprintf(temp_buf, "%d", low.s_addr);
596             info[SN_LOW] = strsave(temp_buf);
597         }
598         if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) == SUB_ERROR)
599           return(NULL);
600         if (atoi(info[SN_HIGH]) == ntohl(inet_addr(S_DEFAULT_HIGH))) {
601             struct in_addr high;
602             unsigned long mask, addr;
603
604             addr = atoi(info[SN_ADDRESS]);
605             mask = atoi(info[SN_MASK]);
606             high.s_addr = atoi(info[SN_HIGH]);
607             high.s_addr = (high.s_addr & ~mask) | (addr & mask);
608             free(info[SN_HIGH]);
609             sprintf(temp_buf, "%d", high.s_addr);
610             info[SN_HIGH] = strsave(temp_buf);
611         }
612         if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) == SUB_ERROR)
613           return(NULL);
614         if (GetValueFromUser("Hostname prefix", &info[SN_PREFIX]) == SUB_ERROR)
615           return(NULL);
616         if (GetTypeFromUser("Owner type", "ace_type", &info[SN_ACE_TYPE]) == SUB_ERROR)
617           return(NULL);
618         if (strcmp(info[SN_ACE_TYPE], "NONE") &&
619             GetValueFromUser("Owner name", &info[SN_ACE_NAME]) == SUB_ERROR)
620           return(NULL);
621         FreeAndClear(&info[SN_MODTIME], TRUE);
622         FreeAndClear(&info[SN_MODBY], TRUE);
623         FreeAndClear(&info[SN_MODWITH], TRUE);
624         break;
625     case CLUSTER:
626         if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) ==
627             SUB_ERROR)
628           return(NULL);
629         if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) ==
630             SUB_ERROR)
631           return(NULL);
632         FreeAndClear(&info[C_MODTIME], TRUE);
633         FreeAndClear(&info[C_MODBY], TRUE);
634         FreeAndClear(&info[C_MODWITH], TRUE);
635         break;
636     case DATA:
637         if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) ==
638             SUB_ERROR)
639           return(NULL);
640         if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR)
641           return(NULL);
642         break;
643     }
644
645 /* 
646  * Slide the newname into the #2 slot, this screws up all future references 
647  * to this list.
648  */
649     if (name)                   
650         SlipInNewName(info, newname);
651
652     return(info);
653 }
654
655 /* -----------  Machine Menu ----------- */
656
657 /*      Function Name: ShowMachineInfo
658  *      Description: This function shows the information about a machine.
659  *      Arguments: argc, argv - the name of the machine in argv[1].
660  *      Returns: DM_NORMAL.
661  */
662
663 /* ARGSUSED */
664 int
665 ShowMachineInfo(argc, argv)
666 int argc;
667 char **argv;
668 {
669     struct qelem *top;
670     char *tmpname;
671
672     tmpname = canonicalize_hostname(strsave(argv[1]));
673     top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
674     Loop(top, ( (void *) PrintMachInfo) );
675     FreeQueue(top);
676     return(DM_NORMAL);
677 }
678
679 /*      Function Name: ShowMachineQuery
680  *      Description: This function shows the information about a machine.
681  *              or group of machines, which may be selected through a
682  *              number of criteria. 
683  *      Arguments: argc, argv - the name of the machine in argv[1],
684  *              the address of the machine in argv[2],
685  *              the location of the machine in argv[3],
686  *              and the contact name in argv[4].
687  *           any of these may be wildcards.
688  *      Returns: DM_NORMAL.
689  */
690
691 /* ARGSUSED */
692 int
693 ShowMachineQuery(argc, argv)
694 int argc;
695 char **argv;
696 {
697     int stat;
698     struct qelem *top, *elem = NULL;
699     char *args[5];
700
701     if (!strcmp(argv[1], "") && !strcmp(argv[2], "") &&
702         !strcmp(argv[3], "") && !strcmp(argv[4], "")) {
703         Put_message("You must specify at least one parameter of the query.");
704         return(DM_NORMAL);
705     }
706
707     if (*argv[1])
708       args[0] = canonicalize_hostname(strsave(argv[1]));
709     else
710       args[0] = "*";
711     if (*argv[2])
712       args[1] = argv[2];
713     else
714       args[1] = "*";
715     if (*argv[3])
716       args[2] = argv[3];
717     else
718       args[2] = "*";
719     if (*argv[4])
720       args[3] = argv[4];
721     else
722       args[3] = "*";
723
724     if ((stat = do_mr_query("get_host", 4, args, StoreInfo,
725                             (char *)&elem)) != 0) {
726         if (stat == MR_NO_MATCH)
727           Put_message("No machine(s) found matching query in the database.");
728         else
729           com_err(program_name, stat, " in get_machine.");
730         return(DM_NORMAL);
731     }
732     top = QueueTop(elem);
733     Loop(top, ( (void *) PrintMachInfo) );
734     FreeQueue(top);
735     return(DM_NORMAL);
736 }
737
738 /*      Function Name: AddMachine
739  *      Description: This function adds a new machine to the database.
740  *      Arguments: argc, argv - the name of the network in argv[1].
741  *      Returns: DM_NORMAL.
742  */
743
744 /* ARGSUSED */
745 int
746 AddMachine(argc, argv)
747 int argc;
748 char **argv;
749 {
750     char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
751     char **rinfo;
752     struct qelem * elem = NULL;
753     int stat;
754
755     if (!ValidName(argv[1]))    /* Checks for wildcards. */
756         return(DM_NORMAL);
757
758     /* 
759      * get the network record
760      */
761
762     if (strcasecmp(argv[1], "none") &&
763             (stat = do_mr_query("get_subnet", 1, &argv[1],
764                              StoreInfo, (char *)&elem)) != 0) {
765         if (stat == MR_NO_MATCH) {
766             char buf[128];
767             sprintf(buf, "Network '%s' is not in the database.", argv[1]);
768             Put_message(buf);
769         } else
770             com_err(program_name, stat, " in get_subnet.");
771         return(DM_NORMAL);
772      } 
773       
774 /* 
775  * Check to see if this machine already exists. 
776  */
777
778     name = strsave(""); /* want to put prefix here */
779     if (GetValueFromUser("Machine name", &name) == SUB_ERROR)
780           return(NULL);
781
782     name =  canonicalize_hostname(strsave(name));
783
784     xargs[0] = name;
785     xargs[1] = xargs[2] = xargs[3] = "*";
786     if ( (stat = do_mr_query("get_host", 4, xargs, NullFunc, NULL)) == 0) {
787         sprintf(buf, "The machine '%s' already exists.", name);
788         Put_message(buf);
789         free(name);
790         return(DM_NORMAL);
791     }
792     else if (stat != MR_NO_MATCH) {
793         com_err(program_name, stat,
794                 " while checking machine '%s' in AddMachine.", name);
795         free(name);
796         return(DM_NORMAL);
797     }
798     rinfo = SetMachineDefaults(info, name);
799     rinfo[M_SUBNET] = argv[1];
800     if ((args = AskMCDInfo(rinfo, MACHINE, FALSE)) == NULL) {
801         Put_message("Aborted.");
802         return(DM_NORMAL);
803     }
804
805 /*
806  * Actually create the new Machine.
807  */
808     
809     if ( (stat = do_mr_query("add_host", CountArgs(args), 
810                               args, Scream, NULL)) != 0)
811         com_err(program_name, stat, " in AddMachine.");
812
813     FreeInfo(info);
814     free(name);
815     return(DM_NORMAL);
816 }
817
818 /*      Function Name: RealUpdateMachine
819  *      Description: Performs the actual update of the machine data.
820  *      Arguments: info - the information on the machine to update.
821  *                 junk - an UNUSED Boolean.
822  *      Returns: none.
823  */
824
825 /* ARGSUSED */
826 static void
827 RealUpdateMachine(info, junk)
828 char ** info;
829 Bool junk;
830 {
831     register int stat;
832     char ** args = AskMCDInfo(info, MACHINE, TRUE);
833     if (args == NULL) {
834         Put_message("Aborted.");
835         return;
836     }
837     if ( (stat = do_mr_query("update_host", CountArgs(args), 
838                               args, Scream, NULL)) != 0)
839         com_err(program_name, stat, " in UpdateMachine.");
840     else
841         Put_message("Machine sucessfully updated.");
842 }
843
844 /*      Function Name: UpdateMachine
845  *      Description: This function adds a new machine to the database.
846  *      Arguments: argc, argv - the name of the machine in argv[1].
847  *      Returns: DM_NORMAL.
848  */
849
850 /* ARGSUSED */
851 int
852 UpdateMachine(argc, argv)
853 int argc;
854 char **argv;
855 {
856     struct qelem *top;
857     char *tmpname;
858
859     tmpname = canonicalize_hostname(strsave(argv[1]));
860     top = GetMCInfo( MACHINE,  tmpname, (char *) NULL);
861     QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
862
863     FreeQueue(top);
864     free(tmpname);
865     return(DM_NORMAL);
866 }
867
868 /*      Function Name: CheckAndRemoveFromCluster
869  *      Description: This func tests to see if a machine is in a cluster.
870  *                   and if so then removes it
871  *      Arguments: name - name of the machine (already Canonocalized).
872  *                 ask_user- query the user before removing if from clusters?
873  *      Returns: MR_ERROR if machine left in a cluster, or mr_error.
874  */
875
876 int 
877 CheckAndRemoveFromCluster(name, ask_user)
878 char * name;
879 Bool ask_user;
880 {
881     register int stat, ret_value;
882     Bool delete_it;
883     char *args[10], temp_buf[BUFSIZ], *ptr;
884     struct qelem *top, *elem = NULL;
885     
886     ret_value = SUB_NORMAL;     /* initialize ret_value. */
887     args[0] = name;
888     args[1] = "*";
889     stat = do_mr_query("get_machine_to_cluster_map", 2, args, 
890                         StoreInfo, (char *)&elem);
891     if (stat && stat != MR_NO_MATCH) {
892         com_err(program_name, stat, " in get_machine_to_cluster_map.");
893         return(DM_NORMAL);
894     }
895     if (stat == MR_SUCCESS) {
896         elem = top = QueueTop(elem);
897         if (ask_user) {
898             sprintf(temp_buf, "%s is assigned to the following clusters.",
899                     name);
900             Put_message(temp_buf);
901             Loop(top, (void *) PrintMCMap);
902             ptr = "Remove this machine from ** ALL ** these clusters?";
903             if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
904                 delete_it = TRUE;
905             else {
906                 Put_message("Aborting...");
907                 FreeQueue(top);
908                 return(SUB_ERROR);
909             }
910         }
911         else
912             delete_it = TRUE;
913
914         if (delete_it) {
915             while (elem != NULL) {
916                 char **info = (char **) elem->q_data;
917                 if ( (stat = do_mr_query( "delete_machine_from_cluster",
918                                           2, info, Scream, NULL)) != 0) {
919                     ret_value = SUB_ERROR;
920                     com_err(program_name, stat, 
921                             " in delete_machine_from_cluster.");
922                     sprintf(temp_buf, 
923                             "Machine %s ** NOT ** removed from cluster %s.",
924                             info[MAP_MACHINE], info[MAP_CLUSTER]);
925                     Put_message(temp_buf);
926                 }
927                 elem = elem->q_forw;
928             }
929         }
930     }
931     return(ret_value);
932 }
933
934 /*      Function Name: RealDeleteMachine
935  *      Description: Actually Deletes the Machine.
936  *      Arguments: info - nescessary information stored as an array of char *'s
937  *                 one_machine - a boolean, true if there is only one item in
938  *                               the query.
939  *      Returns: none.
940  */
941
942 static void
943 RealDeleteMachine(info, one_machine)
944 char ** info;
945 Bool one_machine;
946 {
947     register int stat;
948     char temp_buf[BUFSIZ];
949
950     sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ",
951             info[M_NAME]);
952     if(!one_machine || Confirm(temp_buf)) {
953         if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR) {
954             if ( (stat = do_mr_query("delete_host", 1,
955                                       &info[M_NAME], Scream, NULL)) != 0) {
956                 com_err(program_name, stat, " in DeleteMachine.");
957                 sprintf(temp_buf, "%s ** NOT ** deleted.", 
958                         info[M_NAME]);
959                 Put_message(temp_buf);
960             }
961             else {
962                 sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
963                 Put_message(temp_buf);
964             }
965         }
966     }
967 }
968
969 /*      Function Name: DeleteMachine
970  *      Description: This function removes a machine from the data base.
971  *      Arguments: argc, argv - the machines name int argv[1].
972  *      Returns: DM_NORMAL.
973  */
974
975 /* Perhaps we should remove the cluster if it has no machine now. */
976
977 /* ARGSUSED */
978 int
979 DeleteMachine(argc, argv)
980 int argc;
981 char **argv;
982 {
983     struct qelem *top;
984     char *tmpname;
985
986     tmpname = canonicalize_hostname(strsave(argv[1]));
987     top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
988     QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
989     FreeQueue(top);
990     free(tmpname);
991     return(DM_NORMAL);
992 }
993
994
995 char *partial_canonicalize_hostname(s)
996 char *s;
997 {
998     char buf[256], *cp;
999     static char *def_domain = NULL;
1000     struct hostent *hp;
1001 #ifdef POSIX
1002     struct utsname name;
1003 #endif
1004
1005     if (!def_domain) {
1006 #ifdef POSIX
1007         (void) uname(&name);
1008         strncpy(buf, name.nodename, sizeof(buf));
1009 #else
1010         gethostname(buf, sizeof(buf));
1011 #endif
1012         hp = gethostbyname(buf);
1013         cp = (char *) strchr(hp->h_name, '.');
1014         if (cp)
1015           def_domain = strsave(++cp);
1016         else
1017           def_domain = "";
1018     }
1019
1020     if (strchr(s, '.') || strchr(s, '*'))
1021       return(s);
1022     sprintf(buf, "%s.%s", s, def_domain);
1023     free(s);
1024     return(strsave(buf));
1025 }
1026
1027
1028 /*      Function Name: ShowCname
1029  *      Description: This function shows machine aliases
1030  *      Arguments: argc, argv - the alias argv[1], the real name in argv[2]
1031  *      Returns: DM_NORMAL.
1032  */
1033
1034 /* ARGSUSED */
1035 int
1036 ShowCname(argc, argv)
1037 int argc;
1038 char **argv;
1039 {
1040     struct qelem *top;
1041     char *tmpalias, *tmpname;
1042
1043     tmpalias = partial_canonicalize_hostname(strsave(argv[1]));
1044     tmpname = canonicalize_hostname(strsave(argv[2]));
1045     top = GetMCInfo(CNAME, tmpalias, tmpname);
1046     Put_message("");            /* blank line on screen */
1047     Loop(top, ( (void *) PrintCname) );
1048     FreeQueue(top);
1049     return(DM_NORMAL);
1050 }
1051
1052
1053 /* ARGSUSED */
1054 int 
1055 AddCname(argc, argv)
1056 int argc;
1057 char ** argv;
1058 {
1059     int stat;
1060     char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1061     Bool add_it, one_machine, one_cluster;
1062     struct qelem * melem, *mtop, *celem, *ctop;
1063
1064     args[0] = partial_canonicalize_hostname(strsave(argv[1]));
1065     args[1] = canonicalize_hostname(strsave(argv[2]));
1066     stat = do_mr_query("add_hostalias", 2, args, Scream, NULL);
1067     switch (stat) {
1068     case MR_SUCCESS:
1069         break;
1070     case MR_EXISTS:
1071         Put_message("That alias name is already in use.");
1072         break;
1073     case MR_PERM:
1074         Put_message("Permission denied.  (Regular users can only add two aliases to a host.");
1075         break;
1076     default:
1077         com_err(program_name, stat, " in add_hostalias");
1078     }
1079     return(DM_NORMAL);
1080 }
1081
1082
1083 /* ARGSUSED */
1084 int 
1085 DeleteCname(argc, argv)
1086 int argc;
1087 char ** argv;
1088 {
1089     int stat;
1090     char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1091     Bool add_it, one_machine, one_cluster;
1092     struct qelem * melem, *mtop, *celem, *ctop;
1093
1094     args[0] = partial_canonicalize_hostname(strsave(argv[1]));
1095     args[1] = canonicalize_hostname(strsave(argv[2]));
1096     stat = do_mr_query("delete_hostalias", 2, args, Scream, NULL);
1097     if (stat)
1098       com_err(program_name, stat, " in delete_hostalias");
1099     return(DM_NORMAL);
1100 }
1101
1102
1103 /*      Function Name: AddMachineToCluster
1104  *      Description: This function adds a machine to a cluster
1105  *      Arguments: argc, argv - The machine name is argv[1].
1106  *                              The cluster name in argv[2].
1107  *      Returns: DM_NORMAL.
1108  */
1109
1110 /* ARGSUSED */
1111 int 
1112 AddMachineToCluster(argc, argv)
1113 int argc;
1114 char ** argv;
1115 {
1116     int stat;
1117     char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1118     Bool add_it, one_machine, one_cluster;
1119     struct qelem * melem, *mtop, *celem, *ctop;
1120
1121     machine = canonicalize_hostname(strsave(argv[1]));
1122     if (strcasecmp(machine, argv[1]) && *argv[1] != '"') {
1123         sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1124                 argv[1], machine);
1125         Put_message(temp_buf);
1126     }
1127     cluster = argv[2];
1128
1129     celem = ctop = GetMCInfo(CLUSTER,  cluster, (char *) NULL);
1130     melem = mtop = GetMCInfo(MACHINE,  machine, (char *) NULL);
1131     free(machine);
1132
1133     one_machine = (QueueCount(mtop) == 1);
1134     one_cluster = (QueueCount(ctop) == 1);
1135
1136     /* No good way to use QueryLoop() here, sigh */
1137
1138     while (melem != NULL) {
1139         char ** minfo = (char **) melem->q_data;
1140         while (celem != NULL) {
1141             char ** cinfo = (char **) celem->q_data;
1142             if (one_machine && one_cluster) 
1143                 add_it = TRUE;
1144             else {
1145                 sprintf(temp_buf,"Add machine %s to cluster %s (y/n/q) ?",
1146                         minfo[M_NAME], cinfo[C_NAME]);
1147                 switch (YesNoQuitQuestion(temp_buf, FALSE)) {
1148                 case TRUE:
1149                     add_it = TRUE;
1150                     break;
1151                 case FALSE:
1152                     add_it = FALSE;
1153                     break;
1154                 default:
1155                     Put_message("Aborting...");
1156                     FreeQueue(ctop);
1157                     FreeQueue(mtop);
1158                     return(DM_NORMAL);
1159                 }
1160             }
1161             if (add_it) {
1162                 args[0] = minfo[M_NAME];
1163                 args[1] = cinfo[C_NAME];
1164                 stat = do_mr_query("add_machine_to_cluster", 2, args,
1165                                     Scream, NULL);
1166                 switch (stat) {
1167                 case MR_SUCCESS:
1168                     break;
1169                 case MR_EXISTS:
1170                     sprintf(temp_buf, "%s is already in cluster %s",
1171                             minfo[M_NAME], cinfo[C_NAME]);
1172                     Put_message(temp_buf);
1173                     break;
1174                 default:
1175                     com_err(program_name, stat, " in AddMachineToCluster.");
1176                     break;
1177                 }
1178             }
1179             celem = celem->q_forw;
1180         }
1181         celem = ctop;           /* reset cluster element. */
1182         melem = melem->q_forw;
1183     }
1184     FreeQueue(ctop);
1185     FreeQueue(mtop);                
1186     return(DM_NORMAL);
1187 }
1188
1189 /*      Function Name: RealRemoveMachineFromCluster
1190  *      Description: This function actually removes the machine from its 
1191  *                   cluster.
1192  *      Arguments: info - all information nescessary to perform the removal.
1193  *                 one_map - True if there is only one case, and we should
1194  *                           confirm.
1195  *      Returns: none.
1196  */
1197
1198 static void
1199 RealRemoveMachineFromCluster(info, one_map)
1200 char ** info;
1201 Bool one_map;
1202 {
1203     char temp_buf[BUFSIZ];
1204     register int stat;
1205
1206     sprintf(temp_buf, "Remove %s from the cluster %s", 
1207             info[MAP_MACHINE], info[MAP_CLUSTER]);
1208     if (!one_map || Confirm(temp_buf)) {
1209         if ( (stat = do_mr_query("delete_machine_from_cluster", 2, 
1210                                   info, Scream, NULL)) != 0 )
1211             com_err(program_name, stat, " in delete_machine_from_cluster");
1212         else {
1213             sprintf(temp_buf, "%s has been removed from the cluster %s.",
1214                     info[MAP_MACHINE], info[MAP_CLUSTER]);
1215             Put_message(temp_buf);
1216         }
1217     }
1218     else
1219         Put_message("Machine not removed.");
1220 }
1221
1222 /*      Function Name: RemoveMachineFromCluster
1223  *      Description: Removes this machine form a specific cluster.
1224  *      Arguments: argc, argv - Name of machine in argv[1].
1225  *                              Name of cluster in argv[2].
1226  *      Returns: none.
1227  */
1228
1229 /* ARGSUSED */
1230 int
1231 RemoveMachineFromCluster(argc, argv)
1232 int argc;
1233 char ** argv;
1234 {
1235     struct qelem *elem = NULL;
1236     char buf[BUFSIZ], * args[10];
1237     register int stat;
1238
1239     args[MAP_MACHINE] = canonicalize_hostname(strsave(argv[1]));
1240     if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"') {
1241         sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
1242                 argv[1], args[MAP_MACHINE]);
1243         Put_message(buf);
1244     }
1245     args[MAP_CLUSTER] = argv[2];
1246     args[MAP_END] = NULL;
1247
1248     stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
1249                         StoreInfo, (char *)&elem);
1250     if (stat == MR_NO_MATCH) {
1251         sprintf(buf, "The machine %s is not is the cluster %s.",
1252                 args[MAP_MACHINE], args[MAP_CLUSTER]);
1253         Put_message(buf);
1254         free(args[MAP_MACHINE]);
1255         return(DM_NORMAL);
1256     }
1257     if (stat != MR_SUCCESS)
1258         com_err(program_name, stat, " in delete_machine_from_cluster");
1259
1260     elem = QueueTop(elem);
1261     QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster,
1262               "Remove this machine from this cluster");
1263
1264     FreeQueue(elem);
1265     free(args[MAP_MACHINE]);
1266     return(DM_NORMAL);
1267 }
1268
1269 /* ---------- Subnet Menu -------- */
1270
1271 /*      Function Name: ShowSubnetInfo
1272  *      Description: Gets information about a subnet given its name.
1273  *      Arguments: argc, argc - the name of the subnet in in argv[1].
1274  *      Returns: DM_NORMAL.
1275  */
1276
1277 /* ARGSUSED */
1278 int
1279 ShowSubnetInfo(argc, argv)
1280 int argc;
1281 char ** argv;
1282 {
1283     struct qelem *top;
1284
1285     top = GetMCInfo(SUBNET, argv[1], (char *) NULL);
1286     Loop(top, (void *) PrintSubnetInfo);
1287     FreeQueue(top);
1288     return(DM_NORMAL);
1289 }
1290
1291 /*      Function Name: AddSubnet
1292  *      Description: Creates a new subnet.
1293  *      Arguments: argc, argv - the name of the new subnet is argv[1].
1294  *      Returns: DM_NORMAL.
1295  */
1296
1297 /* ARGSUSED */
1298 int
1299 AddSubnet(argc, argv)
1300 int argc;
1301 char ** argv;
1302 {
1303     char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1304     int stat;
1305 /* 
1306  * Check to see if this subnet already exists. 
1307  */
1308     if (!ValidName(name))
1309         return(DM_NORMAL);
1310
1311     if ( (stat = do_mr_query("get_subnet", 1, &name, 
1312                               NullFunc, NULL)) == MR_SUCCESS) {
1313         Put_message("This subnet already exists.");
1314         return(DM_NORMAL);
1315     }
1316     else if (stat != MR_NO_MATCH) {
1317         com_err(program_name, stat, " in AddSubnet.");
1318         return(DM_NORMAL);
1319     }
1320     if ((args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE)) ==
1321         NULL) {
1322         Put_message("Aborted.");
1323         FreeInfo(info);
1324         return(DM_NORMAL);
1325     }
1326
1327 /*
1328  * Actually create the new Subnet.
1329  */
1330     if ( (stat = do_mr_query("add_subnet", CountArgs(args), 
1331                               args, Scream, NULL)) != 0)
1332         com_err(program_name, stat, " in AddSubnet.");
1333
1334     FreeInfo(info);
1335     return(DM_NORMAL);
1336 }
1337
1338 /*      Function Name: RealUpdateSubnet
1339  *      Description: This function actually performs the subnet update.
1340  *      Arguments: info - all information nesc. for updating the subnet.
1341  *                 junk - an UNUSED boolean.
1342  *      Returns: none.
1343  */
1344
1345 /* ARGSUSED */
1346 static void
1347 RealUpdateSubnet(info, junk)
1348 char ** info;
1349 Bool junk;
1350 {
1351     register int stat;
1352     char ** args = AskMCDInfo(info, SUBNET, TRUE);
1353     if (args == NULL) {
1354         Put_message("Aborted.");
1355         return;
1356     }
1357     if ( (stat = do_mr_query("update_subnet", CountArgs(args), 
1358                               args, Scream, NULL)) != 0)
1359         com_err(program_name, stat, " in UpdateSubnet.");
1360     else
1361         Put_message("Subnet successfully updated.");
1362 }
1363
1364 /*      Function Name: UpdateSubnet
1365  *      Description: This Function Updates a subnet
1366  *      Arguments: name of the subnet in argv[1].
1367  *      Returns: DM_NORMAL.
1368  */
1369
1370 /* ARGSUSED */
1371 int 
1372 UpdateSubnet(argc, argv)
1373 int argc;
1374 char ** argv;
1375 {
1376     struct qelem *top;    
1377     top = GetMCInfo( SUBNET, argv[1], (char *) NULL );
1378     QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet");
1379
1380     FreeQueue(top);
1381     return(DM_NORMAL);
1382 }
1383
1384 /*      Function Name: RealDeleteSubnet
1385  *      Description: Actually performs the subnet deletion.
1386  *      Arguments: info - all information about this subnet.
1387  *                 one_subnet - If true then there was only one subnet in
1388  *                               the queue, and we should confirm.
1389  *      Returns: none.
1390  */
1391
1392 static void
1393 RealDeleteSubnet(info, one_subnet)
1394 char ** info;
1395 Bool one_subnet;
1396 {
1397     register int stat;
1398     char temp_buf[BUFSIZ];
1399     
1400     sprintf(temp_buf, 
1401             "Are you sure the you want to delete the subnet %s (y/n) ?", 
1402             info[C_NAME]);
1403     if (!one_subnet || Confirm(temp_buf)) {
1404         if ( (stat = do_mr_query("delete_subnet", 1,
1405                                  &info[C_NAME], Scream, NULL)) != 0) {
1406             com_err(program_name, stat, " in delete_subnet.");
1407             sprintf(temp_buf, "Subnet %s ** NOT ** deleted.", 
1408                     info[C_NAME]);
1409             Put_message(temp_buf);
1410         }
1411         else {
1412             sprintf(temp_buf, "subnet %s sucesfully deleted.", 
1413                     info[C_NAME]);
1414             Put_message(temp_buf);
1415         }
1416     }
1417 }
1418
1419 /*      Function Name: DeleteSubnet
1420  *      Description: This function removes a subnet from the database.
1421  *      Arguments: argc, argv - the name of the subnet is stored in argv[1].
1422  *      Returns: DM_NORMAL.
1423  */
1424
1425 /* ARGSUSED */
1426 int
1427 DeleteSubnet(argc, argv)
1428 int argc;
1429 char ** argv;
1430 {
1431     struct qelem *top;
1432
1433     top = GetMCInfo( SUBNET, argv[1], (char *) NULL );
1434     QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet");
1435
1436     FreeQueue(top);
1437     return(DM_NORMAL);
1438 }
1439     
1440 /* ---------- Cluster Menu -------- */
1441
1442 /*      Function Name: ShowClusterInfo
1443  *      Description: Gets information about a cluser given its name.
1444  *      Arguments: argc, argc - the name of the cluster in in argv[1].
1445  *      Returns: DM_NORMAL.
1446  */
1447
1448 /* ARGSUSED */
1449 int
1450 ShowClusterInfo(argc, argv)
1451 int argc;
1452 char ** argv;
1453 {
1454     struct qelem *top;
1455
1456     top = GetMCInfo(CLUSTER, argv[1], (char *) NULL);
1457     Loop(top, (void *) PrintClusterInfo);
1458     FreeQueue(top);
1459     return(DM_NORMAL);
1460 }
1461
1462 /*      Function Name: AddCluster
1463  *      Description: Creates a new cluster.
1464  *      Arguments: argc, argv - the name of the new cluster is argv[1].
1465  *      Returns: DM_NORMAL.
1466  */
1467
1468 /* ARGSUSED */
1469 int
1470 AddCluster(argc, argv)
1471 int argc;
1472 char ** argv;
1473 {
1474     char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1475     int stat;
1476 /* 
1477  * Check to see if this cluster already exists. 
1478  */
1479     if (!ValidName(name))
1480         return(DM_NORMAL);
1481
1482     if ( (stat = do_mr_query("get_cluster", 1, &name, 
1483                               NullFunc, NULL)) == MR_SUCCESS) {
1484         Put_message("This cluster already exists.");
1485         return(DM_NORMAL);
1486     }
1487     else if (stat != MR_NO_MATCH) {
1488         com_err(program_name, stat, " in AddCluster.");
1489         return(DM_NORMAL);
1490     }
1491     if ((args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)) ==
1492         NULL) {
1493         Put_message("Aborted.");
1494         FreeInfo(info);
1495         return(DM_NORMAL);
1496     }
1497
1498 /*
1499  * Actually create the new Cluster.
1500  */
1501     if ( (stat = do_mr_query("add_cluster", CountArgs(args), 
1502                               args, Scream, NULL)) != 0)
1503         com_err(program_name, stat, " in AddCluster.");
1504
1505     FreeInfo(info);
1506     return(DM_NORMAL);
1507 }
1508
1509 /*      Function Name: RealUpdateCluster
1510  *      Description: This function actually performs the cluster update.
1511  *      Arguments: info - all information nesc. for updating the cluster.
1512  *                 junk - an UNUSED boolean.
1513  *      Returns: none.
1514  */
1515
1516 /* ARGSUSED */
1517 static void
1518 RealUpdateCluster(info, junk)
1519 char ** info;
1520 Bool junk;
1521 {
1522     register int stat;
1523     char ** args = AskMCDInfo(info, CLUSTER, TRUE);
1524     if (args == NULL) {
1525         Put_message("Aborted.");
1526         return;
1527     }
1528     if ( (stat = do_mr_query("update_cluster", CountArgs(args), 
1529                               args, Scream, NULL)) != 0)
1530         com_err(program_name, stat, " in UpdateCluster.");
1531     else
1532         Put_message("Cluster successfully updated.");
1533 }
1534
1535 /*      Function Name: UpdateCluster
1536  *      Description: This Function Updates a cluster
1537  *      Arguments: name of the cluster in argv[1].
1538  *      Returns: DM_NORMAL.
1539  */
1540
1541 /* ARGSUSED */
1542 int 
1543 UpdateCluster(argc, argv)
1544 int argc;
1545 char ** argv;
1546 {
1547     struct qelem *top;    
1548     top = GetMCInfo( CLUSTER, argv[1], (char *) NULL );
1549     QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
1550
1551     FreeQueue(top);
1552     return(DM_NORMAL);
1553 }
1554
1555 /*      Function Name: CheckAndRemoveMachine
1556  *      Description: This function checks and removes all machines from a
1557  *                   cluster.
1558  *      Arguments: name - name of the cluster.
1559  *                 ask_first - if TRUE, then we will query the user, before
1560  *                             deletion.
1561  *      Returns: SUB_ERROR if all machines not removed.
1562  */
1563
1564 int
1565 CheckAndRemoveMachines(name, ask_first)
1566 char * name;
1567 Bool ask_first;
1568 {
1569     register int stat, ret_value;
1570     Bool delete_it;
1571     char *args[10], temp_buf[BUFSIZ], *ptr;
1572     struct qelem *top, *elem = NULL;
1573     
1574     ret_value = SUB_NORMAL;
1575     args[MAP_MACHINE] = "*";
1576     args[MAP_CLUSTER] = name;
1577     stat = do_mr_query("get_machine_to_cluster_map", 2, args, 
1578                         StoreInfo, (char *)&elem);
1579     if (stat && stat != MR_NO_MATCH) {
1580         com_err(program_name, stat, " in get_machine_to_cluster_map.");
1581         return(DM_NORMAL);
1582     }
1583     if (stat == 0) {
1584         elem = top = QueueTop(elem);
1585         if (ask_first) {
1586             sprintf(temp_buf,
1587                     "The cluster %s has the following machines in it:",
1588                     name);
1589             Put_message(temp_buf);
1590             while (elem != NULL) {
1591                 char **info = (char **) elem->q_data;
1592                 Print(1, &info[MAP_MACHINE], (char *) NULL);
1593                 elem = elem->q_forw;
1594             }
1595             ptr = "Remove ** ALL ** these machines from this cluster?";
1596
1597             if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1598                 delete_it = TRUE;
1599             else {
1600                 Put_message("Aborting...");
1601                 FreeQueue(top);
1602                 return(SUB_ERROR);
1603             }
1604         }
1605         else
1606             delete_it = TRUE;
1607
1608         if (delete_it) {
1609             elem = top;
1610             while (elem != 0) {
1611                 char **info = (char **) elem->q_data;
1612                 if ( (stat = do_mr_query("delete_machine_from_cluster",
1613                                           2, info, Scream, NULL)) != 0) {
1614                     ret_value = SUB_ERROR;
1615                     com_err(program_name, stat, 
1616                             " in delete_machine_from_cluster.");
1617                     sprintf(temp_buf, 
1618                             "Machine %s ** NOT ** removed from cluster %s.",
1619                             info[MAP_MACHINE], info[MAP_CLUSTER]);
1620                     Put_message(temp_buf);
1621                 }
1622                 elem = elem->q_forw;
1623             }
1624         }
1625     }
1626     return(ret_value);
1627 }
1628
1629 /*      Function Name: RealDeleteCluster
1630  *      Description: Actually performs the cluster deletion.
1631  *      Arguments: info - all information about this cluster.
1632  *                 one_cluster - If true then there was only one cluster in
1633  *                               the queue, and we should confirm.
1634  *      Returns: none.
1635  */
1636
1637 static void
1638 RealDeleteCluster(info, one_cluster)
1639 char ** info;
1640 Bool one_cluster;
1641 {
1642     register int stat;
1643     char temp_buf[BUFSIZ];
1644     
1645     sprintf(temp_buf, 
1646             "Are you sure the you want to delete the cluster %s (y/n) ?", 
1647             info[C_NAME]);
1648     if (!one_cluster || Confirm(temp_buf)) {
1649         if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR) {
1650             if ( (stat = do_mr_query("delete_cluster", 1,
1651                                       &info[C_NAME], Scream, NULL)) != 0) {
1652                 com_err(program_name, stat, " in delete_cluster.");
1653                 sprintf(temp_buf, "Cluster %s ** NOT ** deleted.", 
1654                         info[C_NAME]);
1655                 Put_message(temp_buf);
1656             }
1657             else {
1658                 sprintf(temp_buf, "cluster %s sucesfully deleted.", 
1659                         info[C_NAME]);
1660                 Put_message(temp_buf);
1661             }
1662         }
1663     }
1664 }
1665
1666 /*      Function Name: DeleteCluster
1667  *      Description: This function removes a cluster from the database.
1668  *      Arguments: argc, argv - the name of the cluster is stored in argv[1].
1669  *      Returns: DM_NORMAL.
1670  */
1671
1672 /* ARGSUSED */
1673 int
1674 DeleteCluster(argc, argv)
1675 int argc;
1676 char ** argv;
1677 {
1678     struct qelem *top;
1679
1680     top = GetMCInfo( CLUSTER, argv[1], (char *) NULL );
1681     QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
1682
1683     FreeQueue(top);
1684     return(DM_NORMAL);
1685 }
1686     
1687 /* ----------- Cluster Data Menu -------------- */
1688
1689 /*      Function Name: ShowClusterData
1690  *      Description: This function shows the services for one cluster.
1691  *      Arguments: argc, argv - The name of the cluster is argv[1].
1692  *                              The label of the data in argv[2].
1693  *      Returns: DM_NORMAL.
1694  */
1695
1696 /* ARGSUSED */
1697 int
1698 ShowClusterData(argc, argv)
1699 int argc; 
1700 char ** argv; 
1701
1702     struct qelem *elem, *top;
1703     char **info;
1704
1705     top = elem = GetMCInfo(DATA, argv[1], argv[2]);
1706     while (elem != NULL) {
1707         info = (char **) elem->q_data;
1708         PrintClusterData(info);
1709         elem = elem->q_forw;
1710     }
1711     FreeQueue(top);
1712     return(DM_NORMAL);
1713 }
1714
1715 /*      Function Name: AddClusterData
1716  *      Description: This function adds some data to the cluster.
1717  *      Arguments: argv, argc:   argv[1] - the name of the cluster.
1718  *                               argv[2] - the label of the data.
1719  *                               argv[3] - the data.
1720  *      Returns: DM_NORMAL.
1721  */
1722
1723 /* ARGSUSED */
1724 int
1725 AddClusterData(argc, argv)
1726 int argc; 
1727 char ** argv; 
1728
1729     int stat;
1730
1731     if( (stat = do_mr_query("add_cluster_data", 3, argv + 1,
1732                              Scream, (char *) NULL)) != 0)
1733         com_err(program_name, stat, " in AddClusterData.");
1734     return(DM_NORMAL);
1735 }
1736
1737 /*      Function Name: RealRemoveClusterData
1738  *      Description: actually removes the cluster data.
1739  *      Arguments: info - all info necessary to remove the cluster, in an array
1740  *                        of strings.
1741  *                 one_item - if true then the queue has only one elem and we
1742  *                            should confirm.
1743  *      Returns: none.
1744  */
1745
1746 static void
1747 RealRemoveClusterData(info, one_item)
1748 char ** info;
1749 Bool one_item;
1750 {
1751     register int stat;
1752     char * temp_ptr;
1753
1754     Put_message(" ");
1755     temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1756     PrintClusterData(info);
1757     if (!one_item || Confirm(temp_ptr)) {
1758         if( (stat = do_mr_query("delete_cluster_data", 3, info,
1759                                  Scream, (char *) NULL)) != 0) {
1760             com_err(program_name, stat, " in DeleteClusterData.");
1761             Put_message("Data not removed.");
1762         }
1763         else
1764             Put_message("Removal sucessful.");
1765     }
1766 }
1767
1768 /*      Function Name: RemoveClusterData
1769  *      Description: This function removes data on a given cluster.
1770  *      Arguments: argv, argc:   argv[1] - the name of the cluster.
1771  *                               argv[2] - the label of the data.
1772  *                               argv[3] - the data.
1773  *      Returns: DM_NORMAL.
1774  */
1775
1776 /* ARGSUSED */
1777 int 
1778 RemoveClusterData(argc, argv)
1779 int argc; 
1780 char ** argv; 
1781 {
1782     struct qelem *top;
1783
1784     top = GetMCInfo(DATA, argv[1], argv[2]);
1785     QueryLoop(top, PrintClusterData, RealRemoveClusterData, 
1786               "Remove data from cluster");
1787
1788     FreeQueue(top);
1789     return(DM_NORMAL);
1790 }
1791
1792 /*      Function Name: MachineToClusterMap
1793  *      Description: This Retrieves the mapping between machine and cluster
1794  *      Arguments: argc, argv - argv[1] -> machine name or wildcard.
1795  *                              argv[2] -> cluster name or wildcard.
1796  *      Returns: none.
1797  */
1798
1799 /* ARGSUSED */
1800 int 
1801 MachineToClusterMap(argc,argv)
1802 int argc;
1803 char **argv;
1804 {
1805     struct qelem *elem, *top;
1806     char *tmpname, temp_buf[256];
1807
1808     tmpname = canonicalize_hostname(strsave(argv[1]));
1809     if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"') {
1810         sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1811                 argv[1], tmpname);
1812         Put_message(temp_buf);
1813     }
1814     top = elem = GetMCInfo(MAP, tmpname, argv[2]);
1815   
1816     Put_message("");            /* blank line on screen */
1817     while (elem != NULL) {
1818         char ** info = (char **) elem->q_data;
1819         PrintMCMap(info);
1820         elem = elem->q_forw;
1821     }
1822
1823     FreeQueue(top);
1824     free(tmpname);
1825     return(DM_NORMAL);
1826 }
This page took 0.180559 seconds and 5 git commands to generate.