X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/fbebf6dff5c344f2832f9bf8c05841d4720029c7..5cfca28fbb211515e0f8f2b3ce1878140aca6844:/clients/moira/cluster.c diff --git a/clients/moira/cluster.c b/clients/moira/cluster.c index f1296ef7..78cb4e37 100644 --- a/clients/moira/cluster.c +++ b/clients/moira/cluster.c @@ -26,6 +26,14 @@ #include #include #include +#include +#include +#include +#include +#ifdef POSIX +#include +#endif +#include #include "mit-copyright.h" #include "defs.h" @@ -36,6 +44,8 @@ #define CLUSTER 1 #define DATA 2 #define MAP 3 +#define SUBNET 4 +#define CNAME 5 #define M_DEFAULT_TYPE DEFAULT_NONE @@ -45,6 +55,28 @@ #define CD_DEFAULT_LABEL DEFAULT_NONE #define CD_DEFAULT_DATA DEFAULT_NONE +#define S_DEFAULT_LOW "18.0.0.10" +#define S_DEFAULT_HIGH "18.0.2.252" + +static char *states[] = { "Reserved (0)", + "Active (1)", + "None (2)", + "Deleted (3)" }; + +static char *MacState(state) +int state; +{ + char buf[BUFSIZ]; + + if (state < 0 || state > 3) { + sprintf(buf, "Unknown (%d)", state); + return(buf); + } + return(states[state]); +} + + + /* -------------------- Set Defaults -------------------- */ /* Function Name: SetMachineDefaults @@ -59,8 +91,20 @@ SetMachineDefaults(info, name) char ** info, *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; + info[M_VENDOR] = Strsave(M_DEFAULT_TYPE); + info[M_MODEL] = Strsave(M_DEFAULT_TYPE); + info[M_OS] = Strsave(M_DEFAULT_TYPE); + info[M_LOC] = Strsave(M_DEFAULT_TYPE); + info[M_CONTACT] = Strsave(M_DEFAULT_TYPE); + info[M_USE] = Strsave("0"); + info[M_STAT] = Strsave("1"); + info[8] = Strsave("NONE"); + info[9] = Strsave("unique"); + info[10] = Strsave("NONE"); + info[11] = Strsave("NONE"); + info[12] = Strsave(""); + info[13] = Strsave(""); + info[14] = info[15] = info[16] = NULL; return(info); } @@ -82,8 +126,53 @@ char ** info, *name; return(info); } +/* Function Name: SetSubnetDefaults + * Description: sets Subnet defaults. + * Arguments: info - an array to put the defaults into. + * name - name of the Subnet. + * Returns: info - the array. + */ + +static char ** +SetSubnetDefaults(info, name) +char ** info, *name; +{ + char buf[256]; + + info[C_NAME] = Strsave(name); + info[SN_DESC] = Strsave(""); + sprintf(buf, "%d", ntohl(inet_addr("18.255.0.0"))); + info[SN_ADDRESS] = Strsave(buf); + sprintf(buf, "%d", ntohl(inet_addr("255.255.0.0"))); + info[SN_MASK] = Strsave(buf); + sprintf(buf, "%d", ntohl(inet_addr(S_DEFAULT_LOW))); + info[SN_LOW] = Strsave(buf); + sprintf(buf, "%d", ntohl(inet_addr(S_DEFAULT_HIGH))); + info[SN_HIGH] = Strsave(buf); + info[SN_PREFIX] = Strsave(""); + info[SN_ACE_TYPE] = Strsave("LIST"); + info[SN_ACE_NAME] = Strsave("network_acl"); + info[SN_MODBY] = info[SN_MODTIME] = info[SN_MODWITH] = info[SN_END] = NULL; + return(info); +} + /* -------------------- General Functions -------------------- */ +static char aliasbuf[256]; + +static char * +PrintAliases(info) +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 * a coherent form. @@ -95,16 +184,73 @@ static char * PrintMachInfo(info) char ** info; { - char buf[BUFSIZ]; + char buf[BUFSIZ], tbuf[256]; + char *args[3]; + struct qelem *elem = NULL; + int stat; Put_message(""); - sprintf(buf, "Machine: %-30s Type: %s", info[M_NAME], info[M_TYPE]); + 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, (char *)&elem)) + != 0) { + if (stat != MR_NO_MATCH) + com_err(program_name, stat, " looking up aliases"); + } else { + aliasbuf[0] = 0; + Loop(QueueTop(elem), (void *) PrintAliases); + FreeQueue(elem); + Put_message(aliasbuf); + } + sprintf(buf, "Address: %-16s Subnet: %s", + info[M_ADDR], info[M_SUBNET]); + Put_message(buf); + sprintf(buf, "Status: %-16s Changed: %s", + MacState(atoi(info[M_STAT])), info[M_STAT_CHNG]); + Put_message(buf); + sprintf(tbuf, "%s %s", info[M_OWNER_TYPE], + strcmp(info[M_OWNER_TYPE], "NONE") ? info[M_OWNER_NAME] : ""); + sprintf(buf, "Owner: %-16s Last poll: %s", tbuf, info[M_INUSE]); + Put_message(buf); + Put_message(""); + + sprintf(buf, "Vendor: %-16s Model: %-24s OS: %s", + info[M_VENDOR], info[M_MODEL], info[M_OS]); + Put_message(buf); + sprintf(buf, "Location: %-16s Contact: %s Use code: %s", + info[M_LOC], info[M_CONTACT], info[M_USE]); + Put_message(buf); + sprintf(buf, "Admn 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); return(info[M_NAME]); } +/* 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(info) +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 * in a coherent form. @@ -166,6 +312,49 @@ char ** info; 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(info) +char ** info; +{ + char buf[BUFSIZ]; + struct in_addr addr, mask, low, high; + + Put_message(""); + sprintf(buf, "Subnet: %s", info[SN_NAME]); + Put_message(buf); + sprintf(buf, "Description: %s", info[SN_DESC]); + 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, ", 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", 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. * Description: This function stores info about a machine. * type - type of data we are trying to retrieve. @@ -182,11 +371,13 @@ char * name1, *name2; int stat; struct qelem * elem = NULL; - char * args[2]; + char * args[5]; switch (type) { case MACHINE: - if ( (stat = do_mr_query("get_machine", 1, &name1, + args[0] = name1; + args[1] = args[2] = args[3] = "*"; + if ( (stat = do_mr_query("get_host", 4, args, StoreInfo, (char *)&elem)) != 0) { if (stat == MR_NO_MATCH) { char buf[128]; @@ -197,6 +388,27 @@ char * name1, *name2; return(NULL); } break; + case CNAME: + args[0] = name1; + args[1] = name2; + if ( (stat = do_mr_query("get_hostalias", 2, args, + StoreInfo, (char *)&elem)) != 0) { + com_err(program_name, stat, " in get_hostalias."); + return(NULL); + } + break; + case SUBNET: + if ( (stat = do_mr_query("get_subnet", 1, &name1, + StoreInfo, (char *)&elem)) != 0) { + if (stat == MR_NO_MATCH) { + char buf[128]; + sprintf(buf, "Subnet '%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 = do_mr_query("get_cluster", 1, &name1, StoreInfo, (char *)&elem)) != 0) { @@ -249,6 +461,10 @@ Bool name; sprintf(temp_buf, "Setting the information for the Machine %s.", info[M_NAME]); break; + case SUBNET: + sprintf(temp_buf, "Setting the information for the Subnet %s.", + info[SN_NAME]); + break; case CLUSTER: sprintf(temp_buf, "Setting the information for the Cluster %s.", info[C_NAME]); @@ -276,6 +492,12 @@ Bool name; } free(oldnewname); break; + case SUBNET: + newname = Strsave(info[SN_NAME]); + if (GetValueFromUser("The new name for this subnet? ", + &newname) == SUB_ERROR) + return(NULL); + break; case CLUSTER: newname = Strsave(info[C_NAME]); if (GetValueFromUser("The new name for this cluster? ", @@ -290,12 +512,103 @@ Bool name; switch(type) { case MACHINE: - if (GetTypeFromUser("Machine's Type", "mac_type", &info[M_TYPE]) == + 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("Location of Machine", &info[M_LOC]) == SUB_ERROR) + return(NULL); + if (GetValueFromUser("Contact for Machine", &info[M_CONTACT]) == + SUB_ERROR) + return(NULL); + if (GetValueFromUser("Machine's Use Code", &info[M_USE]) == 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]); + } + if (name) { + free(info[8]); + info[8] = info[M_SUBNET]; + info[9] = info[M_ADDR]; + info[10] = info[M_OWNER_TYPE]; + info[11] = info[M_OWNER_NAME]; + info[12] = info[M_ACOMMENT]; + info[13] = info[M_OCOMMENT]; + } + if (GetValueFromUser("Machine's subnet (or 'none')", &info[8]) + == SUB_ERROR) + return(NULL); + if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')", + &info[9]) == SUB_ERROR) + return(NULL); + if (GetTypeFromUser("Machine's Owner Type", "ace_type", &info[10]) == SUB_ERROR) return(NULL); - FreeAndClear(&info[M_MODTIME], TRUE); - FreeAndClear(&info[M_MODBY], TRUE); - FreeAndClear(&info[M_MODWITH], TRUE); + if (strcmp(info[10], "NONE") && + GetValueFromUser("Owner's Name", &info[11]) == SUB_ERROR) + return(NULL); + if (GetValueFromUser("Administrative Comment", &info[12]) == SUB_ERROR) + return(NULL); + if (GetValueFromUser("Operational Comment", &info[13]) == SUB_ERROR) + return(NULL); + info[14] = NULL; + FreeAndClear(&info[15], TRUE); + FreeAndClear(&info[16], TRUE); + break; + case SUBNET: + if (GetValueFromUser("Subnet Description", &info[SN_DESC]) == SUB_ERROR) + return(NULL); + if (GetAddressFromUser("Subnet Address", &info[SN_ADDRESS]) == SUB_ERROR) + return(NULL); + if (GetAddressFromUser("Subnet Mask", &info[SN_MASK]) == SUB_ERROR) + return(NULL); + if (atoi(info[SN_LOW]) == 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, "%d", low.s_addr); + info[SN_LOW] = strsave(temp_buf); + } + if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) == SUB_ERROR) + return(NULL); + if (atoi(info[SN_HIGH]) == 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, "%d", high.s_addr); + info[SN_HIGH] = strsave(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); + FreeAndClear(&info[SN_MODTIME], TRUE); + FreeAndClear(&info[SN_MODBY], TRUE); + FreeAndClear(&info[SN_MODWITH], TRUE); break; case CLUSTER: if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) == @@ -351,6 +664,65 @@ char **argv; return(DM_NORMAL); } +/* 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. + */ + +/* ARGSUSED */ +int +ShowMachineQuery(argc, argv) +int argc; +char **argv; +{ + int stat; + struct qelem *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); + } + + if (*argv[1]) + args[0] = canonicalize_hostname(strsave(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, + (char *)&elem)) != 0) { + 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 *) 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]. @@ -363,7 +735,7 @@ AddMachine(argc, argv) int argc; char **argv; { - char **args, *info[MAX_ARGS_SIZE], *name, buf[256]; + char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5]; int stat; if (!ValidName(argv[1])) /* Checks for wildcards. */ @@ -373,7 +745,9 @@ char **argv; */ name = canonicalize_hostname(strsave(argv[1])); - if ( (stat = do_mr_query("get_machine", 1, &name, NullFunc, NULL)) == 0) { + xargs[0] = name; + xargs[1] = xargs[2] = xargs[3] = "*"; + if ( (stat = do_mr_query("get_host", 4, xargs, NullFunc, NULL)) == 0) { sprintf(buf, "The machine '%s' already exists.", name); Put_message(buf); free(name); @@ -396,7 +770,7 @@ char **argv; * Actually create the new Machine. */ - if ( (stat = do_mr_query("add_machine", CountArgs(args), + if ( (stat = do_mr_query("add_host", CountArgs(args), args, Scream, NULL)) != 0) com_err(program_name, stat, " in AddMachine."); @@ -424,7 +798,7 @@ Bool junk; Put_message("Aborted."); return; } - if ( (stat = do_mr_query("update_machine", CountArgs(args), + if ( (stat = do_mr_query("update_host", CountArgs(args), args, Scream, NULL)) != 0) com_err(program_name, stat, " in UpdateMachine."); else @@ -541,7 +915,7 @@ Bool one_machine; info[M_NAME]); if(!one_machine || Confirm(temp_buf)) { if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR) { - if ( (stat = do_mr_query("delete_machine", 1, + if ( (stat = do_mr_query("delete_host", 1, &info[M_NAME], Scream, NULL)) != 0) { com_err(program_name, stat, " in DeleteMachine."); sprintf(temp_buf, "%s ** NOT ** deleted.", @@ -581,6 +955,115 @@ char **argv; return(DM_NORMAL); } + +char *partial_canonicalize_hostname(s) +char *s; +{ + char buf[256], *cp; + static char *def_domain = NULL; + struct hostent *hp; +#ifdef POSIX + struct utsname name; +#endif + + if (!def_domain) { +#ifdef POSIX + (void) uname(&name); + strncpy(buf, name.nodename, sizeof(buf)); +#else + gethostname(buf, sizeof(buf)); +#endif + hp = gethostbyname(buf); + cp = strchr(hp->h_name, '.'); + if (cp) + def_domain = strsave(++cp); + else + def_domain = ""; + } + + if (strchr(s, '.') || strchr(s, '*')) + return(s); + sprintf(buf, "%s.%s", s, def_domain); + free(s); + return(strsave(buf)); +} + + +/* 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. + */ + +/* ARGSUSED */ +int +ShowCname(argc, argv) +int argc; +char **argv; +{ + struct qelem *top; + char *tmpalias, *tmpname; + + tmpalias = partial_canonicalize_hostname(strsave(argv[1])); + tmpname = canonicalize_hostname(strsave(argv[2])); + top = GetMCInfo(CNAME, tmpalias, tmpname); + Put_message(""); /* blank line on screen */ + Loop(top, ( (void *) PrintCname) ); + FreeQueue(top); + return(DM_NORMAL); +} + + +/* ARGSUSED */ +int +AddCname(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; + + args[0] = partial_canonicalize_hostname(strsave(argv[1])); + args[1] = canonicalize_hostname(strsave(argv[2])); + stat = do_mr_query("add_hostalias", 2, args, Scream, 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"); + } + return(DM_NORMAL); +} + + +/* ARGSUSED */ +int +DeleteCname(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; + + args[0] = partial_canonicalize_hostname(strsave(argv[1])); + args[1] = canonicalize_hostname(strsave(argv[2])); + stat = do_mr_query("delete_hostalias", 2, args, Scream, 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]. @@ -747,6 +1230,177 @@ char ** argv; 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. + */ + +/* ARGSUSED */ +int +ShowSubnetInfo(argc, argv) +int argc; +char ** argv; +{ + struct qelem *top; + + top = GetMCInfo(SUBNET, argv[1], (char *) NULL); + Loop(top, (void *) 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. + */ + +/* ARGSUSED */ +int +AddSubnet(argc, argv) +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, + NullFunc, 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)) == + NULL) { + Put_message("Aborted."); + FreeInfo(info); + return(DM_NORMAL); + } + +/* + * Actually create the new Subnet. + */ + if ( (stat = do_mr_query("add_subnet", CountArgs(args), + args, Scream, NULL)) != 0) + 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. + */ + +/* ARGSUSED */ +static void +RealUpdateSubnet(info, junk) +char ** info; +Bool junk; +{ + register int stat; + char ** args = AskMCDInfo(info, SUBNET, TRUE); + if (args == NULL) { + Put_message("Aborted."); + return; + } + if ( (stat = do_mr_query("update_subnet", CountArgs(args), + args, Scream, NULL)) != 0) + 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. + */ + +/* ARGSUSED */ +int +UpdateSubnet(argc, argv) +int argc; +char ** argv; +{ + struct qelem *top; + top = GetMCInfo( SUBNET, argv[1], (char *) 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(info, one_subnet) +char ** info; +Bool one_subnet; +{ + register 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], Scream, NULL)) != 0) { + 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 sucesfully deleted.", + info[C_NAME]); + Put_message(temp_buf); + } + } +} + +/* 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. + */ + +/* ARGSUSED */ +int +DeleteSubnet(argc, argv) +int argc; +char ** argv; +{ + struct qelem *top; + + top = GetMCInfo( SUBNET, argv[1], (char *) NULL ); + QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet"); + + FreeQueue(top); + return(DM_NORMAL); +} + /* ---------- Cluster Menu -------- */ /* Function Name: ShowClusterInfo