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