]> andersk Git - moira.git/blobdiff - clients/moira/cluster.c
better defaults on machine info; print machine aliases
[moira.git] / clients / moira / cluster.c
index adf9ad3cb09f88e39e0aa16df6fddd0159b52bcb..78cb4e3735294f049022f7e3816e7fab47c01b37 100644 (file)
@@ -1,20 +1,19 @@
-#ifndef lint
+#if (!defined(lint) && !defined(SABER))
   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.
+/*     This is the file cluster.c for the MOIRA Client, which allows a nieve
+ *      user 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.
+ *     Copyright 1988 by the Massachusetts Institute of Technology.
  *
  *     For further information on copyright and distribution 
  *     see the file mit-copyright.h
 
 #include <stdio.h>
 #include <strings.h>
-#include <sms.h>
+#include <moira.h>
+#include <moira_site.h>
 #include <menu.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#ifdef POSIX
+#include <sys/utsname.h>
+#endif
+#include <netdb.h>
 
 #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
+#define SUBNET  4
+#define CNAME   5
 
 #define M_DEFAULT_TYPE     DEFAULT_NONE
 
 #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
  *     Returns: info - the array.
  */
 
-char **
+static char **
 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);
 }
 
@@ -72,7 +115,7 @@ char ** info, *name;
  *     Returns: info - the array.
  */
 
-char **
+static char **
 SetClusterDefaults(info, name)
 char ** info, *name;
 {
@@ -83,56 +126,139 @@ char ** info, *name;
     return(info);
 }
 
-/*     Function Name: SetClusterDataDefaults
- *     Description: Sets cluster data defaults.
+/*     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)
+static char **
+SetSubnetDefaults(info, name)
 char ** info, *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;
+    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.
  *     Arguments: info - array of information about a machine.
- *     Returns: none.
+ *     Returns: The name of the Machine
  */
 
-void
+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, "Last Modified at %s, by %s with %s",info[M_MODTIME],
-           info[M_MODBY], info[M_MODWITH]);
+    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.
  *     Arguments: info - array of information about a cluster.
- *     Returns: none.
+ *     Returns: The name of the cluster.
  */
 
-void
+static char *
 PrintClusterInfo(info)
 char ** info;
 {
@@ -145,18 +271,18 @@ char ** info;
     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]);
+    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
+static char *
 PrintClusterData(info)
 char ** info;
 {
@@ -166,6 +292,7 @@ char ** info;
     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,7 +301,7 @@ char ** info;
  *     Returns: none
  */
 
-void
+static char *
 PrintMCMap(info)
 char ** info;
 {
@@ -182,6 +309,50 @@ char ** info;
     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(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.
@@ -200,19 +371,47 @@ char * name1, *name2;
 
     int stat;
     struct qelem * elem = NULL;
-    char * args[2];
+    char * args[5];
 
     switch (type) {
     case MACHINE:
-       if ( (stat = sms_query("get_machine", 1, &name1,
-                              StoreInfo, &elem)) != 0) {
-           com_err(program_name, stat, " in get_machine.");
+       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];
+               sprintf(buf, "Machine '%s' is not in the database.", name1);
+               Put_message(buf);
+           } else
+             com_err(program_name, stat, " in get_machine.");
+           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 = sms_query("get_cluster",  1, &name1,
-                              StoreInfo, &elem)) != 0) {
+       if ( (stat = do_mr_query("get_cluster",  1, &name1,
+                                 StoreInfo, (char *)&elem)) != 0) {
            com_err(program_name, stat, " in get_cluster.");
            return(NULL);
        }
@@ -220,8 +419,8 @@ char * name1, *name2;
     case MAP:
        args[MAP_MACHINE] = name1;
        args[MAP_CLUSTER] = name2;
-       if ( (stat = sms_query("get_machine_to_cluster_map", 2, args,
-                              StoreInfo, &elem)) != 0) {
+       if ( (stat = do_mr_query("get_machine_to_cluster_map", 2, args,
+                                 StoreInfo, (char *)&elem)) != 0) {
            com_err(program_name, stat, " in get_machine_to_cluster_map.");
            return(NULL);
        }
@@ -229,8 +428,8 @@ char * name1, *name2;
     case DATA:
        args[CD_NAME] = name1;
        args[CD_LABEL] = name2;
-       if ( (stat = sms_query("get_cluster_data", 2, args,
-                              StoreInfo, &elem)) != 0) {
+       if ( (stat = do_mr_query("get_cluster_data", 2, args,
+                                 StoreInfo, (char *)&elem)) != 0) {
            com_err(program_name, stat, " in get_cluster_data.");
            return(NULL);
        }
@@ -255,13 +454,17 @@ char ** info;
 int type;
 Bool name;
 {
-    char temp_buf[BUFSIZ], *newname;
+    char temp_buf[BUFSIZ], *newname, *oldnewname;
 
     switch (type) {
     case MACHINE:
        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]);
@@ -277,15 +480,29 @@ Bool 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);
+           if (GetValueFromUser("The new name for this machine? ", &newname) ==
+               SUB_ERROR)
+             return(NULL);
+           oldnewname = Strsave(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 = 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]);
-           GetValueFromUser("The new name for this cluster? ",
-                            &newname);
+           if (GetValueFromUser("The new name for this cluster? ",
+                                &newname) == SUB_ERROR)
+             return(NULL);
            break;
        default:
            Put_message("Unknown type in AskMCDInfo, programmer botch");
@@ -295,21 +512,121 @@ Bool name;
 
     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);
+       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);
+       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:
-       GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]);
-       GetValueFromUser("Cluster's Location:", &info[C_LOCATION]);
+       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]);
+       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;
     }
 
@@ -337,17 +654,71 @@ ShowMachineInfo(argc, argv)
 int argc;
 char **argv;
 {
-    struct qelem *elem, *top;
+    struct qelem *top;
+    char *tmpname;
 
-    top = elem = GetMCInfo(MACHINE, CanonicalizeHostname(argv[1]),
-                          (char *) NULL);
+    tmpname = canonicalize_hostname(strsave(argv[1]));
+    top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
+    Loop(top, ( (void *) PrintMachInfo) );
+    FreeQueue(top);
+    return(DM_NORMAL);
+}
 
-    while (elem != NULL) {
-       char **info = (char **) elem->q_data;
-       PrintMachInfo(info);
-       elem = elem->q_forw;
+/*     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);
 }
@@ -364,36 +735,76 @@ AddMachine(argc, argv)
 int argc;
 char **argv;
 {
-    char **args, *info[MAX_ARGS_SIZE], *name;
+    char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
     int stat;
+
+    if (!ValidName(argv[1]))   /* Checks for wildcards. */
+       return(DM_NORMAL);
 /* 
  * Check to see if this machine already exists. 
  */
-    name =  CanonicalizeHostname(argv[1]);
+    name =  canonicalize_hostname(strsave(argv[1]));
 
-    if ( (stat = sms_query("get_machine", 1, &name, NullFunc, NULL)) == 0) {
-       Put_message("This machine already exists.");
+    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);
        return(DM_NORMAL);
     }
-    else if (stat != SMS_NO_MATCH) {
-       com_err(program_name, stat, " in AddMachine.");
+    else if (stat != MR_NO_MATCH) {
+       com_err(program_name, stat,
+               " while checking machine '%s' in AddMachine.", name);
+       free(name);
        return(DM_NORMAL);
     }
 
-    args = AskMCDInfo(SetMachineDefaults(info, name), MACHINE, FALSE);
+    if ((args = AskMCDInfo(SetMachineDefaults(info, name), MACHINE, FALSE)) ==
+       NULL) {
+       Put_message("Aborted.");
+       return(DM_NORMAL);
+    }
 
 /*
  * Actually create the new Machine.
  */
     
-    if ( (stat = sms_query("add_machine", CountArgs(args), 
-                          args, Scream, NULL)) != 0)
+    if ( (stat = do_mr_query("add_host", CountArgs(args), 
+                             args, Scream, NULL)) != 0)
        com_err(program_name, stat, " in AddMachine.");
 
     FreeInfo(info);
+    free(name);
     return(DM_NORMAL);
 }
 
+/*     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.
+ */
+
+/* ARGSUSED */
+static void
+RealUpdateMachine(info, junk)
+char ** info;
+Bool junk;
+{
+    register int stat;
+    char ** args = AskMCDInfo(info, MACHINE, TRUE);
+    if (args == NULL) {
+       Put_message("Aborted.");
+       return;
+    }
+    if ( (stat = do_mr_query("update_host", CountArgs(args), 
+                             args, Scream, NULL)) != 0)
+       com_err(program_name, stat, " in UpdateMachine.");
+    else
+       Put_message("Machine sucessfully updated.");
+}
+
 /*     Function Name: UpdateMachine
  *     Description: This function adds a new machine to the database.
  *     Arguments: argc, argv - the name of the machine in argv[1].
@@ -406,43 +817,15 @@ 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);
+    struct qelem *top;
+    char *tmpname;
+
+    tmpname = canonicalize_hostname(strsave(argv[1]));
+    top = GetMCInfo( MACHINE,  tmpname, (char *) NULL);
+    QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
 
-    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);
+    free(tmpname);
     return(DM_NORMAL);
 }
 
@@ -451,7 +834,7 @@ char **argv;
  *                   and if so then removes it
  *     Arguments: name - name of the machine (already Canonocalized).
  *                 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 
@@ -464,28 +847,23 @@ Bool ask_user;
     char *args[10], temp_buf[BUFSIZ], *ptr;
     struct qelem *top, *elem = NULL;
     
-    ret_value = SUB_NORMAL;
+    ret_value = SUB_NORMAL;    /* initialize ret_value. */
     args[0] = name;
     args[1] = "*";
-    stat = sms_query("get_machine_to_cluster_map", 2, args, 
-                        StoreInfo, &elem);
-    if (stat && stat != SMS_NO_MATCH) {
+    stat = do_mr_query("get_machine_to_cluster_map", 2, args, 
+                       StoreInfo, (char *)&elem);
+    if (stat && stat != MR_NO_MATCH) {
        com_err(program_name, stat, " in get_machine_to_cluster_map.");
        return(DM_NORMAL);
     }
-    if (stat == 0) {
+    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);
-           while (elem != NULL) {
-               char **info = (char **) elem->q_data;
-               Print(1, &info[MAP_CLUSTER], (char *) NULL);
-               elem = elem->q_forw;
-           }
+           Loop(top, (void *) PrintMCMap);
            ptr = "Remove this machine from ** ALL ** these clusters?";
-
            if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
                delete_it = TRUE;
            else {
@@ -498,11 +876,10 @@ Bool ask_user;
            delete_it = TRUE;
 
        if (delete_it) {
-           elem = top;
-           while (elem != 0) {
+           while (elem != NULL) {
                char **info = (char **) elem->q_data;
-               if ( (stat = sms_query( "delete_machine_from_cluster",
-                                      2, info, Scream, NULL)) != 0) {
+               if ( (stat = do_mr_query( "delete_machine_from_cluster",
+                                         2, info, Scream, NULL)) != 0) {
                    ret_value = SUB_ERROR;
                    com_err(program_name, stat, 
                            " in delete_machine_from_cluster.");
@@ -518,6 +895,41 @@ Bool ask_user;
     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.
+ */
+
+static void
+RealDeleteMachine(info, one_machine)
+char ** info;
+Bool one_machine;
+{
+    register 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 ( (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.", 
+                       info[M_NAME]);
+               Put_message(temp_buf);
+           }
+           else {
+               sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
+               Put_message(temp_buf);
+           }
+       }
+    }
+}
+
 /*     Function Name: DeleteMachine
  *     Description: This function removes a machine from the data base.
  *     Arguments: argc, argv - the machines name int argv[1].
@@ -532,59 +944,126 @@ 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;
+    struct qelem *top;
+    char *tmpname;
 
-    name =  CanonicalizeHostname(argv[1]);
-    top = elem = GetMCInfo(MACHINE, name, (char *) NULL);
+    tmpname = canonicalize_hostname(strsave(argv[1]));
+    top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
+    QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
+    FreeQueue(top);
+    free(tmpname);
+    return(DM_NORMAL);
+}
 
-    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;
+
+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].
@@ -603,15 +1082,23 @@ char ** argv;
     Bool add_it, one_machine, one_cluster;
     struct qelem * melem, *mtop, *celem, *ctop;
 
-    machine = CanonicalizeHostname(argv[1]);
+    machine = canonicalize_hostname(strsave(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, (char *) NULL);
     melem = mtop = GetMCInfo(MACHINE,  machine, (char *) NULL);
+    free(machine);
 
     one_machine = (QueueCount(mtop) == 1);
     one_cluster = (QueueCount(ctop) == 1);
 
+    /* No good way to use QueryLoop() here, sigh */
+
     while (melem != NULL) {
        char ** minfo = (char **) melem->q_data;
        while (celem != NULL) {
@@ -638,12 +1125,12 @@ char ** argv;
            if (add_it) {
                args[0] = minfo[M_NAME];
                args[1] = cinfo[C_NAME];
-               stat = sms_query("add_machine_to_cluster", 2, args,
-                                Scream, NULL);
+               stat = do_mr_query("add_machine_to_cluster", 2, args,
+                                   Scream, NULL);
                switch (stat) {
-               case SMS_SUCCESS:
+               case MR_SUCCESS:
                    break;
-               case SMS_EXISTS:
+               case MR_EXISTS:
                    sprintf(temp_buf, "%s is already in cluster %s",
                            minfo[M_NAME], cinfo[C_NAME]);
                    Put_message(temp_buf);
@@ -663,6 +1150,39 @@ char ** argv;
     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(info, one_map)
+char ** info;
+Bool one_map;
+{
+    char temp_buf[BUFSIZ];
+    register 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, Scream, NULL)) != 0 )
+           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
  *     Description: Removes this machine form a specific cluster.
  *     Arguments: argc, argv - Name of machine in argv[1].
@@ -676,64 +1196,211 @@ RemoveMachineFromCluster(argc, argv)
 int argc;
 char ** argv;
 {
-    int stat;
-    Bool remove_machine, one_item;
-    struct qelem *top, *elem = NULL;
+    struct qelem *elem = NULL;
     char buf[BUFSIZ], * args[10];
+    register int stat;
 
-    args[MAP_MACHINE] = CanonicalizeHostname(argv[1]);
+    args[MAP_MACHINE] = canonicalize_hostname(strsave(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,
-                    StoreInfo, &elem);
-    if (stat == SMS_NO_MATCH) {
+    stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
+                       StoreInfo, (char *)&elem);
+    if (stat == MR_NO_MATCH) {
        sprintf(buf, "The machine %s is not is the cluster %s.",
                args[MAP_MACHINE], args[MAP_CLUSTER]);
        Put_message(buf);
+       free(args[MAP_MACHINE]);
        return(DM_NORMAL);
     }
-    if (stat)
+    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;
+    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.
+ */
+
+/* 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(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);
-           }
+           sprintf(temp_buf, "subnet %s sucesfully 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;
     }
+}
+
+/*     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
@@ -748,16 +1415,10 @@ ShowClusterInfo(argc, argv)
 int argc;
 char ** argv;
 {
-    char **info;
-    struct qelem *elem, *top;
+    struct qelem *top;
 
-    top = elem = GetMCInfo( CLUSTER, CanonicalizeHostname(argv[1]),
-                          (char *) NULL);
-    while (elem != NULL) {
-       info = (char **) elem->q_data;
-       PrintClusterInfo(info);
-       elem = elem->q_forw;
-    }
+    top = GetMCInfo(CLUSTER, argv[1], (char *) NULL);
+    Loop(top, (void *) PrintClusterInfo);
     FreeQueue(top);
     return(DM_NORMAL);
 }
@@ -774,36 +1435,67 @@ AddCluster(argc, argv)
 int argc;
 char ** argv;
 {
-    char **args, *info[MAX_ARGS_SIZE], *name;
+    char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
     int stat;
 /* 
- * Check to see if this machine already exists. 
+ * Check to see if this cluster already exists. 
  */
-    name = argv[1];
+    if (!ValidName(name))
+       return(DM_NORMAL);
 
-    if ( (stat = sms_query("get_cluster", 1, &name, NullFunc, NULL)) == 0) {
+    if ( (stat = do_mr_query("get_cluster", 1, &name, 
+                             NullFunc, NULL)) == MR_SUCCESS) {
        Put_message("This cluster already exists.");
        return(DM_NORMAL);
     }
-    else if (stat != SMS_NO_MATCH) {
+    else if (stat != MR_NO_MATCH) {
        com_err(program_name, stat, " in AddCluster.");
        return(DM_NORMAL);
     }
-
-    args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE);
+    if ((args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)) ==
+       NULL) {
+       Put_message("Aborted.");
+       FreeInfo(info);
+       return(DM_NORMAL);
+    }
 
 /*
  * Actually create the new Cluster.
  */
-    
-    if ( (stat = sms_query("add_cluster", CountArgs(args), 
-                          args, Scream, NULL)) != 0)
+    if ( (stat = do_mr_query("add_cluster", CountArgs(args), 
+                             args, Scream, NULL)) != 0)
        com_err(program_name, stat, " in AddCluster.");
 
     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.
+ */
+
+/* ARGSUSED */
+static void
+RealUpdateCluster(info, junk)
+char ** info;
+Bool junk;
+{
+    register int stat;
+    char ** args = AskMCDInfo(info, CLUSTER, TRUE);
+    if (args == NULL) {
+       Put_message("Aborted.");
+       return;
+    }
+    if ( (stat = do_mr_query("update_cluster", CountArgs(args), 
+                             args, Scream, NULL)) != 0)
+       com_err(program_name, stat, " in UpdateCluster.");
+    else
+       Put_message("Cluster successfully updated.");
+}
+
 /*     Function Name: UpdateCluster
  *     Description: This Function Updates a cluster
  *     Arguments: name of the cluster in argv[1].
@@ -816,41 +1508,10 @@ 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 );
+    struct qelem *top;    
+    top = GetMCInfo( CLUSTER, argv[1], (char *) NULL );
+    QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
 
-    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);
 }
@@ -877,9 +1538,9 @@ Bool ask_first;
     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) {
+    stat = do_mr_query("get_machine_to_cluster_map", 2, args, 
+                       StoreInfo, (char *)&elem);
+    if (stat && stat != MR_NO_MATCH) {
        com_err(program_name, stat, " in get_machine_to_cluster_map.");
        return(DM_NORMAL);
     }
@@ -912,8 +1573,8 @@ Bool ask_first;
            elem = top;
            while (elem != 0) {
                char **info = (char **) elem->q_data;
-               if ( (stat = sms_query( "delete_machine_from_cluster",
-                                      2, info, Scream, NULL)) != 0) {
+               if ( (stat = do_mr_query("delete_machine_from_cluster",
+                                         2, info, Scream, NULL)) != 0) {
                    ret_value = SUB_ERROR;
                    com_err(program_name, stat, 
                            " in delete_machine_from_cluster.");
@@ -929,6 +1590,42 @@ Bool ask_first;
     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(info, one_cluster)
+char ** info;
+Bool one_cluster;
+{
+    register 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], Scream, NULL)) != 0) {
+               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 sucesfully deleted.", 
+                       info[C_NAME]);
+               Put_message(temp_buf);
+           }
+       }
+    }
+}
 
 /*     Function Name: DeleteCluster
  *     Description: This function removes a cluster from the database.
@@ -942,60 +1639,15 @@ DeleteCluster(argc, argv)
 int argc;
 char ** argv;
 {
-    char temp_buf[BUFSIZ];
-    int stat;
-    Bool one_cluster, delete_it = FALSE;
-    struct qelem *elem, *top;
+    struct qelem *top;
 
-    top = elem = GetMCInfo( CLUSTER, argv[1], (char *) NULL );
+    top = GetMCInfo( CLUSTER, argv[1], (char *) NULL );
+    QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
 
-    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);
 }
-
+    
 /* ----------- Cluster Data Menu -------------- */
 
 /*     Function Name: ShowClusterData
@@ -1040,10 +1692,41 @@ char ** argv;
 { 
     int stat;
 
-    if( (stat = sms_query("add_cluster_data", 3, argv + 1,
-                         Scream, (char *) NULL)) != 0)
+    if( (stat = do_mr_query("add_cluster_data", 3, argv + 1,
+                            Scream, (char *) NULL)) != 0)
        com_err(program_name, stat, " in AddClusterData.");
+    return(DM_NORMAL);
+}
+
+/*     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(info, one_item)
+char ** info;
+Bool one_item;
+{
+    register 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,
+                                Scream, (char *) NULL)) != 0) {
+           com_err(program_name, stat, " in DeleteClusterData.");
+           Put_message("Data not removed.");
+       }
+       else
+           Put_message("Removal sucessful.");
+    }
 }
 
 /*     Function Name: RemoveClusterData
@@ -1060,54 +1743,16 @@ RemoveClusterData(argc, argv)
 int argc; 
 char ** argv; 
 {
-    Bool one_piece_of_data, remove_it;
-    int stat;
-    struct qelem *elem, *top;
+    struct qelem *top;
 
-    top = elem = GetMCInfo(DATA, argv[1], argv[2]);
+    top = GetMCInfo(DATA, argv[1], argv[2]);
+    QueryLoop(top, PrintClusterData, RealRemoveClusterData, 
+             "Remove data from cluster");
 
-    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);
 }
 
-/* Perhaps an interactive delete cluster data would be nice. */
-
 /*     Function Name: MachineToClusterMap
  *     Description: This Retrieves the mapping between machine and cluster
  *     Arguments: argc, argv - argv[1] -> machine name or wildcard.
@@ -1122,8 +1767,15 @@ int argc;
 char **argv;
 {
     struct qelem *elem, *top;
+    char *tmpname, temp_buf[256];
 
-    top = elem = GetMCInfo(MAP, CanonicalizeHostname(argv[1]), argv[2]);
+    tmpname = canonicalize_hostname(strsave(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 != NULL) {
@@ -1133,38 +1785,6 @@ char **argv;
     }
 
     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;
- */
-
-/* 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:
- */
-
-
-
This page took 0.109217 seconds and 4 git commands to generate.