X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/85ca828a9c0e9390982eacefe9b3cbee661eb5bb..3272891dbc597360973dcadd0c69b1cadec2870b:/clients/moira/cluster.c diff --git a/clients/moira/cluster.c b/clients/moira/cluster.c index adf9ad3c..88aeed65 100644 --- a/clients/moira/cluster.c +++ b/clients/moira/cluster.c @@ -1,51 +1,124 @@ -#ifndef lint - static char rcsid_module_c[] = "$Header$"; -#endif lint - -/* This is the file cluseter.c for allmaint, the SMS client that allows - * a user to maintaint most important parts of the SMS database. - * It Contains: - * +/* $Id$ + * + * This is the file cluster.c for the Moira Client, which allows users + * to quickly and easily maintain most parts of the Moira database. + * It Contains: + * * Created: 4/22/88 * By: Chris D. Peterson - * Based upon: Clusermaint.c by marcus: 87/07/22 * - * $Source$ - * $Author$ - * $Header$ - * - * Copyright 1987, 1988 by the Massachusetts Institute of Technology. - * - * For further information on copyright and distribution - * see the file mit-copyright.h + * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * . */ /* BTW: for anyone who cares MCD is short for Machine, Cluster, Data. */ -#include -#include -#include -#include +#include +#include +#include +#include -#include "mit-copyright.h" -#include "allmaint.h" -#include "allmaint_funcs.h" +#include "defs.h" +#include "f_defs.h" #include "globals.h" -#include "infodefs.h" -#define MACHINE 0 -#define CLUSTER 1 -#define DATA 2 -#define MAP 3 +#include + +#ifdef HAVE_UNAME +#include +#endif + +#ifndef _WIN32 +#include +#include +#include +#endif /* _WIN32 */ + +#include +#include +#include +#include + +void PrintAliases(char **info); +static void PrintMachine(char **info); +struct mqelem *GetMCInfo(int type, char *name1, char *name2); +struct mqelem *GetMachineByOwner(char *type, char *name); +char **AskMCDInfo(char **info, int type, Bool name); +int CheckAndRemoveFromCluster(char *name, Bool ask_user); +int CheckAndRemoveCnames(char *name, Bool ask_user); +int CheckAndRemoveMachines(char *name, Bool ask_first); + +static char *PrintContainerInfo(char **info); +static void RealUpdateContainer(char **info, Bool junk); +static void RealDeleteContainer(char **info, Bool one_container); +static void RealRemoveMachineFromContainer(char **info, Bool one_contmap); + +#define MACHINE 0 +#define CLUSTER 1 +#define DATA 2 +#define MAP 3 +#define SUBNET 4 +#define CNAME 5 +#define CONTAINER 6 +#define CONTMAP 7 #define M_DEFAULT_TYPE DEFAULT_NONE #define C_DEFAULT_DESCRIPT DEFAULT_NONE #define C_DEFAULT_LOCATION DEFAULT_NONE +#define CON_DEFAULT_TYPE DEFAULT_NONE + #define CD_DEFAULT_LABEL DEFAULT_NONE #define CD_DEFAULT_DATA DEFAULT_NONE +#define S_DEFAULT_LOW "18.0.0.20" +#define S_DEFAULT_HIGH "18.0.2.249" + +static char *states[] = { + "Reserved (0)", + "Active (1)", + "None (2)", + "Deleted (3)" +}; + +static char *subnet_states[] = { + "Reserved (0)", + "Billable (1)", + "Private, 10 Mbps (2)", + "Private, 100 Mbps (3)", + "Private, Other (4)", + "Resnet, Dorm (5)", + "Infrastructure (6)", + "Private, 1000 Mbps (7)", + "Resnet, FSILG (8)" +}; + +static char *MacState(int state) +{ + static char buf[BUFSIZ]; + + if (state < 0 || state > 3) + { + sprintf(buf, "Unknown (%d)", state); + return buf; + } + return states[state]; +} + +static char *SubnetState(int state) +{ + static char buf[BUFSIZ]; + + if (state < 0 || state > 8) + { + sprintf(buf, "Unknown (%d)", state); + return buf; + } + return subnet_states[state]; +} + /* -------------------- Set Defaults -------------------- */ /* Function Name: SetMachineDefaults @@ -55,14 +128,26 @@ * Returns: info - the array. */ -char ** -SetMachineDefaults(info, name) -char ** info, *name; +static char **SetMachineDefaults(char **info, char *name) { - info[M_NAME] = Strsave(name); - info[M_TYPE] = Strsave(M_DEFAULT_TYPE); - info[M_MODBY] = info[M_MODTIME] = info[M_MODWITH] = info[M_END] = NULL; - return(info); + info[M_NAME] = strdup(name); + info[M_VENDOR] = strdup(M_DEFAULT_TYPE); + info[M_MODEL] = strdup(M_DEFAULT_TYPE); + info[M_OS] = strdup(M_DEFAULT_TYPE); + info[M_LOC] = strdup(M_DEFAULT_TYPE); + info[M_CONTACT] = strdup(M_DEFAULT_TYPE); + info[M_BILL_CONTACT] = strdup(M_DEFAULT_TYPE); + info[M_ACCT_NUMBER] = strdup(""); + info[M_USE] = strdup("0"); + info[M_STAT] = strdup("1"); + info[M_SUBNET] = strdup("NONE"); + info[M_ADDR] = strdup("unique"); + info[M_OWNER_TYPE] = strdup("NONE"); + info[M_OWNER_NAME] = strdup("NONE"); + info[M_ACOMMENT] = strdup(""); + info[M_OCOMMENT] = strdup(""); + info[17] = info[18] = NULL; + return info; } /* Function Name: SetClusterDefaults @@ -72,100 +157,231 @@ char ** info, *name; * Returns: info - the array. */ -char ** -SetClusterDefaults(info, name) -char ** info, *name; +static char **SetClusterDefaults(char **info, char *name) { - info[C_NAME] = Strsave(name); - info[C_DESCRIPT] = Strsave(C_DEFAULT_DESCRIPT); - info[C_LOCATION] = Strsave(C_DEFAULT_LOCATION); - info[C_MODBY] = info[C_MODTIME] = info[C_MODWITH] = info[C_END] = NULL; - return(info); + info[C_NAME] = strdup(name); + info[C_DESCRIPT] = strdup(C_DEFAULT_DESCRIPT); + info[C_LOCATION] = strdup(C_DEFAULT_LOCATION); + info[C_MODBY] = info[C_MODTIME] = info[C_MODWITH] = info[C_END] = NULL; + return info; } -/* Function Name: SetClusterDataDefaults - * Description: Sets cluster data defaults. +static char **SetContainerDefaults(char **info, char *name) +{ + info[CON_NAME] = strdup(name); + info[CON_PUBLIC] = strdup(DEFAULT_NO); + info[CON_DESCRIPT] = strdup(CON_DEFAULT_TYPE); + info[CON_LOCATION] = strdup(CON_DEFAULT_TYPE); + info[CON_CONTACT] = strdup(CON_DEFAULT_TYPE); + info[CON_OWNER_TYPE] = strdup("NONE"); + info[CON_OWNER_NAME] = strdup("NONE"); + info[CON_MEMACE_TYPE] = strdup("NONE"); + info[CON_MEMACE_NAME] = strdup("NONE"); + info[CON_MODBY] = info[CON_MODTIME] = info[CON_MODWITH] = NULL; + info[CON_END] = NULL; + return info; +} + +/* Function Name: SetSubnetDefaults + * Description: sets Subnet defaults. * Arguments: info - an array to put the defaults into. - * name - name of the Cluster. + * name - name of the Subnet. * Returns: info - the array. */ -char ** -SetClusterDataDefaults(info, name) -char ** info, *name; +static char **SetSubnetDefaults(char **info, char *name) { - info[CD_NAME] = Strsave(name); - info[CD_LABEL] = Strsave(CD_DEFAULT_LABEL); - info[CD_DATA] = Strsave(CD_DEFAULT_DATA); -/*info[CD_MODBY] = info[CD_MODTIME] = info[CD_MODWITH] = info[CD_END] = NULL;*/ - info[CD_END] = NULL; - return(info); + char buf[256]; + + info[SN_NAME] = strdup(name); + info[SN_DESC] = strdup(""); + info[SN_STATUS] = strdup("1"); + info[SN_CONTACT] = strdup(DEFAULT_NONE); + info[SN_ACCT_NUMBER] = strdup(""); + sprintf(buf, "%ld", ntohl(inet_addr("18.255.0.0"))); + info[SN_ADDRESS] = strdup(buf); + sprintf(buf, "%ld", ntohl(inet_addr("255.255.0.0"))); + info[SN_MASK] = strdup(buf); + sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_LOW))); + info[SN_LOW] = strdup(buf); + sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_HIGH))); + info[SN_HIGH] = strdup(buf); + info[SN_PREFIX] = strdup(""); + info[SN_ACE_TYPE] = strdup("LIST"); + info[SN_ACE_NAME] = strdup("network"); + info[SN_MODBY] = info[SN_MODTIME] = info[SN_MODWITH] = info[SN_END] = NULL; + return info; } /* -------------------- General Functions -------------------- */ +static char aliasbuf[256]; + +void PrintAliases(char **info) +{ + if (strlen(aliasbuf) == 0) + sprintf(aliasbuf, "Aliases: %s", info[0]); + else + { + strcat(aliasbuf, ", "); + strcat(aliasbuf, info[0]); + } +} + + /* Function Name: PrintMachInfo - * Description: This function Prints out the Machine info in + * Description: This function Prints out the Machine info in * a coherent form. * Arguments: info - array of information about a machine. - * Returns: none. + * Returns: The name of the Machine + */ + +static char *PrintMachInfo(char **info) +{ + char buf[BUFSIZ], tbuf[256]; + char *args[3]; + struct mqelem *elem = NULL, *elem2 = NULL; + int stat; + + Put_message(""); + sprintf(buf, "Machine: %s", info[M_NAME]); + Put_message(buf); + args[0] = "*"; + args[1] = info[M_NAME]; + if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem))) + { + if (stat != MR_NO_MATCH) + com_err(program_name, stat, " looking up aliases"); + } + else + { + aliasbuf[0] = 0; + Loop(QueueTop(elem), (void (*)(char **)) PrintAliases); + FreeQueue(elem); + Put_message(aliasbuf); + } + sprintf(tbuf, "%s %s", info[M_OWNER_TYPE], + strcmp(info[M_OWNER_TYPE], "NONE") ? info[M_OWNER_NAME] : ""); + sprintf(buf, "Address: %-16s Network: %-16s", + info[M_ADDR], info[M_SUBNET]); + Put_message(buf); + sprintf(buf, "Owner: %-16s Use data: %s", tbuf, info[M_INUSE]); + Put_message(buf); + sprintf(buf, "Status: %-16s Changed: %s", + MacState(atoi(info[M_STAT])), info[M_STAT_CHNG]); + Put_message(buf); + Put_message(""); + sprintf(buf, "Vendor: %-16s Location: %s", info[M_VENDOR], + info[M_LOC]); + Put_message(buf); + sprintf(buf, "Model: %-16s Contact: %s", info[M_MODEL], + info[M_CONTACT]); + Put_message(buf); + sprintf(buf, "OS: %-16s Billing Contact: %s", info[M_OS], + info[M_BILL_CONTACT]); + Put_message(buf); + sprintf(buf, "Opt: %-16s Account Number: %s", info[M_USE], + info[M_ACCT_NUMBER]); + Put_message(buf); + Put_message(""); + sprintf(buf, "Adm cmt: %s", info[M_ACOMMENT]); + Put_message(buf); + sprintf(buf, "Op cmt: %s", info[M_OCOMMENT]); + Put_message(buf); + Put_message(""); + sprintf(buf, "Created by %s on %s", info[M_CREATOR], info[M_CREATED]); + Put_message(buf); + sprintf(buf, MOD_FORMAT, info[M_MODBY], info[M_MODTIME], info[M_MODWITH]); + Put_message(buf); + /* Do a get_subnet for the machine's subnet. We need to know if it's + * Private. + */ + args[0] = info[M_SUBNET]; + stat = do_mr_query("get_subnet", 1, args, StoreInfo, &elem2); + if (stat) + com_err(program_name, stat, " looking up subnet info"); + else if (atoi(((char **)elem2->q_data)[2]) == SNET_STATUS_PRIVATE_10MBPS || + atoi(((char **)elem2->q_data)[2]) == SNET_STATUS_PRIVATE_100MBPS || + atoi(((char **)elem2->q_data)[2]) == SNET_STATUS_PRIVATE_1000MBPS) + { + Put_message(""); + sprintf(buf, "Warning: This host is on a private subnet."); + Put_message(buf); + sprintf(buf, "Billing information shown is superseded by billing information for the subnet."); + Put_message(buf); + FreeQueue(elem2); + } + + return info[M_NAME]; +} + +/* Function Name: PrintMachine + * Description: Prints the name of a machine record + * Arguments: info - array of information about the machine. + * Returns: nothing. */ -void -PrintMachInfo(info) -char ** info; +static void PrintMachine(char **info) { - char buf[BUFSIZ]; + char buf[BUFSIZ]; - Put_message(""); - sprintf(buf, "Machine: %-30s Type: %s", info[M_NAME], info[M_TYPE]); - Put_message(buf); - sprintf(buf, "Last Modified at %s, by %s with %s",info[M_MODTIME], - info[M_MODBY], info[M_MODWITH]); - Put_message(buf); + sprintf(buf, "Machine: %s", info[M_NAME]); + Put_message(buf); +} + +/* Function Name: PrintCname + * Description: Prints the Data on a host alias + * Arguments: info a pointer to the data array. + * Returns: The name of the alias. + */ + +static char *PrintCname(char **info) +{ + char buf[BUFSIZ]; + + sprintf(buf, "Alias: %-32s Canonical Name: %s", info[0], info[1]); + Put_message(buf); + return info[0]; } /* Function Name: PrintClusterInfo - * Description: This function Prints out the cluster info + * Description: This function Prints out the cluster info * in a coherent form. * Arguments: info - array of information about a cluster. - * Returns: none. + * Returns: The name of the cluster. */ -void -PrintClusterInfo(info) -char ** info; +static char *PrintClusterInfo(char **info) { - char buf[BUFSIZ]; - - Put_message(""); - sprintf(buf, "Cluster: %s", info[C_NAME]); - Put_message(buf); - sprintf(buf, "Description: %s", info[C_DESCRIPT]); - Put_message(buf); - sprintf(buf, "Location: %s", info[C_LOCATION]); - Put_message(buf); - sprintf(buf, "Last Modified at %s, by %s with %s",info[C_MODTIME], - info[C_MODBY], info[C_MODWITH]); - Put_message(buf); + char buf[BUFSIZ]; + + Put_message(""); + sprintf(buf, "Cluster: %s", info[C_NAME]); + Put_message(buf); + sprintf(buf, "Description: %s", info[C_DESCRIPT]); + Put_message(buf); + sprintf(buf, "Location: %s", info[C_LOCATION]); + Put_message(buf); + sprintf(buf, MOD_FORMAT, info[C_MODBY], info[C_MODTIME], info[C_MODWITH]); + Put_message(buf); + return info[C_NAME]; } /* Function Name: PrintClusterData * Description: Prints the Data on a cluster * Arguments: info a pointer to the data array. - * Returns: none + * Returns: The name of the cluster. */ -void -PrintClusterData(info) -char ** info; +static char *PrintClusterData(char **info) { - char buf[BUFSIZ]; + char buf[BUFSIZ]; - Put_message(""); - sprintf(buf, "Cluster: %-20s Label: %-15s Data: %s", - info[CD_NAME], info[CD_LABEL], info[CD_DATA]); - Put_message(buf); + Put_message(""); + sprintf(buf, "Cluster: %-20s Label: %-15s Data: %s", + info[CD_NAME], info[CD_LABEL], info[CD_DATA]); + Put_message(buf); + return info[CD_NAME]; } /* Function Name: PrintMCMap @@ -174,14 +390,60 @@ char ** info; * Returns: none */ -void -PrintMCMap(info) -char ** info; +static char *PrintMCMap(char **info) +{ + char buf[BUFSIZ]; + sprintf(buf, "Cluster: %-30s Machine: %-20s", + info[MAP_CLUSTER], info[MAP_MACHINE]); + Put_message(buf); + return ""; /* Used by QueryLoop(). */ +} + +/* Function Name: PrintSubnetInfo + * Description: This function Prints out the subnet info + * in a coherent form. + * Arguments: info - array of information about a subnet. + * Returns: The name of the subnet. + */ + +static char *PrintSubnetInfo(char **info) { - char buf[BUFSIZ]; - sprintf(buf, "Cluster: %-30s Machine: %-20s", - info[MAP_CLUSTER], info[MAP_MACHINE]); - Put_message(buf); + char buf[BUFSIZ]; + struct in_addr addr, mask, low, high; + + Put_message(""); + sprintf(buf, " Network: %s", info[SN_NAME]); + Put_message(buf); + sprintf(buf, " Description: %s", info[SN_DESC]); + Put_message(buf); + sprintf(buf, " Status: %s", SubnetState(atoi(info[SN_STATUS]))); + Put_message(buf); + sprintf(buf, " Contact: %s", info[SN_CONTACT]); + Put_message(buf); + sprintf(buf, " Account Number: %s", info[SN_ACCT_NUMBER]); + Put_message(buf); + addr.s_addr = htonl(atoi(info[SN_ADDRESS])); + mask.s_addr = htonl(atoi(info[SN_MASK])); + low.s_addr = htonl(atoi(info[SN_LOW])); + high.s_addr = htonl(atoi(info[SN_HIGH])); + /* screwy sequence is here because inet_ntoa returns a pointer to + a static buf. If it were all one sprintf, the last value would + appear 4 times. */ + sprintf(buf, " Address: %s Mask: ", inet_ntoa(addr)); + strcat(buf, inet_ntoa(mask)); + strcat(buf, "\n High: "); + strcat(buf, inet_ntoa(high)); + strcat(buf, " Low: "); + strcat(buf, inet_ntoa(low)); + Put_message(buf); + sprintf(buf, "Hostname prefix: %s", info[SN_PREFIX]); + Put_message(buf); + sprintf(buf, " Owner: %s %s\n", info[SN_ACE_TYPE], + strcmp(info[SN_ACE_TYPE], "NONE") ? info[SN_ACE_NAME] : ""); + Put_message(buf); + sprintf(buf, MOD_FORMAT, info[SN_MODBY], info[SN_MODTIME], info[SN_MODWITH]); + Put_message(buf); + return info[SN_NAME]; } /* Function Name: GetMCInfo. @@ -192,135 +454,434 @@ char ** info; * Returns: the top element of a queue containing the data or NULL. */ -struct qelem * -GetMCInfo(type, name1, name2) -int type; -char * name1, *name2; +struct mqelem *GetMCInfo(int type, char *name1, char *name2) { + int stat; + struct mqelem *elem = NULL; + char *args[5]; - int stat; - struct qelem * elem = NULL; - char * args[2]; - - switch (type) { + switch (type) + { case MACHINE: - if ( (stat = sms_query("get_machine", 1, &name1, - StoreInfo, &elem)) != 0) { + args[0] = name1; + args[1] = args[2] = args[3] = "*"; + if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem))) + { + if (stat == MR_NO_MATCH) + { + char buf[128]; + sprintf(buf, "Machine '%s' is not in the database.", name1); + Put_message(buf); + } + else com_err(program_name, stat, " in get_machine."); - return(NULL); + return NULL; + } + break; + case CNAME: + args[0] = name1; + args[1] = name2; + if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem))) + { + com_err(program_name, stat, " in get_hostalias."); + return NULL; } - break; + break; + case SUBNET: + if ((stat = do_mr_query("get_subnet", 1, &name1, StoreInfo, &elem))) + { + if (stat == MR_NO_MATCH) + { + char buf[128]; + sprintf(buf, "Network '%s' is not in the database.", name1); + Put_message(buf); + } + else + com_err(program_name, stat, " in get_subnet."); + return NULL; + } + break; case CLUSTER: - if ( (stat = sms_query("get_cluster", 1, &name1, - StoreInfo, &elem)) != 0) { - com_err(program_name, stat, " in get_cluster."); - return(NULL); + if ((stat = do_mr_query("get_cluster", 1, &name1, StoreInfo, &elem))) + { + com_err(program_name, stat, " in get_cluster."); + return NULL; } - break; + break; case MAP: - args[MAP_MACHINE] = name1; - args[MAP_CLUSTER] = name2; - if ( (stat = sms_query("get_machine_to_cluster_map", 2, args, - StoreInfo, &elem)) != 0) { - com_err(program_name, stat, " in get_machine_to_cluster_map."); - return(NULL); + args[MAP_MACHINE] = name1; + args[MAP_CLUSTER] = name2; + if ((stat = do_mr_query("get_machine_to_cluster_map", 2, args, + StoreInfo, &elem))) + { + com_err(program_name, stat, " in get_machine_to_cluster_map."); + return NULL; } - break; + break; case DATA: - args[CD_NAME] = name1; - args[CD_LABEL] = name2; - if ( (stat = sms_query("get_cluster_data", 2, args, - StoreInfo, &elem)) != 0) { - com_err(program_name, stat, " in get_cluster_data."); - return(NULL); + args[CD_NAME] = name1; + args[CD_LABEL] = name2; + if ((stat = do_mr_query("get_cluster_data", 2, args, StoreInfo, &elem))) + { + com_err(program_name, stat, " in get_cluster_data."); + return NULL; + } + break; + case CONTAINER: + args[CON_NAME] = name1; + if ((stat = do_mr_query("get_container", 1, &name1, StoreInfo, &elem))) + { + com_err(program_name, stat, " in get_container."); + return NULL; + } + break; + case CONTMAP: + args[0] = name1; + if ((stat = do_mr_query("get_machine_to_container_map", 1, &name1, + StoreInfo, &elem))) + { + com_err(program_name, stat, " in get_machine_to_container_map."); + return NULL; } } - return(QueueTop(elem)); + return QueueTop(elem); } /* Function Name: AskMCDInfo. - * Description: This function askes the user for information about a + * Description: This function askes the user for information about a * machine and saves it into a structure. * Arguments: info - a pointer the information to ask about * type - type of information - MACHINE * CLUSTER * DATA + * CONTAINER * name - T/F : change the name of this type. * Returns: none. */ -char ** -AskMCDInfo(info, type, name) -char ** info; -int type; -Bool name; +char **AskMCDInfo(char **info, int type, Bool name) { - char temp_buf[BUFSIZ], *newname; + char temp_buf[BUFSIZ], *newname, *oldnewname; - switch (type) { + switch (type) + { case MACHINE: - sprintf(temp_buf, "Setting the information for the Machine %s.", - info[M_NAME]); - break; + sprintf(temp_buf, "\nSetting the information for the Machine %s...", + info[M_NAME]); + break; + case SUBNET: + sprintf(temp_buf, "Setting the information for the Network %s...", + info[SN_NAME]); + break; case CLUSTER: - sprintf(temp_buf, "Setting the information for the Cluster %s.", - info[C_NAME]); - break; + sprintf(temp_buf, "Setting the information for the Cluster %s...", + info[C_NAME]); + break; case DATA: - sprintf(temp_buf, "Setting the Data for the Cluster %s.", - info[CD_NAME]); - break; + sprintf(temp_buf, "Setting the Data for the Cluster %s...", + info[CD_NAME]); + break; + case CONTAINER: + sprintf(temp_buf, "Setting the Data for the Container %s...", + info[CON_NAME]); + break; } - Put_message(temp_buf); + Put_message(temp_buf); - if (name) { - switch (type) { + if (name) + { + switch (type) + { case MACHINE: - newname = Strsave(info[M_NAME]); - GetValueFromUser("The new name for this machine? ", &newname); - strcpy(temp_buf, CanonicalizeHostname(newname)); - free(newname); - newname = Strsave(temp_buf); - break; + newname = strdup(info[M_NAME]); + if (GetValueFromUser("The new name for this machine? ", &newname) == + SUB_ERROR) + return NULL; + oldnewname = strdup(newname); + newname = canonicalize_hostname(newname); + if (strcasecmp(newname, oldnewname) && *oldnewname != '"') + { + sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'\n", + oldnewname, newname); + Put_message(temp_buf); + } + free(oldnewname); + break; + case SUBNET: + newname = strdup(info[SN_NAME]); + if (GetValueFromUser("The new name for this network? ", &newname) == + SUB_ERROR) + return NULL; + break; case CLUSTER: - newname = Strsave(info[C_NAME]); - GetValueFromUser("The new name for this cluster? ", - &newname); - break; + newname = strdup(info[C_NAME]); + if (GetValueFromUser("The new name for this cluster? ", &newname) == + SUB_ERROR) + return NULL; + break; + case CONTAINER: + newname = strdup(info[CON_NAME]); + if (GetValueFromUser("The new name for this container? ", &newname) + == SUB_ERROR) + return NULL; + break; default: - Put_message("Unknown type in AskMCDInfo, programmer botch"); - return(NULL); + Put_message("Unknown type in AskMCDInfo, programmer botch"); + return NULL; } } - switch(type) { + switch (type) + { case MACHINE: - GetValueFromUser("Machine's Type:", &info[M_TYPE]); - FreeAndClear(&info[M_MODTIME], TRUE); - FreeAndClear(&info[M_MODBY], TRUE); - FreeAndClear(&info[M_MODWITH], TRUE); - break; + if (GetValueFromUser("Machine's vendor", &info[M_VENDOR]) == SUB_ERROR) + return NULL; + if (GetValueFromUser("Machine's model", &info[M_MODEL]) == SUB_ERROR) + return NULL; + if (GetValueFromUser("Machine's operating system", &info[M_OS]) == + SUB_ERROR) + return NULL; + if (GetValueFromUser("Machine's location", &info[M_LOC]) == SUB_ERROR) + return NULL; + if (GetValueFromUser("Machine's contact", &info[M_CONTACT]) == + SUB_ERROR) + return NULL; + if (GetValueFromUser("Machine's billing contact", + &info[M_BILL_CONTACT]) == SUB_ERROR) + return NULL; + if (GetValueFromUser("Machine's billing account number", + &info[M_ACCT_NUMBER]) == SUB_ERROR) + return NULL; + while (1) + { + int i; + if (GetValueFromUser("Machine's status (? for help)", + &info[M_STAT]) == SUB_ERROR) + return NULL; + if (isdigit(info[M_STAT][0])) + break; + Put_message("Valid status numbers:"); + for (i = 0; i < 4; i++) + Put_message(states[i]); + } + + /* there appears to be some argument mismatch between the client + * and the server.. so here is this argument shuffler. + * I have since modified this to always shuffle the arguments.. + * not just do so when performing a modify all fields request. + * The SetMachinedefaults() has been changed to reflect this. + * pray for us and may we attain enlightenment through structures. + */ + + if (name) + { + /* info did not come from SetMachineDefaults(), which does not + * initialize entry 10 (M_STAT_CHNG), therefore we can + * free it. + */ + /* This is an update of an existing machine and the structure + * was filled in thru a query to the db which does fill in this + * field. + */ + free(info[10]); + } + + info[10] = info[M_SUBNET]; + info[11] = info[M_ADDR]; + info[12] = info[M_OWNER_TYPE]; + info[13] = info[M_OWNER_NAME]; + info[14] = info[M_ACOMMENT]; + info[15] = info[M_OCOMMENT]; + + if (name) + { + if (GetValueFromUser("Machine's network (or 'none')", &info[10]) + == SUB_ERROR) + return NULL; + } + if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')", + &info[11]) == SUB_ERROR) + return NULL; + if (GetTypeFromUser("Machine's owner type", "ace_type", &info[12]) == + SUB_ERROR) + return NULL; + if (strcmp(info[12], "NONE") && + GetValueFromUser("Owner's Name", &info[13]) == SUB_ERROR) + return NULL; + if (!strcmp(info[12], "KERBEROS")) + { + char *canon; + + mrcl_validate_kerberos_member(info[13], &canon); + if (mrcl_get_message()) + Put_message(mrcl_get_message()); + free(info[13]); + info[13] = canon; + } + if (GetValueFromUser("Administrative comment", &info[14]) == SUB_ERROR) + return NULL; + if (GetValueFromUser("Operational comment", &info[15]) == SUB_ERROR) + return NULL; + info[16] = NULL; + FreeAndClear(&info[17], TRUE); + FreeAndClear(&info[18], TRUE); + break; + case SUBNET: + if (GetValueFromUser("Network description", &info[SN_DESC]) == SUB_ERROR) + return NULL; + while (1) + { + int i; + if (GetValueFromUser("Network's status (? for help)", + &info[SN_STATUS]) == SUB_ERROR) + return NULL; + if (isdigit(info[SN_STATUS][0])) + break; + Put_message("Valid status numbers:"); + for (i = 0; i < 9; i++) + Put_message(subnet_states[i]); + } + if (GetValueFromUser("Network's contact", &info[SN_CONTACT]) == SUB_ERROR) + return NULL; + if (GetValueFromUser("Network's billing account number", + &info[SN_ACCT_NUMBER]) == SUB_ERROR) + return NULL; + if (GetAddressFromUser("Network address", &info[SN_ADDRESS]) == SUB_ERROR) + return NULL; + if (GetAddressFromUser("Network mask", &info[SN_MASK]) == SUB_ERROR) + return NULL; + if (atoi(info[SN_LOW]) == (int)ntohl(inet_addr(S_DEFAULT_LOW))) + { + struct in_addr low; + unsigned long mask, addr; + + addr = atoi(info[SN_ADDRESS]); + mask = atoi(info[SN_MASK]); + low.s_addr = atoi(info[SN_LOW]); + low.s_addr = (low.s_addr & ~mask) | (addr & mask); + free(info[SN_LOW]); + sprintf(temp_buf, "%ld", low.s_addr); + info[SN_LOW] = strdup(temp_buf); + } + if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) == + SUB_ERROR) + return NULL; + if (atoi(info[SN_HIGH]) == (int)ntohl(inet_addr(S_DEFAULT_HIGH))) + { + struct in_addr high; + unsigned long mask, addr; + + addr = atoi(info[SN_ADDRESS]); + mask = atoi(info[SN_MASK]); + high.s_addr = atoi(info[SN_HIGH]); + high.s_addr = (high.s_addr & ~mask) | (addr & mask); + free(info[SN_HIGH]); + sprintf(temp_buf, "%ld", high.s_addr); + info[SN_HIGH] = strdup(temp_buf); + } + if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) == + SUB_ERROR) + return NULL; + if (GetValueFromUser("Hostname prefix", &info[SN_PREFIX]) == SUB_ERROR) + return NULL; + if (GetTypeFromUser("Owner type", "ace_type", &info[SN_ACE_TYPE]) == + SUB_ERROR) + return NULL; + if (strcmp(info[SN_ACE_TYPE], "NONE") && + GetValueFromUser("Owner name", &info[SN_ACE_NAME]) == SUB_ERROR) + return NULL; + if (!strcmp(info[SN_ACE_TYPE], "KERBEROS")) + { + char *canon; + + mrcl_validate_kerberos_member(info[SN_ACE_NAME], &canon); + if (mrcl_get_message()) + Put_message(mrcl_get_message()); + free(info[SN_ACE_NAME]); + info[SN_ACE_NAME] = canon; + } + FreeAndClear(&info[SN_MODTIME], TRUE); + FreeAndClear(&info[SN_MODBY], TRUE); + FreeAndClear(&info[SN_MODWITH], TRUE); + break; case CLUSTER: - GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]); - GetValueFromUser("Cluster's Location:", &info[C_LOCATION]); - FreeAndClear(&info[C_MODTIME], TRUE); - FreeAndClear(&info[C_MODBY], TRUE); - FreeAndClear(&info[C_MODWITH], TRUE); - break; + if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) == + SUB_ERROR) + return NULL; + if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) == + SUB_ERROR) + return NULL; + FreeAndClear(&info[C_MODTIME], TRUE); + FreeAndClear(&info[C_MODBY], TRUE); + FreeAndClear(&info[C_MODWITH], TRUE); + break; case DATA: - GetValueFromUser("Label defining this data?", &info[CD_LABEL]); - GetValueFromUser("The data itself ? ", &info[CD_DATA]); - break; + if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) == + SUB_ERROR) + return NULL; + if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR) + return NULL; + break; + case CONTAINER: + if (GetYesNoValueFromUser("Is this a public container", + &info[CON_PUBLIC]) == SUB_ERROR) + return NULL; + if (GetValueFromUser("Container's Description:", &info[CON_DESCRIPT]) == + SUB_ERROR) + return NULL; + if (GetValueFromUser("Container's Location:", &info[CON_LOCATION]) == + SUB_ERROR) + return NULL; + if (GetValueFromUser("Container's Contact:", &info[CON_CONTACT]) == + SUB_ERROR) + return NULL; + if (GetTypeFromUser("Container's owner type", "ace_type", + &info[CON_OWNER_TYPE]) == SUB_ERROR) + return NULL; + if (strcmp(info[CON_OWNER_TYPE], "NONE") && + GetValueFromUser("Owner's Name", &info[CON_OWNER_NAME]) == SUB_ERROR) + return NULL; + if (!strcmp(info[CON_OWNER_TYPE], "KERBEROS")) + { + char *canon; + + mrcl_validate_kerberos_member(info[CON_OWNER_NAME], &canon); + if (mrcl_get_message()) + Put_message(mrcl_get_message()); + free(info[CON_OWNER_NAME]); + info[CON_OWNER_NAME] = canon; + } + if (GetTypeFromUser("Container's Membership ACL", "ace_type", + &info[CON_MEMACE_TYPE]) == SUB_ERROR) + return NULL; + if (strcmp(info[CON_MEMACE_TYPE], "NONE") && + GetValueFromUser("Membership ACL", &info[CON_MEMACE_NAME]) + == SUB_ERROR) + return NULL; + if (!strcmp(info[CON_MEMACE_TYPE], "KERBEROS")) + { + char *canon; + + mrcl_validate_kerberos_member(info[CON_MEMACE_NAME], &canon); + if (mrcl_get_message()) + Put_message(mrcl_get_message()); + free(info[CON_MEMACE_NAME]); + info[CON_MEMACE_NAME] = canon; + } + FreeAndClear(&info[CON_MODTIME], TRUE); + FreeAndClear(&info[CON_MODBY], TRUE); + FreeAndClear(&info[CON_MODWITH], TRUE); + break; } -/* - * Slide the newname into the #2 slot, this screws up all future references - * to this list. - */ - if (name) - SlipInNewName(info, newname); + /* + * Slide the newname into the #2 slot, this screws up all future references + * to this list. + */ + if (name) + SlipInNewName(info, newname); - return(info); + return info; } /* ----------- Machine Menu ----------- */ @@ -331,67 +892,173 @@ Bool name; * Returns: DM_NORMAL. */ -/* ARGSUSED */ -int -ShowMachineInfo(argc, argv) -int argc; -char **argv; +int ShowMachineInfo(int argc, char **argv) { - struct qelem *elem, *top; + struct mqelem *top; + char *tmpname; + + tmpname = canonicalize_hostname(strdup(argv[1])); + top = GetMCInfo(MACHINE, tmpname, NULL); + Loop(top, ((void (*)(char **)) PrintMachInfo)); + FreeQueue(top); + return DM_NORMAL; +} - top = elem = GetMCInfo(MACHINE, CanonicalizeHostname(argv[1]), - (char *) NULL); +/* Function Name: ShowMachineQuery + * Description: This function shows the information about a machine. + * or group of machines, which may be selected through a + * number of criteria. + * Arguments: argc, argv - the name of the machine in argv[1], + * the address of the machine in argv[2], + * the location of the machine in argv[3], + * and the contact name in argv[4]. + * any of these may be wildcards. + * Returns: DM_NORMAL. + */ - while (elem != NULL) { - char **info = (char **) elem->q_data; - PrintMachInfo(info); - elem = elem->q_forw; +int ShowMachineQuery(int argc, char **argv) +{ + int stat; + struct mqelem *top, *elem = NULL; + char *args[5]; + + if (!strcmp(argv[1], "") && !strcmp(argv[2], "") && + !strcmp(argv[3], "") && !strcmp(argv[4], "")) + { + Put_message("You must specify at least one parameter of the query."); + return DM_NORMAL; } - FreeQueue(top); - return(DM_NORMAL); + if (*argv[1]) + args[0] = canonicalize_hostname(strdup(argv[1])); + else + args[0] = "*"; + if (*argv[2]) + args[1] = argv[2]; + else + args[1] = "*"; + if (*argv[3]) + args[2] = argv[3]; + else + args[2] = "*"; + if (*argv[4]) + args[3] = argv[4]; + else + args[3] = "*"; + + if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem))) + { + if (stat == MR_NO_MATCH) + Put_message("No machine(s) found matching query in the database."); + else + com_err(program_name, stat, " in get_machine."); + return DM_NORMAL; + } + top = QueueTop(elem); + Loop(top, ((void (*)(char **)) PrintMachInfo)); + FreeQueue(top); + return DM_NORMAL; } /* Function Name: AddMachine * Description: This function adds a new machine to the database. - * Arguments: argc, argv - the name of the machine in argv[1]. + * Arguments: argc, argv - the name of the network in argv[1]. * Returns: DM_NORMAL. */ -/* ARGSUSED */ -int -AddMachine(argc, argv) -int argc; -char **argv; +int AddMachine(int argc, char **argv) { - char **args, *info[MAX_ARGS_SIZE], *name; - int stat; -/* - * Check to see if this machine already exists. - */ - name = CanonicalizeHostname(argv[1]); + char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5]; + char **rinfo; + struct mqelem *elem = NULL; + int stat; + + if (!ValidName(argv[1])) /* Checks for wildcards. */ + return DM_NORMAL; + + /* + * get the network record + */ + + if (strcasecmp(argv[1], "none") && + (stat = do_mr_query("get_subnet", 1, &argv[1], StoreInfo, &elem))) + { + if (stat == MR_NO_MATCH) + { + char buf[128]; + sprintf(buf, "Network '%s' is not in the database.", argv[1]); + Put_message(buf); + } else + com_err(program_name, stat, " in get_subnet."); + return DM_NORMAL; + } + + /* + * Check to see if this machine already exists. + */ + + name = strdup(""); /* want to put prefix here */ + if (GetValueFromUser("Machine name", &name) == SUB_ERROR) + return 0; + + name = canonicalize_hostname(strdup(name)); - if ( (stat = sms_query("get_machine", 1, &name, NullFunc, NULL)) == 0) { - Put_message("This machine already exists."); - return(DM_NORMAL); + xargs[0] = name; + xargs[1] = xargs[2] = xargs[3] = "*"; + if (!(stat = do_mr_query("get_host", 4, xargs, NULL, NULL))) + { + sprintf(buf, "The machine '%s' already exists.", name); + Put_message(buf); + free(name); + return DM_NORMAL; } - else if (stat != SMS_NO_MATCH) { - com_err(program_name, stat, " in AddMachine."); - return(DM_NORMAL); + else if (stat != MR_NO_MATCH) + { + com_err(program_name, stat, + " while checking machine '%s' in AddMachine.", name); + free(name); + return DM_NORMAL; } + rinfo = SetMachineDefaults(info, name); + rinfo[M_SUBNET] = strdup(argv[1]); + if (!(args = AskMCDInfo(rinfo, MACHINE, FALSE))) + { + Put_message("Aborted."); + return DM_NORMAL; + } + + /* + * Actually create the new Machine. + */ - args = AskMCDInfo(SetMachineDefaults(info, name), MACHINE, FALSE); + if ((stat = do_mr_query("add_host", CountArgs(args), args, NULL, NULL))) + com_err(program_name, stat, " in AddMachine."); + + FreeInfo(info); + free(name); + return DM_NORMAL; +} -/* - * Actually create the new Machine. +/* Function Name: RealUpdateMachine + * Description: Performs the actual update of the machine data. + * Arguments: info - the information on the machine to update. + * junk - an UNUSED Boolean. + * Returns: none. */ - - if ( (stat = sms_query("add_machine", CountArgs(args), - args, Scream, NULL)) != 0) - com_err(program_name, stat, " in AddMachine."); - FreeInfo(info); - return(DM_NORMAL); +static void RealUpdateMachine(char **info, Bool junk) +{ + int stat; + char **args = AskMCDInfo(info, MACHINE, TRUE); + if (!args) + { + Put_message("Aborted."); + return; + } + if ((stat = do_mr_query("update_host", CountArgs(args), args, NULL, NULL))) + com_err(program_name, stat, " in UpdateMachine."); + else + Put_message("Machine successfully updated."); } /* Function Name: UpdateMachine @@ -400,122 +1067,192 @@ char **argv; * Returns: DM_NORMAL. */ -/* ARGSUSED */ -int -UpdateMachine(argc, argv) -int argc; -char **argv; -{ - struct qelem *elem, *top; - int stat; - char **args, **info, temp_buf[BUFSIZ]; - Bool one_machine, update_it; - - elem = top = GetMCInfo( MACHINE, CanonicalizeHostname(argv[1]), - (char *) NULL); - - one_machine = (QueueCount(top) == 1); - while (elem != NULL) { - info = (char **) elem->q_data; - if (one_machine) - update_it = TRUE; - else { - sprintf(temp_buf, "Update %s (y/n/q) ? ", info[M_NAME]); - switch(YesNoQuitQuestion(temp_buf, FALSE)) { - case TRUE: - update_it = TRUE; - break; - case FALSE: - update_it = FALSE; - break; - default: - Put_message("Aborting..."); - FreeQueue(top); - return(DM_NORMAL); - } - } - if (update_it) { - args = AskMCDInfo(info, MACHINE, TRUE); - if ( (stat = sms_query("update_machine", CountArgs(args), - args, Scream, NULL)) != 0) - com_err(program_name, stat, " in UpdateMachine."); - } - elem = elem->q_forw; - } - FreeQueue(top); - return(DM_NORMAL); +int UpdateMachine(int argc, char **argv) +{ + struct mqelem *top; + char *tmpname; + + tmpname = canonicalize_hostname(strdup(argv[1])); + top = GetMCInfo(MACHINE, tmpname, NULL); + QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine"); + + FreeQueue(top); + free(tmpname); + return DM_NORMAL; } /* Function Name: CheckAndRemoveFromCluster * Description: This func tests to see if a machine is in a cluster. * and if so then removes it - * Arguments: name - name of the machine (already Canonocalized). + * Arguments: name - name of the machine (already Canonicalized). * ask_user- query the user before removing if from clusters? - * Returns: SMS_ERROR if machine left in a cluster, or sms_error. + * Returns: MR_ERROR if machine left in a cluster, or mr_error. */ -int -CheckAndRemoveFromCluster(name, ask_user) -char * name; -Bool ask_user; -{ - register int stat, ret_value; - Bool delete_it; - char *args[10], temp_buf[BUFSIZ], *ptr; - struct qelem *top, *elem = NULL; - - ret_value = SUB_NORMAL; - args[0] = name; - args[1] = "*"; - stat = sms_query("get_machine_to_cluster_map", 2, args, - StoreInfo, &elem); - if (stat && stat != SMS_NO_MATCH) { - com_err(program_name, stat, " in get_machine_to_cluster_map."); - return(DM_NORMAL); - } - if (stat == 0) { - elem = top = QueueTop(elem); - if (ask_user) { - sprintf(temp_buf, "%s is assigned to the following clusters.", - name); - Put_message(temp_buf); - while (elem != NULL) { - char **info = (char **) elem->q_data; - Print(1, &info[MAP_CLUSTER], (char *) NULL); - elem = elem->q_forw; +int CheckAndRemoveFromCluster(char *name, Bool ask_user) +{ + int stat, ret_value; + Bool delete_it; + char *args[10], temp_buf[BUFSIZ], *ptr; + struct mqelem *top, *elem = NULL; + + ret_value = SUB_NORMAL; /* initialize ret_value. */ + args[0] = name; + args[1] = "*"; + stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem); + if (stat && stat != MR_NO_MATCH) + { + com_err(program_name, stat, " in get_machine_to_cluster_map."); + return DM_NORMAL; + } + if (stat == MR_SUCCESS) + { + elem = top = QueueTop(elem); + if (ask_user) + { + sprintf(temp_buf, "%s is assigned to the following clusters.", name); + Put_message(temp_buf); + Loop(top, (void (*)(char **)) PrintMCMap); + ptr = "Remove this machine from ** ALL ** these clusters?"; + if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */ + delete_it = TRUE; + else + { + Put_message("Aborting..."); + FreeQueue(top); + return SUB_ERROR; } - ptr = "Remove this machine from ** ALL ** these clusters?"; - - if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */ - delete_it = TRUE; - else { - Put_message("Aborting..."); - FreeQueue(top); - return(SUB_ERROR); + } + else + delete_it = TRUE; + + if (delete_it) + { + while (elem) + { + char **info = elem->q_data; + if ((stat = do_mr_query("delete_machine_from_cluster", + 2, info, NULL, NULL))) + { + ret_value = SUB_ERROR; + com_err(program_name, stat, + " in delete_machine_from_cluster."); + sprintf(temp_buf, + "Machine %s ** NOT ** removed from cluster %s.", + info[MAP_MACHINE], info[MAP_CLUSTER]); + Put_message(temp_buf); + } + elem = elem->q_forw; } } - else + } + return ret_value; +} + +/* Function Name: CheckAndRemoveCnames + * Description: This func tests to see if a machine has cnames, + * and if so then removes them. + * Arguments: name - name of the machine (already Canonicalized). + * ask_user- query the user before removing cnames? + * Returns: MR_ERROR if machine left with a cname, or mr_error. + */ + +int CheckAndRemoveCnames(char *name, Bool ask_user) +{ + int stat, ret_value; + Bool delete_it; + char *args[10], temp_buf[BUFSIZ], *ptr; + struct mqelem *top, *elem = NULL; + + ret_value = SUB_NORMAL; + args[0] = "*"; + args[1] = name; + stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem); + if (stat && stat != MR_NO_MATCH) + { + com_err(program_name, stat, " in get_hostalias."); + return DM_NORMAL; + } + if (stat == MR_SUCCESS) + { + elem = top = QueueTop(elem); + if (ask_user) + { + sprintf(temp_buf, "%s has the following cnames.", name); + Put_message(temp_buf); + Loop(top, (void (*)(char **)) PrintCname); + ptr = "Remove ** ALL ** these cnames?"; + if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */ delete_it = TRUE; + else + { + Put_message("Aborting..."); + FreeQueue(top); + return SUB_ERROR; + } + } + else + delete_it = TRUE; + + if (delete_it) + { + while (elem) + { + char **info = elem->q_data; + if ((stat = do_mr_query("delete_hostalias", 2, info, + NULL, NULL))) + { + ret_value = SUB_ERROR; + com_err(program_name, stat, " in delete_hostalias."); + sprintf(temp_buf, + "Cname %s ** NOT ** removed from host %s.", + info[0], info[1]); + Put_message(temp_buf); + } + elem = elem->q_forw; + } + } + } + return ret_value; +} + +/* Function Name: RealDeleteMachine + * Description: Actually Deletes the Machine. + * Arguments: info - nescessary information stored as an array of char *'s + * one_machine - a boolean, true if there is only one item in + * the query. + * Returns: none. + */ - if (delete_it) { - elem = top; - while (elem != 0) { - char **info = (char **) elem->q_data; - if ( (stat = sms_query( "delete_machine_from_cluster", - 2, info, Scream, NULL)) != 0) { - ret_value = SUB_ERROR; - com_err(program_name, stat, - " in delete_machine_from_cluster."); - sprintf(temp_buf, - "Machine %s ** NOT ** removed from cluster %s.", - info[MAP_MACHINE], info[MAP_CLUSTER]); - Put_message(temp_buf); +static void RealDeleteMachine(char **info, Bool one_machine) +{ + int stat; + char temp_buf[BUFSIZ]; + + sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ", + info[M_NAME]); + if (!one_machine || Confirm(temp_buf)) + { + if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR) + { + if (CheckAndRemoveCnames(info[M_NAME], TRUE) != SUB_ERROR) + { + if ((stat = do_mr_query("delete_host", 1, + &info[M_NAME], NULL, NULL))) + { + com_err(program_name, stat, " in DeleteMachine."); + sprintf(temp_buf, "%s ** NOT ** deleted.", + info[M_NAME]); + Put_message(temp_buf); + } + else + { + sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]); + Put_message(temp_buf); } - elem = elem->q_forw; } } } - return(ret_value); } /* Function Name: DeleteMachine @@ -526,65 +1263,81 @@ Bool ask_user; /* Perhaps we should remove the cluster if it has no machine now. */ -/* ARGSUSED */ -int -DeleteMachine(argc, argv) -int argc; -char **argv; -{ - int stat; - Bool one_machine, delete_it = FALSE; - char *name, temp_buf[BUFSIZ]; - struct qelem *top, *elem = NULL; - - name = CanonicalizeHostname(argv[1]); - top = elem = GetMCInfo(MACHINE, name, (char *) NULL); - - one_machine = (QueueCount(top) == 1); - while (elem != NULL) { - char **info = (char **) elem->q_data; - if (one_machine) { - if(Confirm("Are you sure that you want to delete this machine?")) - delete_it = TRUE; - } - else { - sprintf(temp_buf, "Delete the machine %s (y/n/q)? ", info[M_NAME]); - switch (YesNoQuitQuestion(temp_buf, FALSE)) { - case TRUE: - delete_it = TRUE; - break; - case FALSE: - delete_it = FALSE; - sprintf(temp_buf, "%s not Deleted.", info[M_NAME]); - Put_message(temp_buf); - break; - default: /* quit. */ - Put_message("Aborting..."); - FreeQueue(top); - return(DM_NORMAL); - } - } - if (delete_it) { - if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR) { - if ( (stat = sms_query("delete_machine", 1, - &info[M_NAME], Scream, NULL)) != 0) { - com_err(program_name, stat, " in DeleteMachine."); - sprintf(temp_buf, "%s ** NOT ** deleted.", - info[M_NAME]); - Put_message(temp_buf); - } - else { - sprintf(temp_buf, "%s sucesfully Deleted.", info[M_NAME]); - Put_message(temp_buf); - } - } - } - elem = elem->q_forw; +int DeleteMachine(int argc, char **argv) +{ + struct mqelem *top; + char *tmpname; + + tmpname = canonicalize_hostname(strdup(argv[1])); + top = GetMCInfo(MACHINE, tmpname, (char *) NULL); + QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine"); + FreeQueue(top); + free(tmpname); + return DM_NORMAL; +} + + +/* Function Name: ShowCname + * Description: This function shows machine aliases + * Arguments: argc, argv - the alias argv[1], the real name in argv[2] + * Returns: DM_NORMAL. + */ + +int ShowCname(int argc, char **argv) +{ + struct mqelem *top; + char *tmpalias, *tmpname; + + tmpalias = partial_canonicalize_hostname(strdup(argv[1])); + tmpname = canonicalize_hostname(strdup(argv[2])); + top = GetMCInfo(CNAME, tmpalias, tmpname); + Put_message(""); /* blank line on screen */ + Loop(top, ((void (*)(char **)) PrintCname)); + FreeQueue(top); + return DM_NORMAL; +} + + +int AddCname(int argc, char **argv) +{ + int stat; + char *args[10]; + + args[0] = partial_canonicalize_hostname(strdup(argv[1])); + args[1] = canonicalize_hostname(strdup(argv[2])); + stat = do_mr_query("add_hostalias", 2, args, NULL, NULL); + switch (stat) + { + case MR_SUCCESS: + break; + case MR_EXISTS: + Put_message("That alias name is already in use."); + break; + case MR_PERM: + Put_message("Permission denied. " + "(Regular users can only add two aliases to a host."); + break; + default: + com_err(program_name, stat, " in add_hostalias"); } - FreeQueue(top); - return(DM_NORMAL); + return DM_NORMAL; } + +int DeleteCname(int argc, char **argv) +{ + int stat; + char *args[10]; + + args[0] = partial_canonicalize_hostname(strdup(argv[1])); + args[1] = canonicalize_hostname(strdup(argv[2])); + stat = do_mr_query("delete_hostalias", 2, args, NULL, NULL); + if (stat) + com_err(program_name, stat, " in delete_hostalias"); + return DM_NORMAL; +} + + /* Function Name: AddMachineToCluster * Description: This function adds a machine to a cluster * Arguments: argc, argv - The machine name is argv[1]. @@ -592,75 +1345,118 @@ char **argv; * Returns: DM_NORMAL. */ -/* ARGSUSED */ -int -AddMachineToCluster(argc, argv) -int argc; -char ** argv; -{ - int stat; - char *machine, *cluster, temp_buf[BUFSIZ], *args[10]; - Bool add_it, one_machine, one_cluster; - struct qelem * melem, *mtop, *celem, *ctop; - - machine = CanonicalizeHostname(argv[1]); - cluster = argv[2]; - - celem = ctop = GetMCInfo(CLUSTER, cluster, (char *) NULL); - melem = mtop = GetMCInfo(MACHINE, machine, (char *) NULL); - - one_machine = (QueueCount(mtop) == 1); - one_cluster = (QueueCount(ctop) == 1); - - while (melem != NULL) { - char ** minfo = (char **) melem->q_data; - while (celem != NULL) { - char ** cinfo = (char **) celem->q_data; - if (one_machine && one_cluster) - add_it = TRUE; - else { - sprintf(temp_buf,"Add machine %s to cluster %s (y/n/q) ?", - minfo[M_NAME], cinfo[C_NAME]); - switch (YesNoQuitQuestion(temp_buf, FALSE)) { +int AddMachineToCluster(int argc, char **argv) +{ + int stat; + char *machine, *cluster, temp_buf[BUFSIZ], *args[10]; + Bool add_it, one_machine, one_cluster; + struct mqelem *melem, *mtop, *celem, *ctop; + + machine = canonicalize_hostname(strdup(argv[1])); + if (strcasecmp(machine, argv[1]) && *argv[1] != '"') + { + sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.", + argv[1], machine); + Put_message(temp_buf); + } + cluster = argv[2]; + + celem = ctop = GetMCInfo(CLUSTER, cluster, NULL); + melem = mtop = GetMCInfo(MACHINE, machine, NULL); + free(machine); + + one_machine = (QueueCount(mtop) == 1); + one_cluster = (QueueCount(ctop) == 1); + + /* No good way to use QueryLoop() here, sigh */ + + while (melem) + { + char **minfo = melem->q_data; + while (celem) + { + char **cinfo = celem->q_data; + if (one_machine && one_cluster) + add_it = TRUE; + else + { + sprintf(temp_buf, "Add machine %s to cluster %s (y/n/q) ?", + minfo[M_NAME], cinfo[C_NAME]); + switch (YesNoQuitQuestion(temp_buf, FALSE)) + { case TRUE: - add_it = TRUE; - break; + add_it = TRUE; + break; case FALSE: - add_it = FALSE; - break; + add_it = FALSE; + break; default: - Put_message("Aborting..."); - FreeQueue(ctop); - FreeQueue(mtop); - return(DM_NORMAL); + Put_message("Aborting..."); + FreeQueue(ctop); + FreeQueue(mtop); + return DM_NORMAL; } } - if (add_it) { - args[0] = minfo[M_NAME]; - args[1] = cinfo[C_NAME]; - stat = sms_query("add_machine_to_cluster", 2, args, - Scream, NULL); - switch (stat) { - case SMS_SUCCESS: - break; - case SMS_EXISTS: - sprintf(temp_buf, "%s is already in cluster %s", - minfo[M_NAME], cinfo[C_NAME]); - Put_message(temp_buf); - break; + if (add_it) + { + args[0] = minfo[M_NAME]; + args[1] = cinfo[C_NAME]; + stat = do_mr_query("add_machine_to_cluster", 2, args, + NULL, NULL); + switch (stat) + { + case MR_SUCCESS: + break; + case MR_EXISTS: + sprintf(temp_buf, "%s is already in cluster %s", + minfo[M_NAME], cinfo[C_NAME]); + Put_message(temp_buf); + break; default: - com_err(program_name, stat, " in AddMachineToCluster."); - break; + com_err(program_name, stat, " in AddMachineToCluster."); + break; } } - celem = celem->q_forw; + celem = celem->q_forw; } - celem = ctop; /* reset cluster element. */ - melem = melem->q_forw; + celem = ctop; /* reset cluster element. */ + melem = melem->q_forw; } - FreeQueue(ctop); - FreeQueue(mtop); - return(DM_NORMAL); + FreeQueue(ctop); + FreeQueue(mtop); + return DM_NORMAL; +} + +/* Function Name: RealRemoveMachineFromCluster + * Description: This function actually removes the machine from its + * cluster. + * Arguments: info - all information nescessary to perform the removal. + * one_map - True if there is only one case, and we should + * confirm. + * Returns: none. + */ + +static void RealRemoveMachineFromCluster(char **info, Bool one_map) +{ + char temp_buf[BUFSIZ]; + int stat; + + sprintf(temp_buf, "Remove %s from the cluster %s", + info[MAP_MACHINE], info[MAP_CLUSTER]); + if (!one_map || Confirm(temp_buf)) + { + if ((stat = do_mr_query("delete_machine_from_cluster", 2, + info, NULL, NULL))) + com_err(program_name, stat, " in delete_machine_from_cluster"); + else + { + sprintf(temp_buf, "%s has been removed from the cluster %s.", + info[MAP_MACHINE], info[MAP_CLUSTER]); + Put_message(temp_buf); + } + } + else + Put_message("Machine not removed."); } /* Function Name: RemoveMachineFromCluster @@ -670,68 +1466,192 @@ char ** argv; * Returns: none. */ -/* ARGSUSED */ -int -RemoveMachineFromCluster(argc, argv) -int argc; -char ** argv; +int RemoveMachineFromCluster(int argc, char **argv) { - int stat; - Bool remove_machine, one_item; - struct qelem *top, *elem = NULL; - char buf[BUFSIZ], * args[10]; - - args[MAP_MACHINE] = CanonicalizeHostname(argv[1]); - args[MAP_CLUSTER] = argv[2]; - args[MAP_END] = NULL; + struct mqelem *elem = NULL; + char buf[BUFSIZ], *args[10]; + int stat; + + args[MAP_MACHINE] = canonicalize_hostname(strdup(argv[1])); + if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"') + { + sprintf(buf, "Warning: '%s' canonicalized to '%s'.", + argv[1], args[MAP_MACHINE]); + Put_message(buf); + } + args[MAP_CLUSTER] = argv[2]; + args[MAP_END] = NULL; - stat = sms_query("get_machine_to_cluster_map", CountArgs(args), args, + stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args, StoreInfo, &elem); - if (stat == SMS_NO_MATCH) { - sprintf(buf, "The machine %s is not is the cluster %s.", - args[MAP_MACHINE], args[MAP_CLUSTER]); - Put_message(buf); - return(DM_NORMAL); + if (stat == MR_NO_MATCH) + { + sprintf(buf, "The machine %s is not in the cluster %s.", + args[MAP_MACHINE], args[MAP_CLUSTER]); + Put_message(buf); + free(args[MAP_MACHINE]); + return DM_NORMAL; } - if (stat) - com_err(program_name, stat, " in delete_machine_from_cluster"); + if (stat != MR_SUCCESS) + com_err(program_name, stat, " in delete_machine_from_cluster"); - top = elem = QueueTop(elem); - one_item = (QueueCount(top) == 1); - while (elem != NULL) { - char **info = (char **) elem->q_data; - if (one_item) - remove_machine = TRUE; - else { - sprintf(buf, "Remove %s from the cluster %s? (y/n/q)", - info[MAP_MACHINE], info[MAP_CLUSTER]); - switch (YesNoQuitQuestion(buf, FALSE)) { - case TRUE: - remove_machine = TRUE; - break; - case FALSE: - remove_machine = FALSE; - break; - default: - Put_message("Aborting"); - FreeQueue(top); - return(DM_NORMAL); - } + elem = QueueTop(elem); + QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster, + "Remove this machine from this cluster"); + + FreeQueue(elem); + free(args[MAP_MACHINE]); + return DM_NORMAL; +} + +/* ---------- Subnet Menu -------- */ + +/* Function Name: ShowSubnetInfo + * Description: Gets information about a subnet given its name. + * Arguments: argc, argc - the name of the subnet in in argv[1]. + * Returns: DM_NORMAL. + */ + +int ShowSubnetInfo(int argc, char **argv) +{ + struct mqelem *top; + + top = GetMCInfo(SUBNET, argv[1], (char *) NULL); + Loop(top, (void (*)(char **)) PrintSubnetInfo); + FreeQueue(top); + return DM_NORMAL; +} + +/* Function Name: AddSubnet + * Description: Creates a new subnet. + * Arguments: argc, argv - the name of the new subnet is argv[1]. + * Returns: DM_NORMAL. + */ + +int AddSubnet(int argc, char **argv) +{ + char **args, *info[MAX_ARGS_SIZE], *name = argv[1]; + int stat; + + /* + * Check to see if this subnet already exists. + */ + if (!ValidName(name)) + return DM_NORMAL; + + if ((stat = do_mr_query("get_subnet", 1, &name, NULL, NULL)) == MR_SUCCESS) + { + Put_message("This subnet already exists."); + return DM_NORMAL; + } + else if (stat != MR_NO_MATCH) + { + com_err(program_name, stat, " in AddSubnet."); + return DM_NORMAL; + } + if (!(args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE))) + { + Put_message("Aborted."); + FreeInfo(info); + return DM_NORMAL; + } + + /* + * Actually create the new Subnet. + */ + if ((stat = do_mr_query("add_subnet", CountArgs(args), args, NULL, NULL))) + com_err(program_name, stat, " in AddSubnet."); + + FreeInfo(info); + return DM_NORMAL; +} + +/* Function Name: RealUpdateSubnet + * Description: This function actually performs the subnet update. + * Arguments: info - all information nesc. for updating the subnet. + * junk - an UNUSED boolean. + * Returns: none. + */ + +static void RealUpdateSubnet(char **info, Bool junk) +{ + int stat; + char **args = AskMCDInfo(info, SUBNET, TRUE); + if (!args) + { + Put_message("Aborted."); + return; + } + if ((stat = do_mr_query("update_subnet", CountArgs(args), args, NULL, NULL))) + com_err(program_name, stat, " in UpdateSubnet."); + else + Put_message("Subnet successfully updated."); +} + +/* Function Name: UpdateSubnet + * Description: This Function Updates a subnet + * Arguments: name of the subnet in argv[1]. + * Returns: DM_NORMAL. + */ + +int UpdateSubnet(int argc, char **argv) +{ + struct mqelem *top; + top = GetMCInfo(SUBNET, argv[1], NULL); + QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet"); + + FreeQueue(top); + return DM_NORMAL; +} + +/* Function Name: RealDeleteSubnet + * Description: Actually performs the subnet deletion. + * Arguments: info - all information about this subnet. + * one_subnet - If true then there was only one subnet in + * the queue, and we should confirm. + * Returns: none. + */ + +static void RealDeleteSubnet(char **info, Bool one_subnet) +{ + int stat; + char temp_buf[BUFSIZ]; + + sprintf(temp_buf, + "Are you sure the you want to delete the subnet %s (y/n) ?", + info[C_NAME]); + if (!one_subnet || Confirm(temp_buf)) + { + if ((stat = do_mr_query("delete_subnet", 1, &info[C_NAME], NULL, NULL))) + { + com_err(program_name, stat, " in delete_subnet."); + sprintf(temp_buf, "Subnet %s ** NOT ** deleted.", info[C_NAME]); + Put_message(temp_buf); + } + else + { + sprintf(temp_buf, "subnet %s successfully deleted.", + info[C_NAME]); + Put_message(temp_buf); } - if (remove_machine) - if ( (stat = sms_query("delete_machine_from_cluster", 2, - info, Scream, NULL)) != 0 ) - com_err(program_name, stat, - " in delete_machine_from_cluster"); - else { - sprintf(buf, "%s has been removed from the cluster %s.", - info[MAP_MACHINE], info[MAP_CLUSTER]); - Put_message(buf); - } - elem = elem->q_forw; } - FreeQueue(top); - return(DM_NORMAL); +} + +/* Function Name: DeleteSubnet + * Description: This function removes a subnet from the database. + * Arguments: argc, argv - the name of the subnet is stored in argv[1]. + * Returns: DM_NORMAL. + */ + +int DeleteSubnet(int argc, char **argv) +{ + struct mqelem *top; + + top = GetMCInfo(SUBNET, argv[1], NULL); + QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet"); + + FreeQueue(top); + return DM_NORMAL; } /* ---------- Cluster Menu -------- */ @@ -742,24 +1662,14 @@ char ** argv; * Returns: DM_NORMAL. */ -/* ARGSUSED */ -int -ShowClusterInfo(argc, argv) -int argc; -char ** argv; +int ShowClusterInfo(int argc, char **argv) { - char **info; - struct qelem *elem, *top; + struct mqelem *top; - top = elem = GetMCInfo( CLUSTER, CanonicalizeHostname(argv[1]), - (char *) NULL); - while (elem != NULL) { - info = (char **) elem->q_data; - PrintClusterInfo(info); - elem = elem->q_forw; - } - FreeQueue(top); - return(DM_NORMAL); + top = GetMCInfo(CLUSTER, argv[1], NULL); + Loop(top, (void (*)(char **)) PrintClusterInfo); + FreeQueue(top); + return DM_NORMAL; } /* Function Name: AddCluster @@ -768,40 +1678,66 @@ char ** argv; * Returns: DM_NORMAL. */ -/* ARGSUSED */ -int -AddCluster(argc, argv) -int argc; -char ** argv; +int AddCluster(int argc, char **argv) { - char **args, *info[MAX_ARGS_SIZE], *name; - int stat; -/* - * Check to see if this machine already exists. - */ - name = argv[1]; - - if ( (stat = sms_query("get_cluster", 1, &name, NullFunc, NULL)) == 0) { - Put_message("This cluster already exists."); - return(DM_NORMAL); + char **args, *info[MAX_ARGS_SIZE], *name = argv[1]; + int stat; + + /* + * Check to see if this cluster already exists. + */ + if (!ValidName(name)) + return DM_NORMAL; + + if ((stat = do_mr_query("get_cluster", 1, &name, NULL, NULL)) == MR_SUCCESS) + { + Put_message("This cluster already exists."); + return DM_NORMAL; + } + else if (stat != MR_NO_MATCH) + { + com_err(program_name, stat, " in AddCluster."); + return DM_NORMAL; } - else if (stat != SMS_NO_MATCH) { - com_err(program_name, stat, " in AddCluster."); - return(DM_NORMAL); + if (!(args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE))) + { + Put_message("Aborted."); + FreeInfo(info); + return DM_NORMAL; } - args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE); + /* + * Actually create the new Cluster. + */ + if ((stat = do_mr_query("add_cluster", CountArgs(args), args, NULL, NULL))) + com_err(program_name, stat, " in AddCluster."); -/* - * Actually create the new Cluster. + FreeInfo(info); + return DM_NORMAL; +} + +/* Function Name: RealUpdateCluster + * Description: This function actually performs the cluster update. + * Arguments: info - all information nesc. for updating the cluster. + * junk - an UNUSED boolean. + * Returns: none. */ - - if ( (stat = sms_query("add_cluster", CountArgs(args), - args, Scream, NULL)) != 0) - com_err(program_name, stat, " in AddCluster."); - FreeInfo(info); - return(DM_NORMAL); +static void RealUpdateCluster(char **info, Bool junk) +{ + int stat; + char **args = AskMCDInfo(info, CLUSTER, TRUE); + + if (!args) + { + Put_message("Aborted."); + return; + } + if ((stat = do_mr_query("update_cluster", CountArgs(args), + args, NULL, NULL))) + com_err(program_name, stat, " in UpdateCluster."); + else + Put_message("Cluster successfully updated."); } /* Function Name: UpdateCluster @@ -810,49 +1746,14 @@ char ** argv; * Returns: DM_NORMAL. */ -/* ARGSUSED */ -int -UpdateCluster(argc, argv) -int argc; -char ** argv; -{ - struct qelem *elem, *top; - char **args, **info, temp_buf[BUFSIZ]; - int stat; - Bool one_cluster, update_it; - - elem = top = GetMCInfo( CLUSTER, argv[1], (char *) NULL ); - - one_cluster = (QueueCount(top) == 1); - while (elem != NULL) { - info = (char **) elem->q_data; - if (one_cluster) - update_it = TRUE; - else { - sprintf(temp_buf, "Update Cluster %s (y/n/q) ? ", info[C_NAME]); - switch(YesNoQuitQuestion(temp_buf, FALSE)) { - case TRUE: - update_it = TRUE; - break; - case FALSE: - update_it = FALSE; - break; - default: - Put_message("Aborting..."); - FreeQueue(top); - return(DM_NORMAL); - } - } - if (update_it) { - args = AskMCDInfo(info, CLUSTER, TRUE); - if ( (stat = sms_query("update_cluster", CountArgs(args), - args, Scream, NULL)) != 0) - com_err(program_name, stat, " in UpdateCluster."); - } - elem = elem->q_forw; - } - FreeQueue(top); - return(DM_NORMAL); +int UpdateCluster(int argc, char **argv) +{ + struct mqelem *top; + top = GetMCInfo(CLUSTER, argv[1], NULL); + QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster"); + + FreeQueue(top); + return DM_NORMAL; } /* Function Name: CheckAndRemoveMachine @@ -864,71 +1765,110 @@ char ** argv; * Returns: SUB_ERROR if all machines not removed. */ -int -CheckAndRemoveMachines(name, ask_first) -char * name; -Bool ask_first; -{ - register int stat, ret_value; - Bool delete_it; - char *args[10], temp_buf[BUFSIZ], *ptr; - struct qelem *top, *elem = NULL; - - ret_value = SUB_NORMAL; - args[MAP_MACHINE] = "*"; - args[MAP_CLUSTER] = name; - stat = sms_query("get_machine_to_cluster_map", 2, args, - StoreInfo, &elem); - if (stat && stat != SMS_NO_MATCH) { - com_err(program_name, stat, " in get_machine_to_cluster_map."); - return(DM_NORMAL); - } - if (stat == 0) { - elem = top = QueueTop(elem); - if (ask_first) { - sprintf(temp_buf, - "The cluster %s has the following machines in it:", - name); - Put_message(temp_buf); - while (elem != NULL) { - char **info = (char **) elem->q_data; - Print(1, &info[MAP_MACHINE], (char *) NULL); - elem = elem->q_forw; +int CheckAndRemoveMachines(char *name, Bool ask_first) +{ + int stat, ret_value; + Bool delete_it; + char *args[10], temp_buf[BUFSIZ], *ptr; + struct mqelem *top, *elem = NULL; + + ret_value = SUB_NORMAL; + args[MAP_MACHINE] = "*"; + args[MAP_CLUSTER] = name; + stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem); + if (stat && stat != MR_NO_MATCH) + { + com_err(program_name, stat, " in get_machine_to_cluster_map."); + return DM_NORMAL; + } + if (stat == MR_SUCCESS) + { + elem = top = QueueTop(elem); + if (ask_first) + { + sprintf(temp_buf, "The cluster %s has the following machines in it:", + name); + Put_message(temp_buf); + while (elem) + { + char **info = elem->q_data; + Print(1, &info[MAP_MACHINE], (char *) NULL); + elem = elem->q_forw; } - ptr = "Remove ** ALL ** these machines from this cluster?"; - - if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */ - delete_it = TRUE; - else { - Put_message("Aborting..."); - FreeQueue(top); - return(SUB_ERROR); + ptr = "Remove ** ALL ** these machines from this cluster?"; + + if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */ + delete_it = TRUE; + else + { + Put_message("Aborting..."); + FreeQueue(top); + return SUB_ERROR; } } - else - delete_it = TRUE; - - if (delete_it) { - elem = top; - while (elem != 0) { - char **info = (char **) elem->q_data; - if ( (stat = sms_query( "delete_machine_from_cluster", - 2, info, Scream, NULL)) != 0) { - ret_value = SUB_ERROR; - com_err(program_name, stat, - " in delete_machine_from_cluster."); - sprintf(temp_buf, - "Machine %s ** NOT ** removed from cluster %s.", - info[MAP_MACHINE], info[MAP_CLUSTER]); - Put_message(temp_buf); + else + delete_it = TRUE; + + if (delete_it) + { + elem = top; + while (elem) + { + char **info = elem->q_data; + if ((stat = do_mr_query("delete_machine_from_cluster", + 2, info, NULL, NULL))) + { + ret_value = SUB_ERROR; + com_err(program_name, stat, + " in delete_machine_from_cluster."); + sprintf(temp_buf, + "Machine %s ** NOT ** removed from cluster %s.", + info[MAP_MACHINE], info[MAP_CLUSTER]); + Put_message(temp_buf); } - elem = elem->q_forw; + elem = elem->q_forw; } } } - return(ret_value); + return ret_value; } +/* Function Name: RealDeleteCluster + * Description: Actually performs the cluster deletion. + * Arguments: info - all information about this cluster. + * one_cluster - If true then there was only one cluster in + * the queue, and we should confirm. + * Returns: none. + */ + +static void RealDeleteCluster(char **info, Bool one_cluster) +{ + int stat; + char temp_buf[BUFSIZ]; + + sprintf(temp_buf, + "Are you sure the you want to delete the cluster %s (y/n) ?", + info[C_NAME]); + if (!one_cluster || Confirm(temp_buf)) + { + if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR) + { + if ((stat = do_mr_query("delete_cluster", 1, + &info[C_NAME], NULL, NULL))) + { + com_err(program_name, stat, " in delete_cluster."); + sprintf(temp_buf, "Cluster %s ** NOT ** deleted.", info[C_NAME]); + Put_message(temp_buf); + } + else + { + sprintf(temp_buf, "cluster %s successfully deleted.", + info[C_NAME]); + Put_message(temp_buf); + } + } + } +} /* Function Name: DeleteCluster * Description: This function removes a cluster from the database. @@ -936,64 +1876,15 @@ Bool ask_first; * Returns: DM_NORMAL. */ -/* ARGSUSED */ -int -DeleteCluster(argc, argv) -int argc; -char ** argv; -{ - char temp_buf[BUFSIZ]; - int stat; - Bool one_cluster, delete_it = FALSE; - struct qelem *elem, *top; - - top = elem = GetMCInfo( CLUSTER, argv[1], (char *) NULL ); - - one_cluster = (QueueCount(top) == 1); - while (elem != NULL) { - char **info = (char **) elem->q_data; - if (one_cluster) { - if(Confirm("Are you sure that you want to delete this cluster?")) - delete_it = TRUE; - } - else { - PrintClusterInfo(info); - sprintf(temp_buf, "Delete the cluster %s (y/n/q)? ", info[C_NAME]); - switch (YesNoQuitQuestion(temp_buf, FALSE)) { - case TRUE: - delete_it = TRUE; - break; - case FALSE: - delete_it = FALSE; - sprintf(temp_buf, "%s not Deleted.", info[C_NAME]); - Put_message(temp_buf); - break; - default: /* quit. */ - Put_message("Aborting..."); - FreeQueue(top); - return(DM_NORMAL); - } - } - if (delete_it) { - if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR) { - if ( (stat = sms_query("delete_cluster", 1, - &info[C_NAME], Scream, NULL)) != 0) { - com_err(program_name, stat, " in DeleteCluster."); - sprintf(temp_buf, "Cluster %s ** NOT ** deleted.", - info[C_NAME]); - Put_message(temp_buf); - } - else { - sprintf(temp_buf, "cluster %s sucesfully Deleted.", - info[C_NAME]); - Put_message(temp_buf); - } - } - } - elem = elem->q_forw; - } - FreeQueue(top); - return(DM_NORMAL); +int DeleteCluster(int argc, char **argv) +{ + struct mqelem *top; + + top = GetMCInfo(CLUSTER, argv[1], NULL); + QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster"); + + FreeQueue(top); + return DM_NORMAL; } /* ----------- Cluster Data Menu -------------- */ @@ -1005,23 +1896,20 @@ char ** argv; * Returns: DM_NORMAL. */ -/* ARGSUSED */ -int -ShowClusterData(argc, argv) -int argc; -char ** argv; -{ - struct qelem *elem, *top; - char **info; - - top = elem = GetMCInfo(DATA, argv[1], argv[2]); - while (elem != NULL) { - info = (char **) elem->q_data; - PrintClusterData(info); - elem = elem->q_forw; +int ShowClusterData(int argc, char **argv) +{ + struct mqelem *elem, *top; + char **info; + + top = elem = GetMCInfo(DATA, argv[1], argv[2]); + while (elem) + { + info = elem->q_data; + PrintClusterData(info); + elem = elem->q_forw; } - FreeQueue(top); - return(DM_NORMAL); + FreeQueue(top); + return DM_NORMAL; } /* Function Name: AddClusterData @@ -1032,18 +1920,50 @@ char ** argv; * Returns: DM_NORMAL. */ -/* ARGSUSED */ -int -AddClusterData(argc, argv) -int argc; -char ** argv; -{ - int stat; +int AddClusterData(int argc, char **argv) +{ + int stat, i; + + for (i = 1; i < 4; i++) + { + if (IS_EMPTY(argv[i])) + { + Put_message("Cluster data cannot be an empty string."); + return DM_NORMAL; + } + } + if ((stat = do_mr_query("add_cluster_data", 3, argv + 1, NULL, NULL))) + com_err(program_name, stat, " in AddClusterData."); + return DM_NORMAL; +} - if( (stat = sms_query("add_cluster_data", 3, argv + 1, - Scream, (char *) NULL)) != 0) - com_err(program_name, stat, " in AddClusterData."); +/* Function Name: RealRemoveClusterData + * Description: actually removes the cluster data. + * Arguments: info - all info necessary to remove the cluster, in an array + * of strings. + * one_item - if true then the queue has only one elem and we + * should confirm. + * Returns: none. + */ +static void RealRemoveClusterData(char **info, Bool one_item) +{ + int stat; + char *temp_ptr; + + Put_message(" "); + temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?"; + PrintClusterData(info); + if (!one_item || Confirm(temp_ptr)) + { + if ((stat = do_mr_query("delete_cluster_data", 3, info, NULL, NULL))) + { + com_err(program_name, stat, " in DeleteClusterData."); + Put_message("Data not removed."); + } + else + Put_message("Removal successful."); + } } /* Function Name: RemoveClusterData @@ -1054,59 +1974,17 @@ char ** argv; * Returns: DM_NORMAL. */ -/* ARGSUSED */ -int -RemoveClusterData(argc, argv) -int argc; -char ** argv; -{ - Bool one_piece_of_data, remove_it; - int stat; - struct qelem *elem, *top; - - top = elem = GetMCInfo(DATA, argv[1], argv[2]); - - one_piece_of_data = (QueueCount(elem) == 1); - while (elem != NULL) { - char **info = (char **) elem->q_data; - if (one_piece_of_data) { - if(Confirm("Do you really want to remove this data?")) - remove_it = TRUE; - else - Put_message("Operation aborted.\n"); - } - else { - PrintClusterData(info); - switch (YesNoQuitQuestion - ("Remove this piece of cluster data (y/n/q) ? ", FALSE)) { - case TRUE: - remove_it = TRUE; - break; - case FALSE: - remove_it = FALSE; - break; - default: - Put_message("Aborting"); - FreeQueue(top); - return(DM_NORMAL); - } - } - if (remove_it) { - if( (stat = sms_query("delete_cluster_data", 3, info, - Scream, (char *) NULL)) != 0) { - com_err(program_name, stat, " in DeleteClusterData."); - Put_message("Data not removed."); - } - else - Put_message("Removal sucessful."); - } - elem = elem->q_forw; - } - FreeQueue(top); - return(DM_NORMAL); -} +int RemoveClusterData(int argc, char **argv) +{ + struct mqelem *top; -/* Perhaps an interactive delete cluster data would be nice. */ + top = GetMCInfo(DATA, argv[1], argv[2]); + QueryLoop(top, PrintClusterData, RealRemoveClusterData, + "Remove data from cluster"); + + FreeQueue(top); + return DM_NORMAL; +} /* Function Name: MachineToClusterMap * Description: This Retrieves the mapping between machine and cluster @@ -1115,56 +1993,603 @@ char ** argv; * Returns: none. */ -/* ARGSUSED */ -int -MachineToClusterMap(argc,argv) -int argc; -char **argv; +int MachineToClusterMap(int argc, char **argv) { - struct qelem *elem, *top; - - top = elem = GetMCInfo(MAP, CanonicalizeHostname(argv[1]), argv[2]); - - Put_message(""); /* blank line on screen */ - while (elem != NULL) { - char ** info = (char **) elem->q_data; - PrintMCMap(info); - elem = elem->q_forw; + struct mqelem *elem, *top; + char *tmpname, temp_buf[256]; + + tmpname = canonicalize_hostname(strdup(argv[1])); + if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"') + { + sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.", + argv[1], tmpname); + Put_message(temp_buf); + } + top = elem = GetMCInfo(MAP, tmpname, argv[2]); + + Put_message(""); /* blank line on screen */ + while (elem) + { + char **info = elem->q_data; + PrintMCMap(info); + elem = elem->q_forw; } - FreeQueue(top); - return(DM_NORMAL); + FreeQueue(top); + free(tmpname); + return DM_NORMAL; } -/* Function Name: MachinesInCluster - * Description: Shows all machines in a give cluster. - * Arguments: argv, argc - name of cluster in argv[1]. - * Returns: DM_NORMAL; +/* Function Name: MachineByOwner + * Description: This function prints all machines which are owned by + * a given user or group. + * Arguments: none. + * Returns: DM_NORMAL. */ -/* ARGSUSED */ -int -MachinesInCluster(argc, argv) -int argc; -char **argv; -{ - char *info[10]; - info[0] = argv[0]; - info[2] = argv[1]; - info[1] = "*"; - return(MachineToClusterMap(3, info)); -} - -/* - * Local Variables: - * mode: c - * c-indent-level: 4 - * c-continued-statement-offset: 4 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * End: +int MachineByOwner(int argc, char **argv) +{ + char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name; + struct mqelem *top; + + type = strdup("USER"); + if (GetTypeFromUser("Type of owner", "ace_type", &type) == SUB_ERROR) + return DM_NORMAL; + + sprintf(buf, "Name of %s", type); + name = strdup(user); + if (GetValueFromUser(buf, &name) == SUB_ERROR) + return DM_NORMAL; + + switch (YesNoQuestion("Do you want a recursive search (y/n)", FALSE)) + { + case TRUE: + sprintf(temp_buf, "R%s", type); /* "USER to "RUSER", etc. */ + free(type); + type = strdup(temp_buf); + break; + case FALSE: + break; + default: + return DM_NORMAL; + } + + top = GetMachineByOwner(type, name); + Loop(top, PrintMachine); + + FreeQueue(top); + return DM_NORMAL; +} + +/* Function Name: GetMachineByOwner + * Description: This function stores information retrieved by + * the get_host_by_owner query + * Arguments: type - an ace_type, argv[0] for the query + * name - name of machine, argv[1] for the query + * Returns: the top element of a queue returning the data, or NULL. */ +struct mqelem *GetMachineByOwner(char *type, char *name) +{ + char *args[2]; + struct mqelem *elem = NULL; + int status; + + args[0] = type; + args[1] = name; + if ((status = do_mr_query("get_host_by_owner", 2, args, StoreInfo, &elem))) + { + com_err(program_name, status, " in get_host_by_owner"); + return NULL; + } + return QueueTop(elem); +} + +int MachineByAcctNumber(int argc, char **argv) +{ + char *args[1], *account_number; + int status; + struct mqelem *elem = NULL; + + account_number = strdup(""); + if (GetValueFromUser("Account Number", &account_number) == SUB_ERROR) + return DM_NORMAL; + + args[0] = account_number; + if (status = do_mr_query("get_host_by_account_number", 1, args, StoreInfo, + &elem)) + { + com_err(program_name, status, " in get_host_by_account_number"); + return DM_NORMAL; + } + Loop(QueueTop(elem), (void (*)(char **)) PrintMachInfo); + FreeQueue(elem); + + return DM_NORMAL; +} + +int ShowContainerInfo(int argc, char **argv) +{ + struct mqelem *top; + + top = GetMCInfo(CONTAINER, argv[1], NULL); + Loop(top, (void (*)(char **)) PrintContainerInfo); + FreeQueue(top); + return DM_NORMAL; +} + +static char *PrintContainerInfo(char **info) +{ + char buf[BUFSIZ], tbuf[256]; + char *args[2]; + struct mqelem *elem = NULL; + int stat; + + Put_message(""); + sprintf(buf, "Container: %-16s Public: %s", info[CON_NAME], + atoi(info[CON_PUBLIC]) ? "Yes" : "No"); + Put_message(buf); + /* Do a get_container_list to see what the associated list is. */ + args[0] = info[CON_NAME]; + if (stat = do_mr_query("get_container_list", 1, args, StoreInfo, &elem)) + { + if (stat != MR_NO_MATCH) + com_err(program_name, stat, " looking up container list"); + } + else + { + sprintf(buf, "Container's associated list is: LIST %s", + ((char **)elem->q_data)[1]); + Put_message(buf); + FreeQueue(elem); + } + sprintf(buf, "Description: %-16s", info[CON_DESCRIPT]); + Put_message(buf); + sprintf(buf, "Location: %-16s Contact: %s", info[CON_LOCATION], + info[CON_CONTACT]); + Put_message(buf); + sprintf(tbuf, "%s %s", info[CON_OWNER_TYPE], + strcmp(info[CON_OWNER_TYPE], "NONE") ? info[CON_OWNER_NAME] : ""); + sprintf(buf, "Owner: %-16s", tbuf); + Put_message(buf); + sprintf(tbuf, "%s %s", info[CON_MEMACE_TYPE], + strcmp(info[CON_MEMACE_TYPE], "NONE") ? info[CON_MEMACE_NAME] : ""); + sprintf(buf, "Membership ACL: %-16s", tbuf); + Put_message(buf); + Put_message(""); + sprintf(buf, MOD_FORMAT, info[CON_MODBY], info[CON_MODTIME], + info[CON_MODWITH]); + Put_message(buf); + return(info[CON_NAME]); +} + +static char *PrintContainer(char **info) +{ + char buf[BUFSIZ]; + + sprintf(buf, "Container: %s", info[CON_NAME]); + Put_message(buf); + return ""; +} + +static char *PrintMContMap(char **info) +{ + char buf[BUFSIZ]; + sprintf(buf, "Container: %-30s Machine: %-20s", + info[1], info[0]); + Put_message(buf); + return ""; +} + +int AddContainer(int argc, char **argv) +{ + char **args, *info[MAX_ARGS_SIZE], *name = argv[1]; + int stat; + + /* Can't use ValidName() because spaces are allowed in container names */ + if (IS_EMPTY(name)) + { + Put_message("Please use a non-empty name."); + return DM_NORMAL; + } + + if (strchr(name, '*') || strchr(name, '?')) + { + Put_message("Wildcards not accepted here."); + return DM_NORMAL; + } + + /* Check if this cluster already exists. */ + if ((stat = do_mr_query("get_container", 1, &name, NULL, NULL)) + == MR_SUCCESS) + { + Put_message("This container already exists."); + return DM_NORMAL; + } + else if (stat != MR_NO_MATCH) + { + com_err(program_name, stat, " in AddContainer."); + return DM_NORMAL; + } + if (!(args = AskMCDInfo(SetContainerDefaults(info, name), CONTAINER, FALSE))) + { + Put_message("Aborted."); + FreeInfo(info); + return DM_NORMAL; + } + + /* Create the new container. */ + if ((stat = do_mr_query("add_container", CountArgs(args), args, NULL, NULL))) + com_err(program_name, stat, " in AddContainer."); + + FreeInfo(info); + return DM_NORMAL; +} + +int UpdateContainer(int argc, char **argv) +{ + struct mqelem *top; + top = GetMCInfo(CONTAINER, argv[1], NULL); + QueryLoop(top, NullPrint, RealUpdateContainer, "Update the container"); + + FreeQueue(top); + return DM_NORMAL; +} + +static void RealUpdateContainer(char **info, Bool junk) +{ + int stat; + char **args = AskMCDInfo(info, CONTAINER, TRUE); + + if (!args) + { + Put_message("Aborted."); + return; + } + if ((stat = do_mr_query("update_container", CountArgs(args), args, + NULL, NULL))) + com_err(program_name, stat, " in UpdateContainer."); + else + Put_message("Container successfully updated."); +} + +int DeleteContainer(int argc, char **argv) +{ + struct mqelem *top; + + top = GetMCInfo(CONTAINER, argv[1], NULL); + QueryLoop(top, PrintClusterInfo, RealDeleteContainer, + "Delete the container"); + + FreeQueue(top); + return DM_NORMAL; +} + +static void RealDeleteContainer(char **info, Bool one_container) +{ + int stat; + char temp_buf[BUFSIZ]; + + sprintf(temp_buf, + "Are you sure you want to delete the container %s (y/n) ?", + info[CON_NAME]); + if (!one_container || Confirm(temp_buf)) + { + if (CheckAndRemoveMachinesFromContainer(info[CON_NAME], TRUE) + != SUB_ERROR) + { + if ((stat = do_mr_query("delete_container", 1, &info[CON_NAME], + NULL, NULL))) + { + com_err(program_name, stat, " in delete_container."); + sprintf(temp_buf, "Container %s ** NOT ** deleted.", + info[CON_NAME]); + Put_message(temp_buf); + } + else + { + sprintf(temp_buf, "Container %s successfully deleted.", + info[CON_NAME]); + Put_message(temp_buf); + } + } + } +} + +int CheckAndRemoveMachinesFromContainer(char *name, Bool ask_first) +{ + int stat, ret_value; + Bool delete_it; + char *args[10], temp_buf[BUFSIZ], *ptr; + struct mqelem *top, *elem = NULL; + + ret_value = SUB_NORMAL; + args[0] = name; + args[1] = "0"; + stat = do_mr_query("get_machines_of_container", 2, args, StoreInfo, + &elem); + if (stat && stat != MR_NO_MATCH) + { + com_err(program_name, stat, " in get_machines_of_container"); + return DM_NORMAL; + } + if (stat == MR_SUCCESS) + { + elem = top = QueueTop(elem); + if (ask_first) + { + sprintf(temp_buf, + "The container %s has the following machines in it:", name); + Put_message(temp_buf); + while (elem) + { + char **info = elem->q_data; + Print(1, &info[0], (char *) NULL); + elem = elem->q_forw; + } + ptr = "Remove ** ALL ** these machines from this container?"; + + if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */ + delete_it = TRUE; + else + { + Put_message("Aborting..."); + FreeQueue(top); + return SUB_ERROR; + } + } + else + delete_it = TRUE; + + if (delete_it) + { + elem = top; + while (elem) + { + char **info = elem->q_data; + if ((stat = do_mr_query("delete_machine_from_container", + 2, info, NULL, NULL))) + { + ret_value = SUB_ERROR; + com_err(program_name, stat, + " in delete_machine_from_container."); + sprintf(temp_buf, + "Machine %s ** NOT ** removed from container %s.", + info[0], info[1]); + Put_message(temp_buf); + } + elem = elem->q_forw; + } + } + } + return ret_value; +} + +int GetSubContainers(int argc, char **argv) +{ + char *args[2]; + struct mqelem *elem = NULL, *top = NULL; + int stat; + + args[0] = argv[1]; + + if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE) + args[1] = "1"; + else + args[1] = "0"; + + if (stat = do_mr_query("get_subcontainers_of_container", 2, args, + StoreInfo, &elem)) + com_err(program_name, stat, " in get_subcontainers_of_container"); + + top = QueueTop(elem); + Loop(top, ((void (*)(char **)) PrintContainer)); + FreeQueue(top); + return DM_NORMAL; +} + +int MachineToContainerMap(int argc, char **argv) +{ + struct mqelem *elem, *top; + char *tmpname, temp_buf[256]; + + tmpname = canonicalize_hostname(strdup(argv[1])); + if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"') + { + sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.", + argv[1], tmpname); + Put_message(temp_buf); + } + top = elem = GetMCInfo(CONTMAP, tmpname, NULL); + + Put_message(""); + while (elem) + { + char **info = elem->q_data; + PrintMContMap(info); + elem = elem->q_forw; + } + + FreeQueue(top); + free(tmpname); + return DM_NORMAL; +} + +int AddMachineToContainer(int argc, char **argv) +{ + int stat; + char *machine, *container, temp_buf[BUFSIZ], *args[10]; + Bool add_it, one_machine, one_container; + struct mqelem *melem, *mtop, *celem, *ctop; + + machine = canonicalize_hostname(strdup(argv[1])); + if (strcasecmp(machine, argv[1]) && *argv[1] != '"') + { + sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.", + argv[1], machine); + Put_message(temp_buf); + } + container = argv[2]; + + celem = ctop = GetMCInfo(CONTAINER, container, NULL); + melem = mtop = GetMCInfo(MACHINE, machine, NULL); + free(machine); + + one_machine = (QueueCount(mtop) == 1); + one_container = (QueueCount(ctop) == 1); + + while (melem) + { + char **minfo = melem->q_data; + while (celem) + { + char **cinfo = celem->q_data; + if (one_machine && one_container) + add_it = TRUE; + else + { + sprintf(temp_buf, "Add machine %s to container %s (y/n/q) ?", + minfo[M_NAME], cinfo[CON_NAME]); + switch (YesNoQuestion(temp_buf, FALSE)) + { + case TRUE: + add_it = TRUE; + break; + case FALSE: + add_it = FALSE; + break; + default: + Put_message("Aborting..."); + FreeQueue(ctop); + FreeQueue(mtop); + return DM_NORMAL; + } + } + if (add_it) + { + args[0] = minfo[M_NAME]; + args[1] = cinfo[CON_NAME]; + stat = do_mr_query("add_machine_to_container", 2, args, NULL, + NULL); + switch (stat) + { + case MR_SUCCESS: + break; + case MR_EXISTS: + sprintf(temp_buf, "%s is already in container %s", + minfo[M_NAME], cinfo[CON_NAME]); + Put_message(temp_buf); + break; + default: + com_err(program_name, stat, " in AddMachineToContainer."); + break; + } + } + celem = celem->q_forw; + } + celem = ctop; + melem = melem->q_forw; + } + FreeQueue(ctop); + FreeQueue(mtop); + return DM_NORMAL; +} + +int RemoveMachineFromContainer(int argc, char **argv) +{ + struct mqelem *elem = NULL; + char buf[BUFSIZ], *args[10]; + int stat; + + args[0] = canonicalize_hostname(strdup(argv[1])); + if (strcasecmp(args[0], argv[1]) && *argv[1] != '"') + { + sprintf(buf, "Warning: '%s' canonicalized to '%s'.", + argv[1], args[0]); + Put_message(buf); + } + args[1] = argv[2]; + args[2] = NULL; + + stat = do_mr_query("get_machine_to_container_map", 1, args, StoreInfo, + &elem); + if (stat == MR_NO_MATCH) + { + sprintf(buf, "The machine %s is not in the container %s.", + args[0], args[1]); + Put_message(buf); + free(args[0]); + return DM_NORMAL; + } + if (stat != MR_SUCCESS) + com_err(program_name, stat, " in deleter_machine_from_container"); + + elem = QueueTop(elem); + QueryLoop(elem, PrintMContMap, RealRemoveMachineFromContainer, + "Remove this machine from this container"); + + FreeQueue(elem); + free(args[0]); + return DM_NORMAL; +} + +static void RealRemoveMachineFromContainer(char **info, Bool one_contmap) +{ + char temp_buf[BUFSIZ]; + int stat; + + sprintf(temp_buf, "Remove %s from the container %s", + info[0], info[1]); + if (!one_contmap || Confirm(temp_buf)) + { + if ((stat = do_mr_query("delete_machine_from_container", 2, + info, NULL, NULL))) + com_err(program_name, stat, " in delete_machine_from_container"); + else + { + sprintf(temp_buf, "%s has been removed from the container %s.", + info[0], info[1]); + Put_message(temp_buf); + } + } + else + Put_message("Machine not removed."); +} + +int GetMachinesOfContainer(int argc, char **argv) +{ + char *args[2]; + struct mqelem *elem = NULL, *top = NULL; + int stat; + + args[0] = argv[1]; + if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE) + args[1] = "1"; + else + args[1] = "0"; + if (stat = do_mr_query("get_machines_of_container", 2, args, + StoreInfo, &elem)) + com_err(program_name, stat, " in get_machines_of_container"); + + top = QueueTop(elem); + Loop(top, ((void (*)(char **)) PrintMContMap)); + FreeQueue(top); + return DM_NORMAL; +} + +int GetTopLevelCont(int argc, char **argv) +{ + int status; + struct mqelem *elem = NULL; + if (status = do_mr_query("get_toplevel_containers", 0, NULL, StoreInfo, + &elem)) + { + com_err(program_name, status, " in get_toplevel_containers"); + return DM_NORMAL; + } + Loop(QueueTop(elem), (void(*)(char **)) PrintContainer); + FreeQueue(elem); + return DM_NORMAL; +}