1 #if (!defined(lint) && !defined(SABER))
2 static char rcsid_module_c[] = "$Header$";
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.
10 * By: Chris D. Peterson
16 * Copyright 1988 by the Massachusetts Institute of Technology.
18 * For further information on copyright and distribution
19 * see the file mit-copyright.h
22 /* BTW: for anyone who cares MCD is short for Machine, Cluster, Data. */
27 #include <moira_site.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <sys/utsname.h>
37 #include "mit-copyright.h"
49 #define M_DEFAULT_TYPE DEFAULT_NONE
51 #define C_DEFAULT_DESCRIPT DEFAULT_NONE
52 #define C_DEFAULT_LOCATION DEFAULT_NONE
54 #define CD_DEFAULT_LABEL DEFAULT_NONE
55 #define CD_DEFAULT_DATA DEFAULT_NONE
57 #define S_DEFAULT_LOW "18.0.0.20"
58 #define S_DEFAULT_HIGH "18.0.2.249"
60 static char *states[] = {
67 static char *MacState(int state)
69 static char buf[BUFSIZ];
71 if (state < 0 || state > 3)
73 sprintf(buf, "Unknown (%d)", state);
81 /* -------------------- Set Defaults -------------------- */
83 /* Function Name: SetMachineDefaults
84 * Description: sets machine defaults.
85 * Arguments: info - an array to put the defaults into.
86 * name - Canonacalized name of the machine.
87 * Returns: info - the array.
90 static char **SetMachineDefaults(char **info, char *name)
92 info[M_NAME] = Strsave(name);
93 info[M_VENDOR] = Strsave(M_DEFAULT_TYPE);
94 info[M_MODEL] = Strsave(M_DEFAULT_TYPE);
95 info[M_OS] = Strsave(M_DEFAULT_TYPE);
96 info[M_LOC] = Strsave(M_DEFAULT_TYPE);
97 info[M_CONTACT] = Strsave(M_DEFAULT_TYPE);
98 info[M_USE] = Strsave("0");
99 info[M_STAT] = Strsave("1");
100 info[M_SUBNET] = Strsave("NONE");
101 info[M_ADDR] = Strsave("unique");
102 info[M_OWNER_TYPE] = Strsave("NONE");
103 info[M_OWNER_NAME] = Strsave("NONE");
104 info[M_ACOMMENT] = Strsave("");
105 info[M_OCOMMENT] = Strsave("");
106 info[15] = info[16] = NULL;
110 /* Function Name: SetClusterDefaults
111 * Description: sets Cluster defaults.
112 * Arguments: info - an array to put the defaults into.
113 * name - name of the Cluster.
114 * Returns: info - the array.
117 static char **SetClusterDefaults(char **info, char *name)
119 info[C_NAME] = Strsave(name);
120 info[C_DESCRIPT] = Strsave(C_DEFAULT_DESCRIPT);
121 info[C_LOCATION] = Strsave(C_DEFAULT_LOCATION);
122 info[C_MODBY] = info[C_MODTIME] = info[C_MODWITH] = info[C_END] = NULL;
126 /* Function Name: SetSubnetDefaults
127 * Description: sets Subnet defaults.
128 * Arguments: info - an array to put the defaults into.
129 * name - name of the Subnet.
130 * Returns: info - the array.
133 static char **SetSubnetDefaults(char **info, char *name)
137 info[C_NAME] = Strsave(name);
138 info[SN_DESC] = Strsave("");
139 sprintf(buf, "%ld", ntohl(inet_addr("18.255.0.0")));
140 info[SN_ADDRESS] = Strsave(buf);
141 sprintf(buf, "%ld", ntohl(inet_addr("255.255.0.0")));
142 info[SN_MASK] = Strsave(buf);
143 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_LOW)));
144 info[SN_LOW] = Strsave(buf);
145 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_HIGH)));
146 info[SN_HIGH] = Strsave(buf);
147 info[SN_PREFIX] = Strsave("");
148 info[SN_ACE_TYPE] = Strsave("LIST");
149 info[SN_ACE_NAME] = Strsave("network");
150 info[SN_MODBY] = info[SN_MODTIME] = info[SN_MODWITH] = info[SN_END] = NULL;
154 /* -------------------- General Functions -------------------- */
156 static char aliasbuf[256];
158 static char *PrintAliases(char **info)
160 if (strlen(aliasbuf) == 0)
161 sprintf(aliasbuf, "Aliases: %s", info[0]);
164 strcat(aliasbuf, ", ");
165 strcat(aliasbuf, info[0]);
170 /* Function Name: PrintMachInfo
171 * Description: This function Prints out the Machine info in
173 * Arguments: info - array of information about a machine.
174 * Returns: The name of the Machine
177 static char *PrintMachInfo(char **info)
179 char buf[BUFSIZ], tbuf[256];
181 struct qelem *elem = NULL;
185 sprintf(buf, "Machine: %s", info[M_NAME]);
188 args[1] = info[M_NAME];
189 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, (char *)&elem)))
191 if (stat != MR_NO_MATCH)
192 com_err(program_name, stat, " looking up aliases");
197 Loop(QueueTop(elem), (void *) PrintAliases);
199 Put_message(aliasbuf);
201 sprintf(tbuf, "%s %s", info[M_OWNER_TYPE],
202 strcmp(info[M_OWNER_TYPE], "NONE") ? info[M_OWNER_NAME] : "");
203 sprintf(buf, "Address: %-16s Network: %-16s",
204 info[M_ADDR], info[M_SUBNET]);
206 sprintf(buf, "Owner: %-16s Use data: %s", tbuf, info[M_INUSE]);
208 sprintf(buf, "Status: %-16s Changed: %s",
209 MacState(atoi(info[M_STAT])), info[M_STAT_CHNG]);
213 sprintf(buf, "Vendor: %-16s Model: %-20s OS: %s",
214 info[M_VENDOR], info[M_MODEL], info[M_OS]);
216 sprintf(buf, "Location: %-16s Contact: %-20s Opt: %s",
217 info[M_LOC], info[M_CONTACT], info[M_USE]);
219 sprintf(buf, "\nAdm cmt: %s", info[M_ACOMMENT]);
221 sprintf(buf, "Op cmt: %s", info[M_OCOMMENT]);
224 sprintf(buf, "Created by %s on %s", info[M_CREATOR], info[M_CREATED]);
226 sprintf(buf, MOD_FORMAT, info[M_MODBY], info[M_MODTIME], info[M_MODWITH]);
231 /* Function Name: PrintCname
232 * Description: Prints the Data on a host alias
233 * Arguments: info a pointer to the data array.
234 * Returns: The name of the alias.
237 static char *PrintCname(char **info)
241 sprintf(buf, "Alias: %-32s Canonical Name: %s", info[0], info[1]);
246 /* Function Name: PrintClusterInfo
247 * Description: This function Prints out the cluster info
248 * in a coherent form.
249 * Arguments: info - array of information about a cluster.
250 * Returns: The name of the cluster.
253 static char *PrintClusterInfo(char **info)
258 sprintf(buf, "Cluster: %s", info[C_NAME]);
260 sprintf(buf, "Description: %s", info[C_DESCRIPT]);
262 sprintf(buf, "Location: %s", info[C_LOCATION]);
264 sprintf(buf, MOD_FORMAT, info[C_MODBY], info[C_MODTIME], info[C_MODWITH]);
269 /* Function Name: PrintClusterData
270 * Description: Prints the Data on a cluster
271 * Arguments: info a pointer to the data array.
272 * Returns: The name of the cluster.
275 static char *PrintClusterData(char **info)
280 sprintf(buf, "Cluster: %-20s Label: %-15s Data: %s",
281 info[CD_NAME], info[CD_LABEL], info[CD_DATA]);
283 return info[CD_NAME];
286 /* Function Name: PrintMCMap
287 * Description: Prints the data about a machine to cluster mapping.
288 * Arguments: info a pointer to the data array.
292 static char *PrintMCMap(char **info)
295 sprintf(buf, "Cluster: %-30s Machine: %-20s",
296 info[MAP_CLUSTER], info[MAP_MACHINE]);
298 return ""; /* Used by QueryLoop(). */
301 /* Function Name: PrintSubnetInfo
302 * Description: This function Prints out the subnet info
303 * in a coherent form.
304 * Arguments: info - array of information about a subnet.
305 * Returns: The name of the subnet.
308 static char *PrintSubnetInfo(char **info)
311 struct in_addr addr, mask, low, high;
314 sprintf(buf, " Network: %s", info[SN_NAME]);
316 sprintf(buf, " Description: %s", info[SN_DESC]);
318 addr.s_addr = htonl(atoi(info[SN_ADDRESS]));
319 mask.s_addr = htonl(atoi(info[SN_MASK]));
320 low.s_addr = htonl(atoi(info[SN_LOW]));
321 high.s_addr = htonl(atoi(info[SN_HIGH]));
322 /* screwy sequence is here because inet_ntoa returns a pointer to
323 a static buf. If it were all one sprintf, the last value would
325 sprintf(buf, " Address: %s Mask: ", inet_ntoa(addr));
326 strcat(buf, inet_ntoa(mask));
327 strcat(buf, "\n High: ");
328 strcat(buf, inet_ntoa(high));
329 strcat(buf, " Low: ");
330 strcat(buf, inet_ntoa(low));
332 sprintf(buf, "Hostname prefix: %s", info[SN_PREFIX]);
334 sprintf(buf, " Owner: %s %s\n", info[SN_ACE_TYPE],
335 strcmp(info[SN_ACE_TYPE], "NONE") ? info[SN_ACE_NAME] : "");
337 sprintf(buf, MOD_FORMAT, info[SN_MODBY], info[SN_MODTIME], info[SN_MODWITH]);
339 return info[SN_NAME];
342 /* Function Name: GetMCInfo.
343 * Description: This function stores info about a machine.
344 * type - type of data we are trying to retrieve.
345 * name1 - the name of argv[0] for the call.
346 * name2 - the name of argv[1] for the call.
347 * Returns: the top element of a queue containing the data or NULL.
350 struct qelem *GetMCInfo(int type, char *name1, char *name2)
353 struct qelem *elem = NULL;
360 args[1] = args[2] = args[3] = "*";
361 if ((stat = do_mr_query("get_host", 4, args,
362 StoreInfo, (char *)&elem)))
364 if (stat == MR_NO_MATCH)
367 sprintf(buf, "Machine '%s' is not in the database.", name1);
371 com_err(program_name, stat, " in get_machine.");
378 if ((stat = do_mr_query("get_hostalias", 2, args,
379 StoreInfo, (char *)&elem)))
381 com_err(program_name, stat, " in get_hostalias.");
386 if ((stat = do_mr_query("get_subnet", 1, &name1,
387 StoreInfo, (char *)&elem)))
389 if (stat == MR_NO_MATCH)
392 sprintf(buf, "Network '%s' is not in the database.", name1);
396 com_err(program_name, stat, " in get_subnet.");
401 if ((stat = do_mr_query("get_cluster", 1, &name1,
402 StoreInfo, (char *)&elem)))
404 com_err(program_name, stat, " in get_cluster.");
409 args[MAP_MACHINE] = name1;
410 args[MAP_CLUSTER] = name2;
411 if ((stat = do_mr_query("get_machine_to_cluster_map", 2, args,
412 StoreInfo, (char *)&elem)))
414 com_err(program_name, stat, " in get_machine_to_cluster_map.");
419 args[CD_NAME] = name1;
420 args[CD_LABEL] = name2;
421 if ((stat = do_mr_query("get_cluster_data", 2, args,
422 StoreInfo, (char *)&elem)))
424 com_err(program_name, stat, " in get_cluster_data.");
428 return QueueTop(elem);
431 /* Function Name: AskMCDInfo.
432 * Description: This function askes the user for information about a
433 * machine and saves it into a structure.
434 * Arguments: info - a pointer the information to ask about
435 * type - type of information - MACHINE
438 * name - T/F : change the name of this type.
442 char **AskMCDInfo(char **info, int type, Bool name)
444 char temp_buf[BUFSIZ], *newname, *oldnewname;
449 sprintf(temp_buf, "\nSetting the information for the Machine %s...",
453 sprintf(temp_buf, "Setting the information for the Network %s...",
457 sprintf(temp_buf, "Setting the information for the Cluster %s...",
461 sprintf(temp_buf, "Setting the Data for the Cluster %s...",
465 Put_message(temp_buf);
472 newname = Strsave(info[M_NAME]);
473 if (GetValueFromUser("The new name for this machine? ", &newname) ==
476 oldnewname = Strsave(newname);
477 newname = canonicalize_hostname(newname);
478 if (strcasecmp(newname, oldnewname) && *oldnewname != '"')
480 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'\n",
481 oldnewname, newname);
482 Put_message(temp_buf);
487 newname = Strsave(info[SN_NAME]);
488 if (GetValueFromUser("The new name for this network? ", &newname) ==
493 newname = Strsave(info[C_NAME]);
494 if (GetValueFromUser("The new name for this cluster? ", &newname) ==
499 Put_message("Unknown type in AskMCDInfo, programmer botch");
507 if (GetValueFromUser("Machine's vendor", &info[M_VENDOR]) == SUB_ERROR)
509 if (GetValueFromUser("Machine's model", &info[M_MODEL]) == SUB_ERROR)
511 if (GetValueFromUser("Machine's operating system", &info[M_OS]) ==
514 if (GetValueFromUser("Machine's location", &info[M_LOC]) == SUB_ERROR)
516 if (GetValueFromUser("Machine's contact", &info[M_CONTACT]) ==
522 if (GetValueFromUser("Machine's status (? for help)",
523 &info[M_STAT]) == SUB_ERROR)
525 if (isdigit(info[M_STAT][0]))
527 Put_message("Valid status numbers:");
528 for (i = 0; i < 4; i++)
529 Put_message(states[i]);
532 /* there appears to be some argument mismatch between the client
533 * and the server.. so here is this argument shuffler.
534 * I have since modified this to always shuffle the arguments..
535 * not just do so when performing a modify all fields request.
536 * The SetMachinedefaults() has been changed to reflect this.
537 * pray for us and may we attain enlightenment through structures.
542 /* info did not come from SetMachineDefaults(), which does not
543 * initialize entry 8 (M_STAT_CHNG), therefore we can
546 /* This is an update of an existing machine and the structure
547 * was filled in thru a query to the db which does fill in this
553 info[8] = info[M_SUBNET];
554 info[9] = info[M_ADDR];
555 info[10] = info[M_OWNER_TYPE];
556 info[11] = info[M_OWNER_NAME];
557 info[12] = info[M_ACOMMENT];
558 info[13] = info[M_OCOMMENT];
562 if (GetValueFromUser("Machine's network (or 'none')", &info[8])
566 if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')",
567 &info[9]) == SUB_ERROR)
569 if (GetTypeFromUser("Machine's owner type", "ace_type", &info[10]) ==
572 if (strcmp(info[10], "NONE") &&
573 GetValueFromUser("Owner's Name", &info[11]) == SUB_ERROR)
575 if (GetValueFromUser("Administrative comment", &info[12]) == SUB_ERROR)
577 if (GetValueFromUser("Operational comment", &info[13]) == SUB_ERROR)
580 FreeAndClear(&info[15], TRUE);
581 FreeAndClear(&info[16], TRUE);
584 if (GetValueFromUser("Network description", &info[SN_DESC]) == SUB_ERROR)
586 if (GetAddressFromUser("Network address", &info[SN_ADDRESS]) == SUB_ERROR)
588 if (GetAddressFromUser("Network mask", &info[SN_MASK]) == SUB_ERROR)
590 if (atoi(info[SN_LOW]) == ntohl(inet_addr(S_DEFAULT_LOW)))
593 unsigned long mask, addr;
595 addr = atoi(info[SN_ADDRESS]);
596 mask = atoi(info[SN_MASK]);
597 low.s_addr = atoi(info[SN_LOW]);
598 low.s_addr = (low.s_addr & ~mask) | (addr & mask);
600 sprintf(temp_buf, "%d", low.s_addr);
601 info[SN_LOW] = strsave(temp_buf);
603 if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) ==
606 if (atoi(info[SN_HIGH]) == ntohl(inet_addr(S_DEFAULT_HIGH)))
609 unsigned long mask, addr;
611 addr = atoi(info[SN_ADDRESS]);
612 mask = atoi(info[SN_MASK]);
613 high.s_addr = atoi(info[SN_HIGH]);
614 high.s_addr = (high.s_addr & ~mask) | (addr & mask);
616 sprintf(temp_buf, "%d", high.s_addr);
617 info[SN_HIGH] = strsave(temp_buf);
619 if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) ==
622 if (GetValueFromUser("Hostname prefix", &info[SN_PREFIX]) == SUB_ERROR)
624 if (GetTypeFromUser("Owner type", "ace_type", &info[SN_ACE_TYPE]) ==
627 if (strcmp(info[SN_ACE_TYPE], "NONE") &&
628 GetValueFromUser("Owner name", &info[SN_ACE_NAME]) == SUB_ERROR)
630 FreeAndClear(&info[SN_MODTIME], TRUE);
631 FreeAndClear(&info[SN_MODBY], TRUE);
632 FreeAndClear(&info[SN_MODWITH], TRUE);
635 if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) ==
638 if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) ==
641 FreeAndClear(&info[C_MODTIME], TRUE);
642 FreeAndClear(&info[C_MODBY], TRUE);
643 FreeAndClear(&info[C_MODWITH], TRUE);
646 if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) ==
649 if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR)
655 * Slide the newname into the #2 slot, this screws up all future references
659 SlipInNewName(info, newname);
664 /* ----------- Machine Menu ----------- */
666 /* Function Name: ShowMachineInfo
667 * Description: This function shows the information about a machine.
668 * Arguments: argc, argv - the name of the machine in argv[1].
669 * Returns: DM_NORMAL.
672 int ShowMachineInfo(int argc, char **argv)
677 tmpname = canonicalize_hostname(strsave(argv[1]));
678 top = GetMCInfo(MACHINE, tmpname, NULL);
679 Loop(top, ((void *) PrintMachInfo));
684 /* Function Name: ShowMachineQuery
685 * Description: This function shows the information about a machine.
686 * or group of machines, which may be selected through a
687 * number of criteria.
688 * Arguments: argc, argv - the name of the machine in argv[1],
689 * the address of the machine in argv[2],
690 * the location of the machine in argv[3],
691 * and the contact name in argv[4].
692 * any of these may be wildcards.
693 * Returns: DM_NORMAL.
696 int ShowMachineQuery(int argc, char **argv)
699 struct qelem *top, *elem = NULL;
702 if (!strcmp(argv[1], "") && !strcmp(argv[2], "") &&
703 !strcmp(argv[3], "") && !strcmp(argv[4], ""))
705 Put_message("You must specify at least one parameter of the query.");
710 args[0] = canonicalize_hostname(strsave(argv[1]));
726 if ((stat = do_mr_query("get_host", 4, args, StoreInfo,
729 if (stat == MR_NO_MATCH)
730 Put_message("No machine(s) found matching query in the database.");
732 com_err(program_name, stat, " in get_machine.");
735 top = QueueTop(elem);
736 Loop(top, ((void *) PrintMachInfo));
741 /* Function Name: AddMachine
742 * Description: This function adds a new machine to the database.
743 * Arguments: argc, argv - the name of the network in argv[1].
744 * Returns: DM_NORMAL.
747 int AddMachine(int argc, char **argv)
749 char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
751 struct qelem *elem = NULL;
754 if (!ValidName(argv[1])) /* Checks for wildcards. */
758 * get the network record
761 if (strcasecmp(argv[1], "none") &&
762 (stat = do_mr_query("get_subnet", 1, &argv[1],
763 StoreInfo, (char *)&elem)))
765 if (stat == MR_NO_MATCH)
768 sprintf(buf, "Network '%s' is not in the database.", argv[1]);
771 com_err(program_name, stat, " in get_subnet.");
776 * Check to see if this machine already exists.
779 name = strsave(""); /* want to put prefix here */
780 if (GetValueFromUser("Machine name", &name) == SUB_ERROR)
783 name = canonicalize_hostname(strsave(name));
786 xargs[1] = xargs[2] = xargs[3] = "*";
787 if (!(stat = do_mr_query("get_host", 4, xargs, NullFunc, NULL)))
789 sprintf(buf, "The machine '%s' already exists.", name);
794 else if (stat != MR_NO_MATCH)
796 com_err(program_name, stat,
797 " while checking machine '%s' in AddMachine.", name);
801 rinfo = SetMachineDefaults(info, name);
802 rinfo[M_SUBNET] = strsave(argv[1]);
803 if (!(args = AskMCDInfo(rinfo, MACHINE, FALSE)))
805 Put_message("Aborted.");
810 * Actually create the new Machine.
813 if ((stat = do_mr_query("add_host", CountArgs(args),
814 args, Scream, NULL)))
815 com_err(program_name, stat, " in AddMachine.");
822 /* Function Name: RealUpdateMachine
823 * Description: Performs the actual update of the machine data.
824 * Arguments: info - the information on the machine to update.
825 * junk - an UNUSED Boolean.
829 static void RealUpdateMachine(char **info, Bool junk)
832 char **args = AskMCDInfo(info, MACHINE, TRUE);
835 Put_message("Aborted.");
838 if ((stat = do_mr_query("update_host", CountArgs(args),
839 args, Scream, NULL)))
840 com_err(program_name, stat, " in UpdateMachine.");
842 Put_message("Machine successfully updated.");
845 /* Function Name: UpdateMachine
846 * Description: This function adds a new machine to the database.
847 * Arguments: argc, argv - the name of the machine in argv[1].
848 * Returns: DM_NORMAL.
851 int UpdateMachine(int argc, char **argv)
856 tmpname = canonicalize_hostname(strsave(argv[1]));
857 top = GetMCInfo(MACHINE, tmpname, NULL);
858 QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
865 /* Function Name: CheckAndRemoveFromCluster
866 * Description: This func tests to see if a machine is in a cluster.
867 * and if so then removes it
868 * Arguments: name - name of the machine (already Canonocalized).
869 * ask_user- query the user before removing if from clusters?
870 * Returns: MR_ERROR if machine left in a cluster, or mr_error.
873 int CheckAndRemoveFromCluster(char *name, Bool ask_user)
875 register int stat, ret_value;
877 char *args[10], temp_buf[BUFSIZ], *ptr;
878 struct qelem *top, *elem = NULL;
880 ret_value = SUB_NORMAL; /* initialize ret_value. */
883 stat = do_mr_query("get_machine_to_cluster_map", 2, args,
884 StoreInfo, (char *)&elem);
885 if (stat && stat != MR_NO_MATCH)
887 com_err(program_name, stat, " in get_machine_to_cluster_map.");
890 if (stat == MR_SUCCESS)
892 elem = top = QueueTop(elem);
895 sprintf(temp_buf, "%s is assigned to the following clusters.", name);
896 Put_message(temp_buf);
897 Loop(top, (void *) PrintMCMap);
898 ptr = "Remove this machine from ** ALL ** these clusters?";
899 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
903 Put_message("Aborting...");
915 char **info = (char **) elem->q_data;
916 if ((stat = do_mr_query("delete_machine_from_cluster",
917 2, info, Scream, NULL)))
919 ret_value = SUB_ERROR;
920 com_err(program_name, stat,
921 " in delete_machine_from_cluster.");
923 "Machine %s ** NOT ** removed from cluster %s.",
924 info[MAP_MACHINE], info[MAP_CLUSTER]);
925 Put_message(temp_buf);
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
942 static void RealDeleteMachine(char **info, Bool one_machine)
945 char temp_buf[BUFSIZ];
947 sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ",
949 if (!one_machine || Confirm(temp_buf))
951 if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR)
953 if ((stat = do_mr_query("delete_host", 1,
954 &info[M_NAME], Scream, NULL)))
956 com_err(program_name, stat, " in DeleteMachine.");
957 sprintf(temp_buf, "%s ** NOT ** deleted.",
959 Put_message(temp_buf);
963 sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
964 Put_message(temp_buf);
970 /* Function Name: DeleteMachine
971 * Description: This function removes a machine from the data base.
972 * Arguments: argc, argv - the machines name int argv[1].
973 * Returns: DM_NORMAL.
976 /* Perhaps we should remove the cluster if it has no machine now. */
978 int DeleteMachine(int argc, char **argv)
983 tmpname = canonicalize_hostname(strsave(argv[1]));
984 top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
985 QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
992 char *partial_canonicalize_hostname(char *s)
995 static char *def_domain = NULL;
1002 hp = gethostbyname(name.nodename);
1003 cp = strchr(hp->h_name, '.');
1005 def_domain = strsave(++cp);
1010 if (strchr(s, '.') || strchr(s, '*'))
1012 sprintf(buf, "%s.%s", s, def_domain);
1014 return strsave(buf);
1018 /* Function Name: ShowCname
1019 * Description: This function shows machine aliases
1020 * Arguments: argc, argv - the alias argv[1], the real name in argv[2]
1021 * Returns: DM_NORMAL.
1024 int ShowCname(int argc, char **argv)
1027 char *tmpalias, *tmpname;
1029 tmpalias = partial_canonicalize_hostname(strsave(argv[1]));
1030 tmpname = canonicalize_hostname(strsave(argv[2]));
1031 top = GetMCInfo(CNAME, tmpalias, tmpname);
1032 Put_message(""); /* blank line on screen */
1033 Loop(top, ((void *) PrintCname));
1039 int AddCname(int argc, char **argv)
1044 args[0] = partial_canonicalize_hostname(strsave(argv[1]));
1045 args[1] = canonicalize_hostname(strsave(argv[2]));
1046 stat = do_mr_query("add_hostalias", 2, args, Scream, NULL);
1052 Put_message("That alias name is already in use.");
1055 Put_message("Permission denied. "
1056 "(Regular users can only add two aliases to a host.");
1059 com_err(program_name, stat, " in add_hostalias");
1065 int DeleteCname(int argc, char **argv)
1068 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1069 Bool add_it, one_machine, one_cluster;
1070 struct qelem *melem, *mtop, *celem, *ctop;
1072 args[0] = partial_canonicalize_hostname(strsave(argv[1]));
1073 args[1] = canonicalize_hostname(strsave(argv[2]));
1074 stat = do_mr_query("delete_hostalias", 2, args, Scream, NULL);
1076 com_err(program_name, stat, " in delete_hostalias");
1081 /* Function Name: AddMachineToCluster
1082 * Description: This function adds a machine to a cluster
1083 * Arguments: argc, argv - The machine name is argv[1].
1084 * The cluster name in argv[2].
1085 * Returns: DM_NORMAL.
1088 int AddMachineToCluster(int argc, char **argv)
1091 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1092 Bool add_it, one_machine, one_cluster;
1093 struct qelem *melem, *mtop, *celem, *ctop;
1095 machine = canonicalize_hostname(strsave(argv[1]));
1096 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
1098 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1100 Put_message(temp_buf);
1104 celem = ctop = GetMCInfo(CLUSTER, cluster, NULL);
1105 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
1108 one_machine = (QueueCount(mtop) == 1);
1109 one_cluster = (QueueCount(ctop) == 1);
1111 /* No good way to use QueryLoop() here, sigh */
1115 char **minfo = (char **) melem->q_data;
1118 char **cinfo = (char **) celem->q_data;
1119 if (one_machine && one_cluster)
1123 sprintf(temp_buf, "Add machine %s to cluster %s (y/n/q) ?",
1124 minfo[M_NAME], cinfo[C_NAME]);
1125 switch (YesNoQuitQuestion(temp_buf, FALSE))
1134 Put_message("Aborting...");
1142 args[0] = minfo[M_NAME];
1143 args[1] = cinfo[C_NAME];
1144 stat = do_mr_query("add_machine_to_cluster", 2, args,
1151 sprintf(temp_buf, "%s is already in cluster %s",
1152 minfo[M_NAME], cinfo[C_NAME]);
1153 Put_message(temp_buf);
1156 com_err(program_name, stat, " in AddMachineToCluster.");
1160 celem = celem->q_forw;
1162 celem = ctop; /* reset cluster element. */
1163 melem = melem->q_forw;
1170 /* Function Name: RealRemoveMachineFromCluster
1171 * Description: This function actually removes the machine from its
1173 * Arguments: info - all information nescessary to perform the removal.
1174 * one_map - True if there is only one case, and we should
1179 static void RealRemoveMachineFromCluster(char **info, Bool one_map)
1181 char temp_buf[BUFSIZ];
1184 sprintf(temp_buf, "Remove %s from the cluster %s",
1185 info[MAP_MACHINE], info[MAP_CLUSTER]);
1186 if (!one_map || Confirm(temp_buf))
1188 if ((stat = do_mr_query("delete_machine_from_cluster", 2,
1189 info, Scream, NULL)))
1190 com_err(program_name, stat, " in delete_machine_from_cluster");
1193 sprintf(temp_buf, "%s has been removed from the cluster %s.",
1194 info[MAP_MACHINE], info[MAP_CLUSTER]);
1195 Put_message(temp_buf);
1199 Put_message("Machine not removed.");
1202 /* Function Name: RemoveMachineFromCluster
1203 * Description: Removes this machine form a specific cluster.
1204 * Arguments: argc, argv - Name of machine in argv[1].
1205 * Name of cluster in argv[2].
1209 int RemoveMachineFromCluster(int argc, char **argv)
1211 struct qelem *elem = NULL;
1212 char buf[BUFSIZ], * args[10];
1215 args[MAP_MACHINE] = canonicalize_hostname(strsave(argv[1]));
1216 if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"')
1218 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
1219 argv[1], args[MAP_MACHINE]);
1222 args[MAP_CLUSTER] = argv[2];
1223 args[MAP_END] = NULL;
1225 stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
1226 StoreInfo, (char *)&elem);
1227 if (stat == MR_NO_MATCH)
1229 sprintf(buf, "The machine %s is not is the cluster %s.",
1230 args[MAP_MACHINE], args[MAP_CLUSTER]);
1232 free(args[MAP_MACHINE]);
1235 if (stat != MR_SUCCESS)
1236 com_err(program_name, stat, " in delete_machine_from_cluster");
1238 elem = QueueTop(elem);
1239 QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster,
1240 "Remove this machine from this cluster");
1243 free(args[MAP_MACHINE]);
1247 /* ---------- Subnet Menu -------- */
1249 /* Function Name: ShowSubnetInfo
1250 * Description: Gets information about a subnet given its name.
1251 * Arguments: argc, argc - the name of the subnet in in argv[1].
1252 * Returns: DM_NORMAL.
1255 int ShowSubnetInfo(int argc, char **argv)
1259 top = GetMCInfo(SUBNET, argv[1], (char *) NULL);
1260 Loop(top, (void *) PrintSubnetInfo);
1265 /* Function Name: AddSubnet
1266 * Description: Creates a new subnet.
1267 * Arguments: argc, argv - the name of the new subnet is argv[1].
1268 * Returns: DM_NORMAL.
1271 int AddSubnet(int argc, char **argv)
1273 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1277 * Check to see if this subnet already exists.
1279 if (!ValidName(name))
1282 if ((stat = do_mr_query("get_subnet", 1, &name,
1283 NullFunc, NULL)) == MR_SUCCESS)
1285 Put_message("This subnet already exists.");
1288 else if (stat != MR_NO_MATCH)
1290 com_err(program_name, stat, " in AddSubnet.");
1293 if (!(args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE)))
1295 Put_message("Aborted.");
1301 * Actually create the new Subnet.
1303 if ((stat = do_mr_query("add_subnet", CountArgs(args),
1304 args, Scream, NULL)))
1305 com_err(program_name, stat, " in AddSubnet.");
1311 /* Function Name: RealUpdateSubnet
1312 * Description: This function actually performs the subnet update.
1313 * Arguments: info - all information nesc. for updating the subnet.
1314 * junk - an UNUSED boolean.
1318 static void RealUpdateSubnet(char **info, Bool junk)
1321 char **args = AskMCDInfo(info, SUBNET, TRUE);
1324 Put_message("Aborted.");
1327 if ((stat = do_mr_query("update_subnet", CountArgs(args),
1328 args, Scream, NULL)))
1329 com_err(program_name, stat, " in UpdateSubnet.");
1331 Put_message("Subnet successfully updated.");
1334 /* Function Name: UpdateSubnet
1335 * Description: This Function Updates a subnet
1336 * Arguments: name of the subnet in argv[1].
1337 * Returns: DM_NORMAL.
1340 int UpdateSubnet(int argc, char **argv)
1343 top = GetMCInfo(SUBNET, argv[1], NULL);
1344 QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet");
1350 /* Function Name: RealDeleteSubnet
1351 * Description: Actually performs the subnet deletion.
1352 * Arguments: info - all information about this subnet.
1353 * one_subnet - If true then there was only one subnet in
1354 * the queue, and we should confirm.
1358 static void RealDeleteSubnet(char **info, Bool one_subnet)
1361 char temp_buf[BUFSIZ];
1364 "Are you sure the you want to delete the subnet %s (y/n) ?",
1366 if (!one_subnet || Confirm(temp_buf))
1368 if ((stat = do_mr_query("delete_subnet", 1,
1369 &info[C_NAME], Scream, NULL)))
1371 com_err(program_name, stat, " in delete_subnet.");
1372 sprintf(temp_buf, "Subnet %s ** NOT ** deleted.", info[C_NAME]);
1373 Put_message(temp_buf);
1377 sprintf(temp_buf, "subnet %s successfully deleted.",
1379 Put_message(temp_buf);
1384 /* Function Name: DeleteSubnet
1385 * Description: This function removes a subnet from the database.
1386 * Arguments: argc, argv - the name of the subnet is stored in argv[1].
1387 * Returns: DM_NORMAL.
1390 int DeleteSubnet(int argc, char **argv)
1394 top = GetMCInfo(SUBNET, argv[1], NULL);
1395 QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet");
1401 /* ---------- Cluster Menu -------- */
1403 /* Function Name: ShowClusterInfo
1404 * Description: Gets information about a cluser given its name.
1405 * Arguments: argc, argc - the name of the cluster in in argv[1].
1406 * Returns: DM_NORMAL.
1409 int ShowClusterInfo(int argc, char **argv)
1413 top = GetMCInfo(CLUSTER, argv[1], NULL);
1414 Loop(top, (void *) PrintClusterInfo);
1419 /* Function Name: AddCluster
1420 * Description: Creates a new cluster.
1421 * Arguments: argc, argv - the name of the new cluster is argv[1].
1422 * Returns: DM_NORMAL.
1425 int AddCluster(int argc, char **argv)
1427 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1431 * Check to see if this cluster already exists.
1433 if (!ValidName(name))
1436 if ((stat = do_mr_query("get_cluster", 1, &name,
1437 NullFunc, NULL)) == MR_SUCCESS)
1439 Put_message("This cluster already exists.");
1442 else if (stat != MR_NO_MATCH)
1444 com_err(program_name, stat, " in AddCluster.");
1447 if (!(args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)))
1449 Put_message("Aborted.");
1455 * Actually create the new Cluster.
1457 if ((stat = do_mr_query("add_cluster", CountArgs(args),
1458 args, Scream, NULL)))
1459 com_err(program_name, stat, " in AddCluster.");
1465 /* Function Name: RealUpdateCluster
1466 * Description: This function actually performs the cluster update.
1467 * Arguments: info - all information nesc. for updating the cluster.
1468 * junk - an UNUSED boolean.
1472 static void RealUpdateCluster(char **info, Bool junk)
1475 char **args = AskMCDInfo(info, CLUSTER, TRUE);
1479 Put_message("Aborted.");
1482 if ((stat = do_mr_query("update_cluster", CountArgs(args),
1483 args, Scream, NULL)))
1484 com_err(program_name, stat, " in UpdateCluster.");
1486 Put_message("Cluster successfully updated.");
1489 /* Function Name: UpdateCluster
1490 * Description: This Function Updates a cluster
1491 * Arguments: name of the cluster in argv[1].
1492 * Returns: DM_NORMAL.
1495 int UpdateCluster(int argc, char **argv)
1498 top = GetMCInfo(CLUSTER, argv[1], NULL);
1499 QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
1505 /* Function Name: CheckAndRemoveMachine
1506 * Description: This function checks and removes all machines from a
1508 * Arguments: name - name of the cluster.
1509 * ask_first - if TRUE, then we will query the user, before
1511 * Returns: SUB_ERROR if all machines not removed.
1514 int CheckAndRemoveMachines(char *name, Bool ask_first)
1516 register int stat, ret_value;
1518 char *args[10], temp_buf[BUFSIZ], *ptr;
1519 struct qelem *top, *elem = NULL;
1521 ret_value = SUB_NORMAL;
1522 args[MAP_MACHINE] = "*";
1523 args[MAP_CLUSTER] = name;
1524 stat = do_mr_query("get_machine_to_cluster_map", 2, args,
1525 StoreInfo, (char *)&elem);
1526 if (stat && stat != MR_NO_MATCH)
1528 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1531 if (stat == MR_SUCCESS)
1533 elem = top = QueueTop(elem);
1536 sprintf(temp_buf, "The cluster %s has the following machines in it:",
1538 Put_message(temp_buf);
1541 char **info = (char **) elem->q_data;
1542 Print(1, &info[MAP_MACHINE], (char *) NULL);
1543 elem = elem->q_forw;
1545 ptr = "Remove ** ALL ** these machines from this cluster?";
1547 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1551 Put_message("Aborting...");
1564 char **info = (char **) elem->q_data;
1565 if ((stat = do_mr_query("delete_machine_from_cluster",
1566 2, info, Scream, NULL)))
1568 ret_value = SUB_ERROR;
1569 com_err(program_name, stat,
1570 " in delete_machine_from_cluster.");
1572 "Machine %s ** NOT ** removed from cluster %s.",
1573 info[MAP_MACHINE], info[MAP_CLUSTER]);
1574 Put_message(temp_buf);
1576 elem = elem->q_forw;
1583 /* Function Name: RealDeleteCluster
1584 * Description: Actually performs the cluster deletion.
1585 * Arguments: info - all information about this cluster.
1586 * one_cluster - If true then there was only one cluster in
1587 * the queue, and we should confirm.
1591 static void RealDeleteCluster(char **info, Bool one_cluster)
1594 char temp_buf[BUFSIZ];
1597 "Are you sure the you want to delete the cluster %s (y/n) ?",
1599 if (!one_cluster || Confirm(temp_buf))
1601 if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR)
1603 if ((stat = do_mr_query("delete_cluster", 1,
1604 &info[C_NAME], Scream, NULL)))
1606 com_err(program_name, stat, " in delete_cluster.");
1607 sprintf(temp_buf, "Cluster %s ** NOT ** deleted.", info[C_NAME]);
1608 Put_message(temp_buf);
1612 sprintf(temp_buf, "cluster %s successfully deleted.",
1614 Put_message(temp_buf);
1620 /* Function Name: DeleteCluster
1621 * Description: This function removes a cluster from the database.
1622 * Arguments: argc, argv - the name of the cluster is stored in argv[1].
1623 * Returns: DM_NORMAL.
1626 int DeleteCluster(int argc, char **argv)
1630 top = GetMCInfo(CLUSTER, argv[1], NULL);
1631 QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
1637 /* ----------- Cluster Data Menu -------------- */
1639 /* Function Name: ShowClusterData
1640 * Description: This function shows the services for one cluster.
1641 * Arguments: argc, argv - The name of the cluster is argv[1].
1642 * The label of the data in argv[2].
1643 * Returns: DM_NORMAL.
1646 int ShowClusterData(int argc, char **argv)
1648 struct qelem *elem, *top;
1651 top = elem = GetMCInfo(DATA, argv[1], argv[2]);
1654 info = (char **) elem->q_data;
1655 PrintClusterData(info);
1656 elem = elem->q_forw;
1662 /* Function Name: AddClusterData
1663 * Description: This function adds some data to the cluster.
1664 * Arguments: argv, argc: argv[1] - the name of the cluster.
1665 * argv[2] - the label of the data.
1666 * argv[3] - the data.
1667 * Returns: DM_NORMAL.
1670 int AddClusterData(int argc, char **argv)
1674 if ((stat = do_mr_query("add_cluster_data", 3, argv + 1,
1675 Scream, (char *) NULL)))
1676 com_err(program_name, stat, " in AddClusterData.");
1680 /* Function Name: RealRemoveClusterData
1681 * Description: actually removes the cluster data.
1682 * Arguments: info - all info necessary to remove the cluster, in an array
1684 * one_item - if true then the queue has only one elem and we
1689 static void RealRemoveClusterData(char **info, Bool one_item)
1695 temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1696 PrintClusterData(info);
1697 if (!one_item || Confirm(temp_ptr))
1699 if ((stat = do_mr_query("delete_cluster_data", 3, info,
1700 Scream, (char *) NULL)))
1702 com_err(program_name, stat, " in DeleteClusterData.");
1703 Put_message("Data not removed.");
1706 Put_message("Removal successful.");
1710 /* Function Name: RemoveClusterData
1711 * Description: This function removes data on a given cluster.
1712 * Arguments: argv, argc: argv[1] - the name of the cluster.
1713 * argv[2] - the label of the data.
1714 * argv[3] - the data.
1715 * Returns: DM_NORMAL.
1718 int RemoveClusterData(int argc, char **argv)
1722 top = GetMCInfo(DATA, argv[1], argv[2]);
1723 QueryLoop(top, PrintClusterData, RealRemoveClusterData,
1724 "Remove data from cluster");
1730 /* Function Name: MachineToClusterMap
1731 * Description: This Retrieves the mapping between machine and cluster
1732 * Arguments: argc, argv - argv[1] -> machine name or wildcard.
1733 * argv[2] -> cluster name or wildcard.
1737 int MachineToClusterMap(int argc, char **argv)
1739 struct qelem *elem, *top;
1740 char *tmpname, temp_buf[256];
1742 tmpname = canonicalize_hostname(strsave(argv[1]));
1743 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
1745 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1747 Put_message(temp_buf);
1749 top = elem = GetMCInfo(MAP, tmpname, argv[2]);
1751 Put_message(""); /* blank line on screen */
1754 char **info = (char **) elem->q_data;
1756 elem = elem->q_forw;