]> andersk Git - moira.git/commitdiff
Initial revision
authorkit <kit>
Thu, 9 Jun 1988 14:12:43 +0000 (14:12 +0000)
committerkit <kit>
Thu, 9 Jun 1988 14:12:43 +0000 (14:12 +0000)
12 files changed:
clients/moira/attach.c [new file with mode: 0644]
clients/moira/cluster.c [new file with mode: 0644]
clients/moira/delete.c [new file with mode: 0644]
clients/moira/globals.c [new file with mode: 0644]
clients/moira/globals.h [new file with mode: 0644]
clients/moira/lists.c [new file with mode: 0644]
clients/moira/main.c [new file with mode: 0644]
clients/moira/menus.c [new file with mode: 0644]
clients/moira/nfs.c [new file with mode: 0644]
clients/moira/user.c [new file with mode: 0644]
clients/moira/utils.c [new file with mode: 0644]
include/moira_site.h [new file with mode: 0644]

diff --git a/clients/moira/attach.c b/clients/moira/attach.c
new file mode 100644 (file)
index 0000000..0947fd0
--- /dev/null
@@ -0,0 +1,613 @@
+#ifndef lint
+  static char rcsid_module_c[] = "$Header$";
+#endif lint
+
+/*     This is the file attach.c for allmaint, the SMS client that allows
+ *      a user to maintaint most important parts of the SMS database.
+ *     It Contains: Functions for maintaining data used by Hesiod 
+ *                   to map courses/projects/users to their file systems, 
+ *                   and maintain filesys info. 
+ *     
+ *     Created:        5/4/88
+ *     By:             Chris D. Peterson
+ *      Based Upon:     attach.c 87/07/24 marcus
+ *
+ *      $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
+ */
+
+#include "mit-copyright.h"
+#include "allmaint.h"
+#include "globals.h"
+#include "infodefs.h"
+
+#include <stdio.h>
+#include <strings.h>
+#include <sms.h>
+#include <menu.h>
+
+#define FS_ALIAS_TYPE "FILESYS"
+
+#define FS_NAME         0
+#define FS_TYPE         1
+#define FS_MACHINE      2
+#define FS_PACK         3
+#define FS_M_POINT      4
+#define FS_ACCESS       5
+#define FS_COMMENTS     6
+#define FS_OWNER        7
+#define FS_OWNERS       8
+#define FS_CREATE       9
+#define FS_L_TYPE       10
+#define FS_MODTIME      11
+#define FS_MODBY        12
+#define FS_MODWITH      13
+
+#define FS_LABEL        14
+/* FS_MACHINE already defined, this is okay, as there is no overlap. */
+#define FS_GROUP        15
+
+/*     Function Name: GetFSInfo
+ *     Description: Stores the info in a queue.
+ *     Arguments: type - type of information to get.
+ *                 name - name of the item to get information on.
+ *     Returns: a pointer to the first element in the queue.
+ */
+
+struct qelem *
+GetFSInfo(type, name)
+int type;
+char *name;
+{
+    int stat;
+    struct qelem * elem = NULL;
+    char * args[2];
+
+    switch (type) {
+    case FS_LABEL:
+       if ( (stat = sms_query("get_filesys_by_label", 1, &name,
+                              StoreInfo, &elem)) != 0) {
+           com_err(whoami, stat, NULL);
+           return(NULL);
+       }
+       break;
+    case FS_MACHINE:
+       if ( (stat = sms_query("get_filesys_by_label", 1, &name,
+                              StoreInfo, &elem)) != 0) {
+           com_err(whoami, stat, NULL);
+           return(NULL);
+       }
+       break;
+    case FS_GROUP:
+       if ( (stat = sms_query("get_filesys_by_label", 1, &name,
+                              StoreInfo, &elem)) != 0) {
+           com_err(whoami, stat, NULL);
+           return(NULL);
+       }
+       break;
+    case FS_ALIAS:
+       args[0] = name;
+       args[1] = FS_ALIAS_TYPE;
+       if ( (stat = sms_query("get_alias", 2, args, StoreInfo, &elem)) != 0) {
+           com_err(whoami, stat, " in get_alias.");
+           return(NULL);
+       }
+    }
+
+    return(QueueTop(elem));
+}
+
+/*     Function Name: PrintFSInfo
+ *     Description: Prints the filesystem information.
+ *     Arguments: info - a pointer to the filesystem information.
+ *     Returns: none.
+ */
+
+PrintFSInfo(info);
+char ** info;
+{
+    char print_buf[BUFSIZ];
+    sprintf(print_buf,"Information about filesystem: %s", info[FS_NAME]);
+    Put_message(print_buf);
+    sprintf(print_buf,"Type: %s\t\tMachine: %s\t\tPackname: %s",info[FS_TYPE],
+           info[FS_MACHINE], info[FS_PACK]);
+    Put_message(print_buf);
+    sprintf(print_buf,"Mountpoint %s\t\t Default Access: %s",info[FS_M_POINT],
+           info[FS_ACCESS]);
+    Put_message(print_buf);
+    sprintf(print_buf,"Comments; %s",info[FS_COMMENTS]);
+    Put_message(print_buf);
+    sprintf(print_buf, "User Ownership: %s,\t\tGroup Ownership:\t\t%s",
+           info[FS_OWNER], info[FS_OWNERS]);
+    Put_message(print_buf);
+    sprintf(print_buf, "Auto Create %s\t\tLocker Type: %s",info[FS_CREATE], 
+           info[FS_L_TYPE]);
+    Put_message(print_buf);
+    sprintf(print_buf, "Last Modified at %s, by %s with %s",info[FS_MODTIME],
+           info[FS_MODBY], info[FS_MODWITH]);
+    Put_message(print_buf);
+}
+
+/*     Function Name: PrintAllFSInfo
+ *     Description: Prints all infomation about a filesystem, stored in
+ *                   a queue.
+ *     Arguments: elem - a pointer to the first elem in the queue.
+ *     Returns: none.
+ */
+
+void
+PrintAllFSInfo(elem)
+struct qelem * elem;
+{
+/* 
+ * Not nescessary, but makes it clear that we are not changing this value.
+ */
+    struct qelem * local = elem;       
+                               
+    while(local != NULL) {
+       char ** info = (char **) local->q_date;
+       PrintFSInfo(info);
+       local = local->next;
+    }
+}
+
+/*     Function Name: AskFSInfo.
+ *     Description: This function askes the user for information about a 
+ *                   machine and saves it into a structure.
+ *     Arguments: info - a pointer the the structure to put the
+ *                             info into.
+ *                 name - add a newname field? (T/F)
+ *     Returns: none.
+ */
+
+void
+AskFSInfo(info, flags);
+char ** info;
+Bool name;
+{
+    char * temp_buf, *newname;
+    char *ret_args[100];
+    int counter;
+
+    sprintf(temp_buf,"\nChanging Attributes of user %s.\n",info[NAME]);
+    Put_message(temp_buf);
+
+    if (name) {
+       newname = Strsave(info[FS_NAME]);
+       GetValueFromUser("The new login name for this filesystem.",
+                        &newname);
+    }
+
+    GetValueFromUser("Filesystem's Type:", &info[FS_TYPE]);
+    GetValueFromUser("Filesystem's Machine:", &info[FS_MACHINE]);
+    GetValueFromUser("Filesystem's Pack Name:", &info[FS_PACK]);
+    GetValueFromUser("Filesystem's Mount Point:", &info[FS_M_POINT]);
+    GetValueFromUser("Filesystem's Default Access:", &info[FS_ACCESS]);
+    GetValueFromUser("Commants about this Filesystem:", &info[FS_COMMENTS]);
+    GetValueFromUser("Filesystem's owner (user):", &info[FS_OWNER]);
+    GetValueFromUser("Filesystem's owners (group):", &info[FS_OWNERS]);
+    GetValueFromUser("Automatically create this filsystem (0/1):",
+                    &info[FS_COMMENTS]);
+    GetValueFromUser("Filesystem's lockertype:", &info[FS_L_TYPE]);
+
+    FreeAndClear(&info[FS_MODTIME], TRUE);
+    FreeAndClear(&info[FS_MODBY], TRUE);
+    FreeAndClear(&info[FS_MODWITH], TRUE);
+
+    if (name)                  /* slide the newname into the #2 slot. */
+       SlipInNewName(info, newname);
+
+    return(info);
+}
+
+/* --------------- Filesystem Menu ------------- */
+
+/*     Function Name: GetFS
+ *     Description: Get Filesystem information by name.
+ *     Arguments: argc, argv - name of filsys in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+GetFS(argc, argv)
+int argc;
+char **argv;
+{
+    struct qelem *elem;
+
+    elem = GetFSInfo();        /* get info. */
+    PrintAllFSInfo(elem);      /* print it all. */
+    FreeQueue(elem);           /* clean the queue. */
+    return (DM_NORMAL);
+}
+
+/*     Function Name: DeleteFS
+ *     Description: Delete a filesystem give its name.
+ *     Arguments: argc, argv - argv[1] is the name of the filesystem.
+ *     Returns: none.
+ */
+
+/* ARGSUSED */
+int
+DeleteFS(argc, argv)
+int argc;
+char **argv;
+{
+    int stat, answer, delete, number;
+    struct qelem *elem, *temp_elem;
+    
+    if ( (temp_elem = elem = GetFSInfo(FS_LABEL, argv[1],
+                            (char *) NULL) ) == NULL ) /* get info. */
+       return(DM_NORMAL);
+/* 
+ * 1) If there is no (zero) match then we exit immediately.
+ * 2) If there is exactly 1 element then we ask for confirmation only if in
+ *    verbose mode, via the Confirm function.  
+ * 3) If there is more than 1 filesystem to be deleted then we ask
+ *    about each one, and delete on yes only, and about if the user hits
+ *    quit.
+ */
+    number = QueueCount(elem);
+    while (temp_elem != NULL) {
+       char **info = (char **) temp_elem->q_data;
+       
+       if (number != 1) {
+           PrintFSInfo(info);
+       
+           answer = YesNoQuitQuestion("\nDelete this filesys?", FALSE); 
+           switch(answer) {
+           case TRUE:
+               delete = TRUE;
+               break;
+           case FALSE:
+               delete = FALSE;
+               break;
+           default:            /* Quit. */
+               Put_message("Aborting Delete Operation.");
+               FreeQueue(elem);
+               return(DM_NORMAL);
+           }
+       }
+       else
+           delete = 
+            Confirm("Are you sure that you want to delete this filsystem.")) 
+/* 
+ * Deletetions are  performed if the user hits 'y' on a list of multiple 
+ * filesystem, or if the user confirms on a unique alias.
+ */
+       if (delete) {
+           if ( (status = sms_query("delete_filesys", 1,
+                                    &name, NullFunc, NULL)) != 0)
+               com_err(whoami, stat, " filesystem not deleted.");
+           else
+               Put_message("Filesystem deleted.");
+       }
+       else 
+           Put_message("Filesystem not deleted.");
+       temp_elem = temp_elem->next;
+    }
+
+    FreeQueue(elem);           /* free all members of the queue. */
+    return (DM_NORMAL);
+}
+
+/*     Function Name: ChangeFS
+ *     Description: change the information in a filesys record.
+ *     Arguments: arc, argv - value of filsys in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+ChangeFS(argc, argv)
+char **argv;
+int argc;
+{
+    FS_info *info;
+    struct qelem * elem, temp_elem;
+    int update, stat, answer;
+    
+    elem = temp_elem = GetFSInfo(FS_LABEL, argv[1], (char *) NULL);
+
+/* 
+ * This uses the same basic method as the deletion routine above.
+ */
+
+    number = QueueCount(elem);
+    while (temp_elem != NULL) {
+       char ** info = (char **) temp_elem->q_data;
+       if (number != 1) {
+           sprintf(buf, "%s %s %s (y/n/q)? ", "Would you like to change the",
+                   "information about the filesystem:", 
+                   info[FS_NAME]);
+           info = (char **) temp_elem->q_data;
+           answer = YesNoQuitQuestion(buf, FALSE);
+           switch(answer) {
+           case TRUE:
+               update = TRUE
+               break;
+           case FALSE:
+               upadate = FALSE;
+               break;
+           default:
+               Put_message("Aborting Operation.");
+               FreeQueue(elem);
+               return(DM_NORMAL);
+           }
+       }
+       else
+           update = TRUE;
+
+       if (update) {
+           char * args;
+           args = AskFSInfo(info, TRUE);
+           if ( (stat = sms_query("update_filesys", num_args, 
+                                  args, NullFunc, NULL)) != 0)
+               com_err(whoami, stat, " in filesystem not updated");
+           else
+               Put_message("filesystem sucessfully updated.");
+       }
+       temp_elem = temp_elem->q_forw;
+    }
+    FreeQueue(elem);
+    return (DM_NORMAL);
+}
+
+/*     Function Name: AddFS
+ *     Description: change the information in a filesys record.
+ *     Arguments: arc, argv - name of filsys in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+AddFS(argc, argv)
+char **argv;
+int argc;
+{
+    char *info[MAX_ARGS_SIZE], **args;
+    int stat, count;
+
+    if ( !ValidName(argv[1]) )
+       return(DM_NORMAL);
+
+    if ( (stat = sms_query("get_filesys_by_label", 1, argv + 1,
+                          NullFunc, NULL)) == 0) {
+       Put_message ("A Filesystem by that name already exists.");
+       return(DM_NORMAL);
+    } else if (status != SMS_NOMATCH) {
+       com_err(whoami, stat, " in AddFS");
+       return(DM_NORMAL);
+    } 
+
+    while (count = 0; count < 100; count++)
+       info[count] = NULL;
+    args = AskFSInfo(info, FALSE );
+    
+    if (stat = sms_query("add_filesys", CountArgs(args), args, 
+                        NullFunc, NULL) != 0)
+       com_err(whoami, stat, " in AddFS");
+
+    FreeInfo(info);
+    return (DM_NORMAL);
+}
+
+/* -------------- Top Level Menu ---------------- */
+
+/*     Function Name: GetFSAlias
+ *     Description: Gets the value for a Filesystem Alias.
+ *     Arguments: argc, argv - name of alias in argv[1].
+ *     Returns: DM_NORMAL.
+ *      NOTES: There should only be one filesystem per alias, thus
+ *             this will work correctly.
+ */
+
+/* ARGSUSED */
+int
+GetFSAlias(argc, argv)
+int argc;
+char **argv;
+{
+    register int stat = 0;
+    char **info, buf[BUFSIZ];
+    struct qelem *top, *elem;
+
+    top = elem = GetFSInfo(FS_ALIAS, argv[1]);
+
+    while (elem != NULL) {
+       info = (char **) elem->q_data;
+       sprintf(buf,"Alias: %s\tFilesystem: %s",info[NAME], info[ALIAS_TRANS]);
+       putmessage(buf);
+       elem = elem->q_forw;
+    }
+
+    FreeQueue(top);
+    return(DM_NORMAL);
+}
+
+/*     Function Name: CreateFSAlias
+ *     Description: Create an alias name for a filsystem
+ *     Arguments: argc, argv - name of alias in argv[1].
+ *     Returns: DM_NORMAL.
+ *      NOTES:  This requires (name, type, transl)  I get {name, translation}
+ *              from the user.  I provide type, which is well-known. 
+ */
+
+/* ARGSUSED */
+int
+CreateFSAlias(argc, argv)
+int argc;
+char **argv;
+{
+    register int stat = 0;
+    struct qelem *elem, *top;
+    char *args[3], buf[BUFSIZ], **info;
+    int num_args;
+
+    elem = NULL;
+
+    if (!ValidName(argv[1]))
+       return(DM_NORMAL);
+
+    args[0] = argv[1];
+    args[1] = FS_ALIAS_TYPE;
+
+/*
+ * Check to see if this alias already exists in the database, if so then
+ * print out values, free memory used and then exit.
+ */
+
+    if ( (stat = sms_query("get_alias", 2, args, StoreInfo, &elem)) == 0) {
+       top = elem;
+       while (elem != NULL) {
+           info = (char **) elem->q_data;          
+           sprintf(buf,"The alias: %s\tcurrently describes the filesystem %s",
+                   info[NAME], info[ALIAS_TRANS]);
+           Put_message(buf);
+           elem = elem->q_forw;
+       }
+       FreeQueue(top);
+       return(DM_NORMAL);
+    }
+    else if ( stat != SMS_NO_MATCH) {
+       com_err(whoami, stat, " in CreateFSAlias.");
+        return(DM_NORMAL);
+    }
+
+    args[ALIAS_TRANS] = NULL;  /* set to zero */
+    GetValueFromUser("Which filesystem will this alias point to?",
+                    args[ALIAS_TRANS]);
+
+    if ( (stat = sms_query("add_alias", 3, args, NullFunc, NULL)) != 0)
+       com_err(whoami, stat, " in CreateFSAlias.");
+
+    free(args[ALIAS_TRANS]);
+    return (DM_NORMAL);
+}
+
+/*     Function Name: DeleteFSAlias
+ *     Description: Delete an alias name for a filsystem
+ *     Arguments: argc, argv - name of alias in argv[1].
+ *     Returns: DM_NORMAL.
+ *      NOTES:  This requires (name, type, transl)  I get {name, translation}
+ *              from the user.  I provide type, which is well-known. 
+ */
+
+/* ARGSUSED */
+int
+DeleteFSAlias(argc, argv)
+int argc;
+char **argv;
+{
+    register int stat;
+    char *args[3], buf[BUFSIZ], **info;
+    int num_args, delete;
+    struct qelem *elem, *top;
+
+    if (!ValidName(argv[1]))
+       return(DM_NORMAL);
+
+    top = elem = GetFSInfo(FS_ALIAS, argv[1]);
+
+/* 
+ * 1) If there are no (zero) match in elements then we exit immediately.
+ * 2) If there is exactly 1 element then we ask for confirmation only if in
+ *    verbose mode, via the Confirm function.  
+ * 3) If there is more than 1 filesystem alias to be deleted then we ask
+ *    about each one, and delete on yes only, and about if the user hits
+ *    quit.
+ */
+    number = QueueCount(top);
+    while (elem != NULL) {
+       char **info = (char **) elem->q_data;
+
+       if (number != 1) {
+           sprintf(buf, "%s %s for the filesystem %s.",
+                   "Confirm that you want to delete\n the alias",
+                   info[NAME], info[ALIAS_TRANS]);
+           Put_message(buf);
+           
+           answer = YesNoQuitQuestion("\nDelete this filesystem alias?", 
+                                      FALSE); 
+           switch(answer) {
+           case TRUE:
+               delete = TRUE;
+               break;
+           case FALSE:
+               delete = FALSE;
+               break;
+           default:            /* Quit. */
+               Put_message("Aborting Delete Operation.");
+               FreeQueue(top);
+               return(DM_NORMAL);
+           }
+       }
+       else {
+           sprintf(buf, "Are you sure that you want to delete %s",
+                   "this filesystem alias?");
+           delete = Confirm(buf);
+       }
+/* 
+ * Deletetions are  performed if the user hits 'y' on a list of multiple 
+ * filesystem aliases, or if the user confirms on a unique alias.
+ */
+       if (delete) {
+           if ( (status = sms_query("delete_filesys", 1,
+                                    &name, NullFunc, NULL)) != 0)
+               com_err(whoami, stat, " filesystem alias not deleted.");
+           else
+               Put_message("Filesystem alias deleted.");
+       }
+       else 
+           Put_message("Filesystem alias not deleted.");
+       elem = elem->q_forw;
+    }
+
+    FreeQueue(Top);
+    return (DM_NORMAL);
+}
+
+/*     Function Name: AttachHelp
+ *     Description: Print help info on attachmaint.
+ *     Arguments: none
+ *     Returns: DM_NORMAL.
+ */
+
+int
+AttachHelp()
+{
+    static char *message[] = {
+       "These are the options:\n",
+       "get - get information about a filesystem.",
+       "add - add a new filesystem to the data base.",
+       "update - update the information in the database on a filesystem.",
+       "delete - delete a filesystem from the database.\n",
+       "check - check information about association of a name and a filesys.",
+       "alias - associate a name with a filsystem.",
+       "unalias - disassociate a name with a filesystem.",
+       "\twhere a name is: user, group, or project\n",
+       "verbose - toggle the request for delete confirmation\n",
+       NULL,
+    };
+
+    return(PrintHelp(message));
+}
+
+/* 
+ * 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:
+ */
diff --git a/clients/moira/cluster.c b/clients/moira/cluster.c
new file mode 100644 (file)
index 0000000..8d967ba
--- /dev/null
@@ -0,0 +1,716 @@
+#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: 
+ *     
+ *     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
+ */
+
+/* BTW: for anyone who cares MCD is short for Machine, Cluster, Data. */
+
+#include "mit-copyright.h"
+#include "allmaint.h"
+#include "globals.h"
+#include "infodefs.h"
+
+#include <stdio.h>
+#include <strings.h>
+#include <sms.h>
+#include <menu.h>
+
+#define MCD_MACHINE  0
+#define MCD_CLUSTER  1
+#define MCD_DATA     2
+#define MCD_MAP      3
+
+extern char *whoami;
+extern char * CanonicalizeHostname();
+
+/*     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.
+ */
+
+void
+PrintMachInfo(info)
+char ** info;
+{
+    char buf[BUFSIZ];
+
+    sprintf(buf, "Machine: %s\tType: %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);
+}
+
+/*     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.
+ */
+
+void
+PrintClusterInfo(info)
+char ** info;
+{
+    char buf[BUFSIZ];
+
+    sprintf(buf, "Cluster: %s", info[C_NAME]);
+    Put_Message(buf);
+    sprintf(buf,"Description: %-20s, Location: %-20s", info[C_DESCRIPT], 
+           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);
+}
+
+/*     Function Name: PrintClusterData
+ *     Description: Prints the Data on a cluster
+ *     Arguments: info a pointer to the data array.
+ *     Returns: none
+ */
+
+void
+PrintClusterData(info)
+char ** info;
+{
+    char buf[BUFSIZ];
+    sprintf(buf, "Cluster: %-30s, Label: %-20s, Data: %-20s",
+           info[CD_NAME], info[CD_LABEL], info[CD_DATA]);
+    Put_message(buf);
+}
+
+/*     Function Name: GetMCInfo.
+ *     Description: This function stores info about a machine.
+ *                   type - type of data we are trying to retrieve.
+ *                   name1 - the name of argv[0] for the call.
+ *                   name2 - the name of argv[1] for the call.
+ *     Returns: the top element of a queue containing the data or NULL.
+ */
+
+struct qelem *
+StoreMCInfo(type, name1, name2)
+int type;
+char * name1, *name2;
+{
+
+    int stat;
+    struct qelem * elem = NULL;
+    char * args[2];
+
+    switch (type) {
+    case MCD_MACHINE:
+       if ( (stat = sms_query("get_machine", 1, &name1,
+                              StoreInfo, &elem)) != 0) {
+           com_err(whoami, stat, " in get_machine.");
+           return(NULL);
+       }
+       break;
+    case MCD_CLUSTER:
+       if ( (stat = sms_query("get_cluster",  1, &name1,
+                              StoreInfo, &elem)) != 0) {
+           com_err(whoami, stat, " in get_cluster.");
+           return(NULL);
+       }
+       break;
+    case MCD_MAP:
+       args[0] = name1;
+       args[1] = name2;
+       if ( (stat = sms_query("get_machine_to_cluster_map", 2, args,
+                              StoreInfo, &elem)) != 0) {
+           com_err(whoami, stat, " in get_machine_to_cluster_map.");
+           return(NULL);
+       }
+       break;
+    case MCD_DATA:
+       args[0] = name1;
+       args[1] = name2;
+       if ( (stat = sms_query("get_cluster_data", 2, args,
+                              StoreInfo, &elem)) != 0) {
+           com_err(whoami, stat, " in get_cluster_data.");
+           return(NULL);
+       }
+    }
+    return(QueueTop(elem));
+}
+
+/*     Function Name: AskInfo.
+ *     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 - MCD_MACHINE
+ *                                              MCD_CLUSTER
+ *                                              MCD_DATA
+ *                 name - T/F : change the name of this type.
+ *     Returns: none.
+ */
+
+void
+AskInfo(mcs_info, type, name);
+char ** mcs_info;
+int type;
+Bool name;
+{
+    char * temp_buf;
+
+    switch (type) {
+    case MCD_MACHINE:
+       sprintf(temp_buf, "Changing the information for the Machine %s.",
+               name);
+       break;
+    case MCD_CLUSTER:
+       sprintf(temp_buf, "Changing the information for the Cluster %s.",
+               name);
+       break;
+    case MCD_DATA:
+       sprintf(temp_buf, "Changing the Data for the Cluster %s.",
+               name);
+       break;
+    }
+    Put_message(temp_buf);
+
+    if (name) {
+       info[NEWNAME] = Strsave(info->name);
+       switch (type) {
+       case MCD_MACHINE:
+           GetValueFromUser("The new name for this machine? ",
+                            info[M_NEWNAME]);
+           break;
+       case MCD_CLUSTER:
+           GetValueFromUser("The new name for this cluster? ",
+                            info[C_NEWNAME]);
+           break;
+       default:
+           Put_message("Unknown type in AskInfo, programmer botch");
+           return;
+       }
+    }
+
+    switch(type) {
+    case MCD_MACHINE:
+       GetValueFromUser("Machine's Type:",info[M_TYPE]);
+       FreeAndClear(&info[M_MODTIME], TRUE);
+       FreeAndClear(&info[M_MODBY], TRUE);
+       FreeAndClear(&info[M_MODWITH], TRUE);
+       break;
+    case MCD_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;
+    case MCD_DATA:
+       GetValueFromUser("Label defining this data?",info[CD_LABEL]);
+       GetValueFromUser("The data itself ? ",info[CD_DATA]);
+       break;
+    }
+
+/* 
+ * Slide the newname into the #2 slot, this screws up all future references 
+ * to this list.
+ */
+    if (name)                  
+       SlipInNewName(info, newname);
+
+    return(info);
+}
+
+/* -----------  Machine Menu ----------- */
+
+/*     Function Name: ShowMachineInfo
+ *     Description: This function shows the information about a machine.
+ *     Arguments: argc, argv - the name of the machine in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+ShowMachineInfo(argc, argv)
+int argc;
+char **argv;
+{
+    char **info;
+    struct qelem *elem, *top;
+
+    top = elem = GetMCInfo(  CanonicalizeHostname(argv[1]), MCD_MACHINE);
+
+    while (elem != NULL) {
+       info = (char **) elem->q_data;
+       PrintMachInfo(info);
+       elem = elem->q_forw;
+    }
+
+    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].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+AddMachine(argc, argv)
+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]);
+
+    if ( (stat = sms_query("get_machine", 1, &name, NullFunc, NULL)) == 0) {
+       Put_message("This machine already exists.");
+       return(DM_NORMAL);
+    }
+    else if (stat != SMS_NOMATCH) {
+       com_err(whoami, status, " in AddMachine.");
+       return(DM_NORMAL);
+    }
+
+    info[0] = name;
+    args = AskMCDInfo(info, MCD_MACHINE, FALSE);
+
+/*
+ * Actually create the new Machine.
+ */
+    
+    if ( (stat = sms_query("add_machine", CountArgs(args), 
+                          args, NullFunc, NULL)) != 0)
+       com_err(whoami, status, " in AddMachine.");
+
+    FreeInfo(info);
+    return(DM_NORMAL);
+}
+
+/*     Function Name: UpdateMachine
+ *     Description: This function adds a new machine to the database.
+ *     Arguments: argc, argv - the name of the machine in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+UpdateMachine(argc, argv)
+int argc;
+char **argv;
+{
+    char **args, **info;
+    int stat;
+    
+    elem = top = GetMCDInfo( MCD_MACHINE,  CanonicalizeHostname(argv[1]) );
+
+    while (elem != NULL) {
+       info = (char **) elem->q_data;
+       args = AskMCDInfo(info, MCD_MACHINE, TRUE);
+       if ( (stat = sms_query("update_machine", CountArgs(args), 
+                              args, Scream, NULL)) != 0)
+           com_err(whoami, status, " in UpdateMachine.");
+       elem = elem->q_forw;
+    }
+
+    FreeQueue(top);
+    return(DM_NORMAL);
+}
+
+/*     Function Name: DeleteMachine
+ *     Description: This function removes a machine from the data base.
+ *     Arguments: argc, argv - the machines name int argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+DeleteMachine(argc,argv)
+int argc;
+char **argv;
+{
+    int stat;
+    char * args[2], *name;
+
+    name =  CanonicalizeHostname(argv[1]);
+
+/* Should probabally check for wildcards, none allowed. */
+/* Perhaps we should remove the cluster if it has no machine now. */
+
+    args[0] = argv[1];
+    args[1] = "*";
+    stat = sms_query("get_machine_to_cluster_map", 2, args, Null, NULL);
+    if (stat != SMS_NO_MATCH) {
+       sprintf(temp_buf, "%s is assigned to cluster %s.",args[0], args[1]);
+       Put_message(temp_buf);
+       if ( YesNoQuestion("Would you like to remove it from this cluster?",
+                          FALSE)) {
+           if ( (stat = sms_query( "delete_machine_from_cluster",
+                                1, args, Null, NULL)) != 0)
+               com_err(whoami, status, " in DeleteMachine.");
+       }
+       else {
+           Put_message("Aborting...");
+           return(DM_NORMAL);
+       }
+    }
+    if(Confirm("Are you sure that you want to delete this machine?")) {
+       if ( (stat = sms_query("delete_machine", 1, &name, Null, NULL)) != 0)
+           com_err(whoami, status, " in DeleteMachine.");
+    }
+    else 
+       Put_message("Operation aborted.");
+
+    return(DM_NORMAL);
+}
+
+/*     Function Name: AddMachineToCluster
+ *     Description: This function adds a machine to a cluster
+ *     Arguments: argc, argv - The machine name is argv[1].
+ *                              The cluster name in argv[2].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int 
+AddMachineToCluster(argc, argv)
+int argc;
+char ** argv;
+{
+    int stat;
+
+    if ( (stat = sms_query("add_machine_to_cluster", 2, args + 1,
+                                 Scream, NULL) != 0))
+       com_err(whoami, status, " in AddMachineToCluster.");
+
+    return(DM_NORMAL);
+}
+
+/*     Function Name: RemoveMachineFromCluster
+ *     Description: Removes this machine form a specific cluster.
+ *     Arguments: argc, argv - Name of machine in argv[1].
+ *     Returns: none.
+ */
+
+/* ARGSUSED */
+int
+RemoveMachineFromCluster(argc, argv)
+int argc;
+char ** argv;
+{
+    int stat, ans;
+    struct qelem *elem, *top;
+    char ** info;
+    
+    elem = top = GetMCDInfo(MCD_CLUSTER,  CanonicalizeHostname(argv[1]), "*");
+
+    Put_message("This machine is the following clusters:");
+    while (elem != NULL) {
+       info = (char *) elem->q_data;
+       Put_message(info[MAP_CLUSTER]);
+       elem = elem->q_forw;
+    }
+    elem = top;
+
+    if ( Confirm("Remove this machine from ** ALL ** these clusters?") ) {
+       while (elem != NULL) {  /* delete all */
+           info = (char *) elem->q_data;        
+           if ( (stat =sms_query("delete_machine_from_cluster", 2, 
+                                 info, Scream, NULL)) != 0 )
+               com_err(whoami, stat, " in delete_machine_from_cluster");
+           elem = elem->q_forw;
+       }
+    }
+    else 
+       while (elem != NULL) {  /* query delete. */
+           info = (char *) elem->q_data;       
+           sprintf(buf, "Remove %13s from the cluster %30s? (y/n/q)", 
+                   info[MAP_MACHINE], info[MAP_CLUSTER]);
+           ans = YesNoQuitQuestion(buf, FALSE);
+           if (ans == TRUE) 
+               if ( (stat =sms_query("delete_machine_from_cluster", 2, 
+                                     info, Scream, NULL)) != 0 )
+                   com_err(whoami, stat, " in delete_machine_from_cluster");
+           else if (ans != FALSE) /* quit. or ^C */
+               break;
+           elem = elem->q_forw;
+       }
+    
+    FreeQueue(top);
+    return(DM_NORMAL);
+}
+
+/* ---------- Cluster Menu -------- */
+
+/*     Function Name: ShowClusterInfo
+ *     Description: Gets information about a cluser given its name.
+ *     Arguments: argc, argc - the name of the cluster in in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+ShowClusterInfo(argc, argv);
+int argc;
+char ** argv;
+{
+    char **info;
+    struct qelem *elem, *top;
+
+    top = elem = GetMCInfo(argv[1], MCD_MACHINE);
+    while (elem != NULL) {
+       info = (char **) elem->q_data;
+       PrintClusterInfo(info);
+       elem = elem->q_forw;
+    }
+    FreeQueue(top);
+    return(DM_NORMAL);
+}
+
+/*     Function Name: AddCluster
+ *     Description: Creates a new cluster.
+ *     Arguments: argc, argv - the name of the new cluster is argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+AddCluster(argc, argv)
+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);
+    }
+    else if (stat != SMS_NOMATCH) {
+       com_err(whoami, status, " in AddCluster.");
+       return(DM_NORMAL);
+    }
+
+    info[0] = name;
+    args = AskMCDInfo(info, MCD_CLUSTER, FALSE);
+
+/*
+ * Actually create the new Cluster.
+ */
+    
+    if ( (stat = sms_query("add_cluster", CountArgs(args), 
+                          args, Scream, NULL)) != 0)
+       com_err(whoami, status, " in AddCluster.");
+
+    FreeInfo(info);
+    return(DM_NORMAL);
+}
+
+/*     Function Name: UpdateCluster
+ *     Description: This Function Updates a cluster
+ *     Arguments: name of the cluster in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int 
+UpdateCluster(argc, argv)
+int argc;
+char ** argv;
+{
+    struct qelem *elem, *top;    
+    char **args, **info;
+    int stat;
+    
+    elem = top = GetMCDInfo( MCD_Cluster, argv[1], (char *) NULL );
+
+    while (elem != NULL) {
+       info = (char **) elem->q_data;
+       args = AskMCDInfo(info, MCD_CLUSTER, TRUE);
+       if ( (stat = sms_query("update_cluter", CountArgs(args), 
+                              args, Scream, NULL)) != 0)
+           com_err(whoami, status, " in UpdateCluster.");
+       elem = elem->q_forw;
+    }
+
+    FreeQueue(top);
+    return(DM_NORMAL);
+}
+
+/*     Function Name: DeleteCluster
+ *     Description: This function removes a cluster from the database.
+ *     Arguments: argc, argv - the name of the cluster is stored in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+DeleteCluster(argc, argv);
+int argc;
+char ** argv;
+{
+    char * args[3];
+
+/* Should probabally check for wildcards, none allowed. */
+
+    args[MAP_MACHINE] = "*";
+    args[MAP_CLUSTER] = argv[1];
+
+    stat = sms_query("get_machine_to_cluster_map", 2, args, NullFunc, NULL);
+    if (stat != SMS_NO_MATCH) {
+       sprintf(temp_buf, "Cluster %s still has machines in it.",args[0]);
+       Put_message(temp_buf);
+       if ( YesNoQuestion("Would you like a list? (y/n)") == TRUE ) {
+           args[0] = "foo";    /* not used. */
+           args[1] = "*";
+           args[2] = argv[1];
+           MachineToClusterMap(3, args);
+       }
+       return(DM_NORMAL);
+    }
+    if(Confirm("Are you sure that you want to delete this cluster? ")) {
+       if ( (stat = sms_query("delete_cluster", 
+                              1, &args[MAP_CLUSTER], Scream, NULL)) != 0)
+           com_err(whoami, status, " in DeleteCluster.");
+    }
+    else 
+       Put_message("Operation aborted.");
+
+    return(DM_NORMAL);
+}
+    
+/* ----------- Cluster Data Menu -------------- */
+
+/*     Function Name: ShowClusterData
+ *     Description: This function shows the services for one cluster.
+ *     Arguments: argc, argv - The name of the cluster is argv[1].
+ *                              The name of the data in argv[2].
+ *     Returns: DM_NORMAL.
+ */
+
+int
+ShowClusterData(argc, argv)
+int argc; 
+char ** argv; 
+{ 
+    struct qelem *elem, *top;
+    char **info;
+
+    top = elem = GetMCDInfo(MCD_DATA, argv[1], argv[2]);
+    while (elem != NULL) {
+       info = (char **) elem->q_data;
+       PrintClusterData(info);
+       elem = elem->data;
+    }
+    FreeQueue(top);
+    return(DM_NORMAL);
+}
+
+/*     Function Name: AddClusterData
+ *     Description: This function adds some data to the cluster.
+ *     Arguments: argv, argc:   argv[1] - the name of the cluster.
+ *                               argv[2] - the label of the data.
+ *                               argv[3] - the data.
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+AddClusterData(argc, argv)
+int argc; 
+char ** argv; 
+{ 
+    if( (stat = sms_query("add_cluster_data", 3, argv + 1,
+                         Scream, (char *) NULL)) != 0)
+       com_err(whoami, status, " in AddClusterData.");
+
+}
+
+/*     Function Name: DeleteClusterData
+ *     Description: This function deletes a service
+ *     Arguments: argv, argc:   argv[1] - the name of the cluster.
+ *                               argv[2] - the label of the data.
+ *                               argv[3] - the data.
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int DeleteClusterData(argc, argv)
+int argc; 
+char ** argv; 
+{
+    int stat;
+
+    if(Confirm("Do you really want to delete this data?")) {
+       if( (stat = sms_query("delete_cluster_data", 3, argv + 1,
+                             Scream, (char *) NULL)) != 0)
+           com_err(whoami, status, " in DeleteClusterData.");
+    } else 
+       Put_message("Operation aborted.\n");
+
+    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.
+ *                              argv[2] -> cluster name or wildcard.
+ *     Returns: none.
+ */
+
+/* ARGSUSED */
+int 
+MachineToClusterMap(argc,argv)
+int argc;
+char **argv;
+{
+  int stat;
+
+  argv[1] =  CanonicalizeHostname(argv[1]);
+  
+  if (stat = sms_query("get_machine_to_cluster_map", 
+                   argc-1, argv+1, Print, NULL) != 0)
+      com_err(whoami, qstat, NULL);
+
+  return(DM_NORMAL);
+}
+
+/* 
+ * 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:
+ */
+
+
+
diff --git a/clients/moira/delete.c b/clients/moira/delete.c
new file mode 100644 (file)
index 0000000..7d67cb8
--- /dev/null
@@ -0,0 +1,663 @@
+#ifndef lint
+  static char rcsid_module_c[] = "$Header$";
+#endif lint
+
+/*     This is the file delete.c for allmaint, the SMS client that allows
+ *      a user to maintaint most important parts of the SMS database.
+ *     It Contains: functions for deleting users and lists.
+ *     
+ *     Created:        5/18/88
+ *     By:             Chris D. Peterson
+ *
+ *      $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
+ */
+
+#include "mit-copyright.h"
+#include "allmaint.h"
+#include "globals.h"
+#include "infodefs.h"
+
+#include <stdio.h>
+#include <strings.h>
+#include <sms.h>
+#include <menu.h>
+
+int DeleteList(), DeleteUser();
+static int RealDeleteList() RealDeleteUser();
+
+/*     Function Name: CheckListForDeletion
+ *     Description: Check one of the lists in which we just removed a member.
+ *                   if the list is empty then it will delete it.
+ *     Arguments: name - name of the list to check.
+ *                 verbose - verbose mode?
+ *     Returns: none.
+ */
+
+void
+CheckListForDeletion(name, verbose)
+char * name;
+Bool verbose;
+{
+    qelem *elem = NULL;
+    int status;
+    char *args[2], buf[BUFSIZ];
+
+    if ( (status = sms_query("count_members_of_list", 1, &name, StoreInfo,
+                            (char *) &elem)) != 0) {
+       com_err(whoami, status, " in DeleteList (count_members_of_list).");
+       return();
+    }
+    if (verbose) {
+       sprintf(buf, "Delete the empty list %s? ",name);
+       ans = YesNoQuestion(buf, TRUE);
+       if (ans != TRUE) {
+           Put_message("Aborting Deletion!");
+           return();
+       }
+    }
+    args[0] = "foo";           /* not used. */
+    args[1] = name;
+    DeleteList(2, args);
+}
+
+/*     Function Name: CheckAcl
+ *     Description: Checks an acl to see of we should delete it.
+ *     Arguments: type - the type of this acl.
+ *                 name - the name of the acl.
+ *                 verbose - query user?
+ *     Returns: none.
+ */
+
+void
+CheckAcl(type, name, verbose)
+char * type, *name;
+Bool verbose;
+{
+    char *args[2], buf[BUFSIZ];
+
+    if ( strcmp(type,"LIST") != 0 ) 
+       return();               /* If the acl is not a list the ignore it. */
+    args[0] = type;
+    args[1] = name;
+    status = sms_query("get_acl_use", 2, args, NullFunc,  (char *) NULL);
+    if (status != SMS_NO_MATCH)
+       return();               /* if this query fails the acl will
+                                not be deleted even if it is empty. */
+    if (verbose) {
+       sprintf(buf, "Delete the unused Access Control List (ACL) %s? ", name);
+       ans = YesNoQuestion(buf, TRUE);
+       if (ans != TRUE) {
+       Put_message("Aborting Deletion!");
+           return();
+    }
+/*
+ * Delete the ACL.
+ *
+ * NOTE: Delete list expects only the name of the list to delete in argv[1].
+ *       since, 'args' already satisfies this, there is no need to create
+ *       a special argument list.
+ */
+    DeleteList(2, args);
+}
+       
+
+/*     Function Name: CheckIfAcl
+ *     Description: Checks to see if this is an acl of another data object.
+ *     Arguments: name - name of the object.
+ *     Returns: SUB_ERROR if this list is an acl, or if the query did noe
+ *               succeed.
+ */
+
+int
+CheckIfAcl(name, type, verbose)
+char * name, type;
+Bool verbose;
+{
+    char * args[2], buf[BUFSIZ];
+    qelem *elem, *local;
+    elem = NULL;
+
+    args[0] = type;
+    args[1] = name;
+    status = sms_query("get_acl_use", 2, args, StoreInfo, (char *) &elem);
+
+    if (status == SMS_NO_MATCH) 
+       return(SUB_NORMAL);
+
+    if (status != 0) {
+       com_err(whoami, status, " in CheckIfAcl (get_acl_use).");
+       return(SUB_ERROR);
+    }  
+    if (verbose) {
+       sprintf(buf, "%s %s %s %s", type, list_name,
+               "is the Access Control List (ACL) for the following data",
+               "objects:\n");
+       Put_message(buf);
+       local = elem;
+       while (local != NULL) {
+           info = (char **) local->q_data;
+           Print( QueueCount(elem), info, NULL);
+           local = local->q_forw;
+       }
+       Put_message("The ACL for each of these items must be changed before");
+       sprintf(buf,"the %s %s can be deleted.\n", type, name);
+       Put_message(buf);
+    }
+    FreeQueue(elem);
+    return(SUB_ERROR);
+    }
+}
+
+/*     Function Name: RemoveItemFromLists
+ *     Description: this function removes a list from all other lists of
+ *                   which it is a member.
+ *     Arguments: name - name of the list.
+ *                 elem - a pointer to a queue element. RETURNED
+ *                 verbose - verbose mode.
+ *     Returns: SUB_ERROR if there is an error.
+ */
+
+int
+RemoveItemFromLists(name, type, elem, verbose);
+char * name, type;
+qelem ** elem;
+int verbose;
+{
+    char *args[2];
+    
+    args[0] = type;
+    args[1] = name;
+    *elem = NULL;
+
+/* 
+ * Get all list of which this list is a member, and store them in a queue.
+ */
+
+    status = sms_query("get_list_of_member", 2, args, StoreInfo,
+                      (char *) elem);
+
+    if (status == SMS_NO_MATCH)
+       return(SUB_NORMAL);
+
+    if (status != 0) { 
+       com_err(whoami, status, " in DeleteList (get_lists_of_member).");
+       return(SUB_ERROR);
+    }
+
+/*
+ * If verbose mode, ask user of we should remove our list from 
+ * all these lists.
+ */
+
+    if (verbose) {
+       sprintf(temp_buf, "%s %s is a member of %d other list(s).\n", type,
+               name, QueueCount(member_of) );
+       Put_message(buf);
+       local = *elem;
+       while (local != NULL) {
+           info = (char **) local->q_data;
+           Print( CountArgs(info), info, NULL);
+           local = local->q_forw;
+       }
+       sprintf(buf,"Remove %s %s from these lists? ", type, name);
+       ans = YesNoQuestion(buf, TRUE);
+       if (ans < 0 || answer == FALSE) {
+           Put_message("Aborting...");
+           FreeQueue(*elem);
+           return(SUB_ERROR);
+       }
+    }
+
+/*
+ * Remove this list from all lists that it is a member of.
+ */
+
+    local = *elem;
+    args[1] = name;
+    args[2] = type;
+    while (local != NULL) {
+       info = (char **) local->q_data;
+       args[0] = info[0];
+       if ( (status = sms_query("delete_member_from_list",
+                                3, args, Scream, NULL)) != 0) {
+           com_err(whoami, status, " in delete_member\nAborting\n");
+           FreeQueue(*elem);
+           return(SUB_ERROR);
+       }
+       local = local->q_forw;
+    }
+    return(SUB_NORMAL);
+}
+
+/*     Function Name: RemoveMembersOfList
+ *     Description: Deletes the members of the list.
+ *     Arguments: name - name of the list.
+ *                 verbose - query user, about deletion?
+ *     Returns: SUB_ERROR - if we could not delete, or the user abouted.
+ */
+
+int
+RemoveMembersOfList(name, verbose);
+char * name;
+Bool verbose;
+{
+    char buf[BUFSIZ], **info;
+    qelem *local, *elem;
+
+/* 
+ * Get the members of this list.
+ */
+
+    *elem = NULL;
+    status = sms_query("get_members_of_list", 1, &name, StoreInfo,
+                      (char *) &elem);
+    if (status == SMS_NOMATCH) 
+       return(SUB_NORM);
+
+    if (status != 0) { 
+       com_err(whoami, status, " in DeleteList (get_members_of_list).");
+       return(SUB_ERROR);
+    }
+
+/*
+ * If verbose mode, then ask the user if we should delete.
+ */
+
+    if (verbose) {
+       sprintf(buf, "List %s has %d member(s):", name, QueueCount(members) );
+       Put_message(buf);
+       local = elem;
+       while (local != NULL) {
+           info = (char **) local->q_data;
+           Print( CountArgs(info), info, NULL);
+           local = local->q_forw;
+       }
+       sprintf(buf, "Remove these member(s) from list %s? ", name);
+       ans = YesNoQuestion(temp_buf, TRUE);
+       if (ans < 0 || answer == FALSE) {
+           Put_message("Aborting...");
+           FreeQueue(elem)
+           return(SUB_ERROR);
+       }
+    }
+
+/*
+ * Perform The Removal.
+ */
+
+    local = elem;
+    args[0] = name; 
+    while (local != NULL) {
+       info = (char **) local->q_data;
+       args[1] = info[0];
+       args[2] = info[1];
+       if ( (status = sms_query("delete_member_from_list",
+                                3, args, Scream, NULL)) != 0) {
+           com_err(whoami, status, " in delete_member\nAborting\n");
+           FreeQueue(elem);
+           return(SUB_ERROR);
+       }
+       local = local->q_forw;
+    }
+    return(SUB_NORMAL);
+}
+
+
+/*     Function Name: DeleteUserGroup
+ *     Description: Deletes the list given by name if it exists.
+ *                   intended to be used to delete user groups
+ *     Arguments: name - the name of the list to delete.
+ *                 verbose - flag that if TRUE queries the user to
+ *                           ask if list should be deleted.
+ *     Returns: SMS_ERROR if there is an error.
+ */
+
+int
+DeleteUserGroup(name, verbose)
+char * name;
+Bool verbose;
+{
+    int status, ans;
+    char buf[BUFSIZ];
+
+    status = sms_query("get_list_info", 1, &name, NullFunc, (char *) NULL);
+    if (status == 0) {
+       if (verbose) {
+           sprintf(buf, "There is also a list named %s, delete it?", name);
+           ans = YesNoQuestion(buf, TRUE);
+           if (ans == FALSE) {
+               Put_message("Leaving group alone.");
+               return(SBU_NORMAL);
+           }
+           if (ans < 0) {
+               Put_message("Aborting...\n");
+               return(SUB_ERROR);
+           }
+       }
+       /* ans == TRUE  || ~verbose */
+           args[0] = "foo";    /* not used. */
+           args[1] = name;
+           DeleteList(2, args);
+    }
+    else if (status != SMS_NO_MATCH) {
+       com_err(whoami, status, " Aborting Delete User.");      
+       return(SUB_ERROR);
+    }
+}
+
+/*     Function Name: DeleteHomeFilesys
+ *     Description: Delete the home filesystem for the named user.
+ *     Arguments: name - name of the user (and filsystem) to delete.
+ *                 verbose - if TRUE query user.
+ *     Returns: SUB_NORMAL if home filesystem deleted, or nonexistant.
+ */
+
+int
+DeleteHomeFilesys(name, verbose)
+char * name;
+Bool verbose;
+{
+    int status, ans;
+    char buf[BUFSIZ];
+    
+    status = sms_query("get_filesystem_by_label", 1, &name, NullFunc, 
+                      (char *) NULL);
+    if (status == SMS_NOMATCH)
+       return(SUB_NORMAL);
+    if (status == 0) {
+       if (verbose) {
+           sprintf(buf, "Delete the filesystem named %s (y/n)?", name);
+           ans = YesNoQuestion(buf, TRUE);
+           if (ans != TRUE) {
+               Put_message("Filesystem Not Deleted, aborting...\n\n");
+               return(SMS_ERROR);
+           }
+       }
+       if ( (status = sms_query("delete_filesystem", 1, &name, Scream,
+                                (char *) NULL) ) != 0) {
+           com_err(whoami, status, " in delete_filesystem).");
+           return(SUB_ERROR);
+       }
+       return(SUB_NORMAL);
+    }
+    com_err(whoami, status, " in get_filesystem_by_label).");
+    return(SUB_ERROR);
+}
+
+/*     Function Name: DeleteAllUserQuotas
+ *     Description: Deletes all quotas for a given user.
+ *     Arguments: name - name of the user.
+ *                 verbose - ask before performing deletion.
+ *     Returns: SUB_NORMAL if no quotas, or all quotas removed.
+ */
+
+int
+DeleteAllUserQuotas(name, verbose)
+char * name;
+int verbose;
+{
+    int status, ans;
+    char buf[BUFSIZ];
+    struct qelem *;
+    
+    status = sms_query("get_nfs_quotas_by_user", 1, &name, StoreInfo, 
+                      (char *) &elem);
+    if (status == SMS_NO_MATCH)
+       return(SUB_NORMAL);
+    if (status != 0) {
+       com_err(whoami, status, " in delete_filesystem.");
+       return(SUB_ERROR);
+    }
+    if (verbose) {
+       sprintf(buf, "User %s has quotas on the following filsystems:");
+       Put_message(buf);
+       local = elem;
+       while (local != NULL) {
+           info = (char **) local->q_data;
+           sprintf(buf, "Filesystem:\t%s\t\tQuota(in Kb):\t%s",
+                   info[0], info[4]);
+           Put_message(buf);
+           local = local->q_forw;
+       }
+       ans = YesNoQuestion("Remove ** ALL ** these quota entries (y/n)?",
+                           TRUE);
+       if (ans != TRUE) {
+           Put_message("Aborting..\n\n");
+           return(SUB_ERROR);
+       }
+    }
+    local = elem;
+    args[1] = name;
+    while (local != elem) {
+       info = (char **) local->q_data;
+       args[0] = info[0];
+       status = sms_query("delete_nfs_quota", 2, args, Scream, (char *) NULL);
+       if (status != 0 && status != SMS_NO_MATCH) {
+           sprintf(buf,
+                   "Could not remove quota on filesystem %s. ** ABORTING **",
+                   args[0]);
+           Put_message(buf);
+           com_err(whoami, status, (char *) NULL);
+           FreeQueue(elem);
+           return(SUB_ERROR);
+       }
+       local = local->normal;
+    }
+    FreeQueue(elem);
+    return(SUB_NORMAL);
+}
+
+/*     Function Name: DeleteList
+ *     Description: deletes a list
+ *     Arguments: argc, argv - standard SMS argc and argv.
+ *     Returns: DM Status Code.
+ */
+
+int
+DeleteList(argc, argv)
+int argc;
+char *argv[];
+{
+    char buf[BUFSIZ], *args[2], *list;
+    struct qelem *elem, *local, *member_of, *list_info;
+    int ans, status;
+
+    member_of = list_info = NULL;
+
+    list = argv[1];
+    if (!Confirm("Are you sure that you want to delete this list?"))
+       return(DM_NORMAL);
+/*
+ * Get Information about a list.
+ */
+    if ( (status = sms_query("get_list_info", 1, &list, StoreInfo, 
+                      (char *) &list_info)) != 0) {
+       com_err(whoami, status, " in DeleteList (delete_list).");
+       return(DM_NORMAL);
+    }
+
+/*
+ * Attempt delete. - will only work if:
+ * 1) This list has no members.
+ * 2) This list in a member of no other lists.
+ * 3) This list is not an acl of another object.
+ */
+
+    status = sms_query("delete_list", 1, &list, Scream, (char *) NULL);
+    if (status != SMS_IN_USE && status != 0) {
+       com_err(whoami, status, " in DeleteList (delete_list).");
+       return(DM_NORMAL);
+    }
+    if (status == 0) {
+       Put_message("List Sucessfully Deleted.");
+    }
+    else  {                    /* status = SMS_IN_USE. */
+
+/* 
+ * This list is in use.  Try to find out why, and for the cases where we
+ * have a good idea of what to do we will query and then do it.
+ */
+
+       if ( (CheckIfAcl(list, "list", TRUE) == SUB_ERROR) ||
+           (RemoveItemFromLists(list, "list",
+                                &member_of, TRUE) == SUB_ERROR) ||
+           (RemoveMembersOfList(list, TRUE) == SUB_ERROR) ||
+           (RealDeleteList(list) == SUB_ERROR) ) {
+           
+           FreeQueue(list_info);
+           FreeQueue(member_of);
+           return(DM_NORMAL);  
+       }
+    }
+
+    info = (char **) list_info->q_data;
+    CheckAcl(info[ACL_TYPE], info[ACL_NAME], TRUE);
+
+    local = member_of;
+    while (local != NULL) {
+       info = (char **) local->q_data;
+       CheckListForDeletion(info[0], TRUE);
+       local = local->q_forw;
+    }
+
+    FreeQueue(list_info);
+    FreeQueue(member_of);
+    return(DM_NORMAL);
+}
+
+/*     Function Name: RealDeleteList
+ *     Description: Just Deletes the list.
+ *     Arguments: name - name of list to delete
+ *     Returns: SUB_ERROR if the deletion failed.
+ */
+
+static int
+RealDeleteList(name);
+char * name;
+{
+    char buf[BUFSIZ];
+    int status;
+
+    if ( (status = sms_query("delete_list", 1, &name, Scream, 
+                            (char *) NULL)) == NULL) {
+       com_err(whoami, status, ": list not deleted");
+       return(SUB_ERROR);
+    }
+    (void) sprintf(buf, "List %s deleted./n", name);
+    Put_message(buf);
+    return(SUB_NORM);
+}
+
+/*     Function Name: DeleteUser
+ *     Description: Deletes a user from the database.
+ *     Arguments: argc, argv - name of the user in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+int
+DeleteUser(argc, argv)
+int argc;
+char ** argv;
+{
+    int status;
+    char buf[BUFSIZ];
+    char * name = argv[1];     /* name of the user we are deleting. */
+    qelem *local, *member_of = NULL;
+
+    if (!Confirm("Are you sure that you want to delete this user?"))
+       return(DM_NORMAL);
+
+    status = sms_query("delete_user", 1, &name, NullFunc, (char *) NULL);
+    if (status != SMS_IN_USE && status != 0) {
+       com_err(whoami, status, ": list not deleted");  
+       return(DM_NORMAL);
+    }
+    if (status == 0) {
+       sprintf(buf,"User %s deleted.", name);
+       Put_message(buf);
+    }
+    else if (status == SMS_IN_USE) {
+
+/*
+ * Check:
+ * 1) Is the user an ACL of any object in the database?
+ * 2) Query - Delete home filesytem.
+ * 3) Query - Delete users quota on all machines.      
+ * 4) Query - Remove user from all list of which he is a member.
+ *
+ * If all these have been accomplished, then attempt to delete the user again.
+ */
+       if ( (CheckIfAcl(name, "user", TRUE) == SUB_ERROR) ||
+            (DeleteHomeFilsys(name, TRUE) == SUB_ERROR) ||
+            (DeleteQuotas(name, TRUE) == SUB_ERROR) ||
+            (RemoveItemFromLists(name, "user",
+                                 &member_of, TRUE) == SUB_ERROR) ||
+            (RealDeleteUser(name) == SUB_ERROR) ) {
+           FreeQueue(member_of);
+           return(DM_NORMAL);
+       }
+    }
+
+/*
+ * Query - Delete user group.
+ * Query - Delete all empty lists created by removing this user from them.
+ */
+
+    if (DeleteUserGroup(name) == SUB_ERROR) {
+       FreeQueue(member_of);
+       return(DM_NORMAL);
+    }
+
+    local = member_of;
+    while (local != NULL) {
+       info = (char **) local->q_data;
+       CheckListForDeletion(info[0], TRUE);
+       local->local->q_forw;
+    }
+
+    FreeQueue(member_of);      /* Free memory and return. */
+    return(DM_NORMAL);
+}
+
+/*     Function Name: RealDeleteUser
+ *     Description: Just Deletes the user.
+ *     Arguments: name - name of User to delete
+ *     Returns: SUB_ERROR if the deletion failed.
+ */
+
+static int
+RealDeleteUser(name);
+char * name;
+{
+    char buf[BUFSIZ];
+    int status;
+
+    if ( (status = sms_query("delete_user", 1, &name, Scream, 
+                            (char *) NULL)) == NULL) {
+       com_err(whoami, status, ": user not deleted");
+       return(SUB_ERROR);
+    }
+    (void) sprintf(buf, "User %s deleted./n", name);
+    Put_message(buf);
+    return(SUB_NORM);
+}
+
+    
+/*
+ * 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:
+ */
diff --git a/clients/moira/globals.c b/clients/moira/globals.c
new file mode 100644 (file)
index 0000000..a8e6818
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef lint
+  static char rcsid_module_c[] = "$Header$";
+#endif lint
+
+/*     This is the file globals.h for allmaint, the SMS client that allows
+ *      a user to maintaint most important parts of the SMS database.
+ *     It Contains: globals variable definitions
+ *     
+ *     Created:        4/12/88
+ *     By:             4/12/88
+ *
+ *      $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
+ */
+
+#include "mit-copyright.h"
+#include "allmaint.h"
+
+char *user                     /* The name of the user executing allmaint. */
+char *program_name;            /* The name of this instance of the program. */
+
diff --git a/clients/moira/globals.h b/clients/moira/globals.h
new file mode 100644 (file)
index 0000000..9d582a2
--- /dev/null
@@ -0,0 +1,27 @@
+/*     This is the file globals.h for allmaint, the SMS client that allows
+ *      a user to maintaint most important parts of the SMS database.
+ *     It Contains: globals variable definitions
+ *     
+ *     Created:        4/12/88
+ *     By:             4/12/88
+ *
+ *      $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
+ */
+
+#include "mit-copyright.h"
+#include "allmaint.h"
+
+#ifndef _allmaint_globals_
+#define _allmaint_globals_
+
+extern char *user              /* The name of the user executing allmaint. */
+extern char *program_name;     /* The name of this instance of the program. */
+
+#endif _allmaint_globals_      /* Do Not Add Anything After This Line */
diff --git a/clients/moira/lists.c b/clients/moira/lists.c
new file mode 100644 (file)
index 0000000..70bdc21
--- /dev/null
@@ -0,0 +1,760 @@
+#ifndef lint
+  static char rcsid_module_c[] = "$Header$";
+#endif lint
+
+/*     This is the file lists.c for allmaint, the SMS client that allows
+ *      a user to maintaint most important parts of the SMS database.
+ *     It Contains: 
+ *     
+ *     Borrowed from listmaint code:   4/12/88
+ *     By:                             Chris D. Peterson
+ *
+ *      $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
+ */
+
+#include <stdio.h>
+#include <strings.h>
+#include <sms.h>
+#include <menu.h>
+
+#include "mit-copyright.h"
+#include "allmaint.h"
+#include "globals.h"
+#include "infodefs.h"
+
+#define LIST    0
+#define MEMBERS 1
+#define GLOM    2
+#define ACL_USE 3
+
+/*     Function Name: PrintListInfo
+ *     Description: This function Prints out the List info in a coherent form.
+ *     Arguments: info - the List info.
+ *     Returns: none.
+ */
+
+void
+PrintListInfo(info)
+char ** info;
+{
+    char buf[BUFSIZ];
+
+    (void) sprintf(buf, "List: %s",info[L_NAME]);
+    (void) Put_message(buf);
+    (void) sprintf(buf, "\nDescription: %s", info[L_DESC]);
+    (void) Put_message(buf);
+    if ( atoi(info[L_MAILLIST]))
+       Put_message("This list is a mailing list.");
+    else
+       Put_message("This list is NOT a mailing list.");
+    if ( atoi(info[L_GROUP]) ) {
+       (void) sprintf(buf,"This list is Group and its ID number is %s",
+                      info[L_GID]);
+       Put_message(buf);
+    }
+    else
+       Put_message("This is NOT a Group.");
+
+    if (strcmp(info[L_ACL_TYPE],"NONE") == 0)
+       Put_message("This list has no Administrator, how strange?!");
+    else {
+       sprintf(buf, "The List Administrator of this list is the %s: %s",
+               info[L_ACL_TYPE], info[ACL_NAME]);
+       Put_message(buf);
+    }
+
+    (void) sprintf(buf, "This list is: %s, %s, and %s",
+                  info[L_ACTIVE] ? "active" : "inactive",
+                  info[L_PUBLIC] ? "public" : "private",
+                  info[L_HIDDEN] ? "hidden" : "visible");
+    (void) Put_message(buf);
+    (void) sprintf(buf, "Last modification at %s, by %s using the program %s",
+                  info[L_MODTIME], info[L_MODBY], info[L_MODWITH]);
+    (void) Put_message(buf);
+}
+
+/*     Function Name: GetListInfo
+ *     Description: Stores all info about a group of lists in a queue.
+ *     Arguments: type - type of info to store.
+ *                 name - name of the info.
+ *     Returns: the first element in the queue.
+ */
+
+/* ARGSUSED */
+struct qelem *
+GetListInfo(type, name1, name2)
+int type;
+char * name;
+{
+    char *args[2];
+    struct quelem * elem = NULL;
+
+    switch(type) {
+    case LIST:
+       args[0] = name1;
+       if ( (status = sms_query("get_list_info", 1, args,
+                              StoreInfo, (char *) &elem)) != 0) {
+           com_err(whoami, status, " in get_nfs_quotas_by_user");
+           return (NULL);
+       }
+       break;
+    case MEMBERS:
+       args[0] = name1;
+       if ( (status = sms_query("get_members_of_list", 1, args,
+                              StoreInfo, (char *) &elem)) != 0) {
+           com_err(whoami, status, " in get_nfs_quotas_by_user");
+           return (NULL);
+       }
+       break;
+    case GLOM:
+       args[0] = name1;        
+       args[1] = name2;        
+       if ( (status =  sms_query("get_list_of_member", 2, args,
+                              StoreInfo, (char *) &elem)) != 0) {
+           com_err(whoami, status, " in get_nfs_quotas_by_user");
+           return (NULL);
+       }
+       break;
+    case ACL_USE:
+       args[0] = name1;        
+       args[1] = name2;        
+       if ( (status =  sms_query("get_acl_use", 2, args,
+                              StoreInfo, (char *) &elem)) != 0) {
+           com_err(whoami, status, " in get_nfs_quotas_by_user");
+           return (NULL);
+       }
+       break;
+    }
+    return( QueueTop(elem) );
+}      
+
+/*     Function Name: AskListInfo.
+ *     Description: This function askes the user for information about a 
+ *                   machine and saves it into a structure.
+ *     Arguments: info - a pointer the the structure to put the
+ *                             info into.
+ *                 name - add a newname field? (T/F)
+ *     Returns: SUB_ERROR or SUB_NORMAL.
+ */
+
+char **
+AskListInfo(info, name);
+char ** info;
+Bool name;
+{
+    char * temp_buf, *newname;
+    char *ret_args[100];
+    int counter;
+
+    sprintf(temp_buf,"\nChanging Attributes of list %s.\n",info[L_NAME]);
+    Put_message(temp_buf);
+
+    if (name) {
+       newname = Strsave(info[L_NAME]);
+       GetValueFromUser("The new name for this list.", &newname);
+    }
+    GetValueFromUser("Is this list active (1/0): ", &info[L_ACTIVE]);
+    GetValueFromUser("Is this list public (1/0): ", &info[L_PUBLIC]);
+    GetValueFromUser("Is this list hidden (1/0): ", &info[L_HIDDEN]);
+    GetValueFromUser("Is this a maillist  (1/0): ", &info[L_MAILLIST]);
+    GetValueFromUser("is this a group     (1/0): ", &info[L_GROUP]);
+    if (atoi(info[L_GROUP])) 
+       GetValueFromUser("What is the Gid for this group '#' get unique gid:".
+                        &info[L_GID]);
+    GetValueFromUser("What Type of Administrator (none, user, list): ",
+                    &info[L_ACL_TYPE]);
+    if ( strcmp(info[L_ACL_TYPE],"USER") == 0) 
+       GetValueFromUser("Who will be the administrator of this list: ",
+                        &info[L_ACL_NAME]);
+    if ( strcmp(info[L_ACL_TYPE],"USER") == 0) 
+       GetValueFromUser("Which group will be the administrator of this list: ",
+                        &info[L_ACL_NAME]);
+    GetValueFromUser("Description: ", &info[L_DESC]);
+
+    FreeAndClear(&info[L_MODTIME], TRUE);
+    FreeAndClear(&info[L_MODBY], TRUE);
+    FreeAndClear(&info[L_MODWITH], TRUE);
+/* 
+ * Slide the newname into the #2 slot, this screws up all future references 
+ * to this list.
+ */
+    if (name)                  /* slide the newname into the #2 slot. */
+       SlipInNewName(info, newname);
+
+    return(info);
+}
+
+/* -------------- List functions. -------------- */
+
+/*     Function Name: ShowListInfo.
+ *     Description: shows info on a list.
+ *     Arguments: argc, argv - standard SMS argc and argv.
+ *     Returns: DM status code.
+ */
+
+int
+ShowListInfo(argc, argv)
+int argc;
+char **argv;
+{
+    struct qelem *top, *list;
+
+    top = list = StoreListInfo(LIST, argv[1], (char *) NULL);
+    while (list != NULL) {
+       PrintListInfo( (char **) list->q_data);
+       list = list->q_forw;
+    }
+    
+    FreeQueue(top);
+    return(DM_NORMAL);
+}
+
+/*     Function Name: UpdateList
+ *     Description: 
+ *     Arguments: argc, argv - name of list in argv[1].
+ *     Returns: DM Status code.
+ */
+
+int
+UpdateList(argc, argv)
+int argc;
+char **argv;
+{
+    char **info, **up_args;
+    struct qelem *top, *list;
+    int status;
+
+    list = top = GetListInfo(LIST, argv[1], (char *) NULL);
+    
+    while (list != NULL) {
+       info = (char **) list->q_data;
+       up_args = AskListInfo(info, TRUE);
+       if ( (status = sms_query("update_list", CountArgs(up_args), up_args,
+                                Scream, (char *) NULL)) != 0) {
+           com_err(whoami, status, " in UpdateList."); 
+           Put_message("List Not Updated.");
+           list = list->q_forw;
+       }
+    }
+
+    FreeQueue(top);
+    return(DM_NORMAL);
+}
+
+/*     Function Name: AddList
+ *     Description: 
+ *     Arguments: argc, argv - name of list in argv[1].
+ *     Returns: DM Status code.
+ */
+
+int
+AddList(argc, argv)
+int argc;
+char **argv;
+{
+    static char *info[MAX_ARGS_SIZE], **add_args;
+    struct qelem *top, *list;
+    int status;
+
+    if (!ValidName(argv[1])) /* Check if list name is valid. */
+       return(DM_QUIT);
+    
+    status = sms_query("get_list_info", 1, argv + 1, NullFunc, 
+                      (caddr_t) NULL);
+    if (status != SMS_NO_MATCH) {
+       if (status == 0)
+           Put_message("This list already exists.");
+       else
+           com_err(whoami, status, " in AddList.");    
+       return(DM_QUIT);
+    }
+
+    add_args = AskListInfo(info, FALSE);
+
+    if ( (status = sms_query("add_list", CountArgs(add_args), add_args,
+                            Scream, (char *) NULL)) != 0) {
+       com_err(whoami, status, " in AddList.");        
+       Put_message("List Not Created.");
+       list = list->q_forw;
+    }
+
+    FreeInfo(info);
+    return(DM_NORMAL);
+}
+
+/*     Function Name: Instructions
+ *     Description: This func prints out instruction on manipulating lists.
+ *     Arguments: none
+ *     Returns: DM Status Code.
+ */
+
+int
+Instructions()
+{
+    static char * message[] = {
+       "Listmaint handles the creation, deletion, and updating of lists.\n",
+       "A list can be a mailing list, a group list, or both.\n",
+       "The concept behind lists is that a list has an owner",
+       "- administrator -  and members.\n";
+       "The administrator of a list may be another list.\n",
+       "The members of a list can be users (login names), other lists,",
+       "or address strings.\n",
+       "You can use certain keys to do the following:",
+       "    Refresh the screen - Type ctrl-L.\n",
+       "    Escape from a function - Type ctrl-C.\n",
+       "    Suspend the program (temporarily) - Type ctrl-Z.\n",
+       NULL,
+    }
+
+    return(PrintHelp(message));
+}
+
+/*-*-* LISTMAINT UPDATE MENU *-*-*/
+
+/*     Function Name: ListmaintMemberMenuEntry
+ *     Description: entry routine into the listmaint member menu.
+ *     Arguments: m - the member menu.
+ *                 argc, argv - name of the list in argv[1].
+ *     Returns: none.
+ */
+
+/* ARGSUSED */
+int
+ListmaintMemberMenuEntry(m, argc, argv)
+Menu *m;
+int argc;
+char **argv;
+{
+    char buf[BUFSIZ], temp_buf[BUFSIZ];
+    char *list_name = argv[1];
+
+    if (*argv[0] == 'a') {     /* add_list */
+       /* actually, AddList no longer returns DM_QUIT.
+        * Maybe later, when com_err no longer blows out there.
+        */
+       if (AddList(argc, argv) == DM_QUIT)
+           return(DM_QUIT);
+       (void) sprintf(temp_buf, "List '%s' created. Do you want to %s",
+                      list_name, "change its membership?");
+       if (YesNoQuestion(temp_buf, TRUE) != TRUE )
+           return(DM_QUIT);
+    }
+    else if (!ValidName(list_name)) {
+       (void) sprintf(temp_buf, "Bad list: '%s'", list_name);
+       Put_message(temp_buf);
+    return(DM_QUIT);
+    }
+
+    (void) sprintf(temp_buf, 
+                  "Change/Display membership of '%s'", list_name);
+    m->m_title = Strsave(temp_buf);
+    strcpy(current_list, list_name);
+    return(DM_NORMAL);
+}
+
+/*     Function Name: ListmaintMemberMenuExit
+ *     Description: This is the function called when the member menu is
+ *                   exited, it frees the memory that is storing the name.
+ *     Arguments: m - the menu
+ *     Returns: DM_NORMAL 
+ */
+
+int
+ListmaintMemberMenuExit(m)
+Menu *m;
+{
+    free(m->m_title);
+    strcpy(current_list, "");
+    return(DM_NORMAL);
+}
+
+/*     Function Name: ListMembersByType
+ *     Description: This function lists the users of a list by type.
+ *     Arguments: type - the type of the list "USER", "LIST", or "STRING".
+ *     Returns: none.
+ *      NOTE: if type is NULL, all lists members are listed.
+ */
+
+void
+ListMembersByType(type);
+char * type;
+{
+    char temp_buf[BUFSIZ];
+
+    found_some = FALSE;
+    if (status = sms_query("get_members_of_list", 1, &current_list, 
+                          PrintByType, type))
+       com_err(whoami, status, " in ListMembersByType\n");
+    if (!found_some) {
+       if (type == NULL)
+           Put_message("List is empty (no members).");
+       else {
+           sprintf(temp_buf,"No %s Members",type);
+           Put_message(temp_buf);
+       }
+    }
+}
+
+/*     Function Name: ListAllMembers
+ *     Description: lists all members of the current list.
+ *     Arguments: 
+ *     Returns: DM_NORMAL
+ */
+
+int
+ListAllMembers()
+{
+    ListMembersByType(NULL);
+    return (DM_NORMAL);
+}
+
+/*     Function Name: ListUserMembers
+ *     Description: This function lists all members of a list of type "USER".
+ *     Arguments: none
+ *     Returns: DM_NORMAL.
+ */
+
+ListUserMembers()
+{
+    ListMembersByType("USER");
+    return(DM_NORMAL);
+}
+
+/*     Function Name: ListListMembers
+ *     Description: This function lists all members of a list of type "LIST".
+ *     Arguments: none
+ *     Returns: DM_NORMAL.
+ */
+
+ListListMembers()
+{
+    ListMembersByType("LIST");
+    return(DM_NORMAL);
+}
+
+/*     Function Name: ListStringMembers
+ *     Description:This function lists all members of a list of type "STRING".
+ *     Arguments: none
+ *     Returns: DM_NORMAL.
+ */
+
+ListStringMembers()
+{
+    ListMembersByType("STRING");
+    return(DM_NORMAL);
+}
+
+/*     Function Name: GetMemberInfo
+ *     Description: This function gets the information needed to
+ *                   add or delete a user from a list.
+ *     Arguments: argc, argv - standard.
+ *                 action - name of the action to be performed either
+ *                          "add" or "delete".
+ *                 ret_argc, ret_argv - the returned value of argc and argv.
+ *     Returns: SUB_ERROR or SUB_NORMAL.
+ */
+
+int
+GetMemberInfo(action, ret_argv)
+char *action, **ret_argv;
+{
+    char temp_buf[BUFSIZ], ret_buf[BUFSIZ];
+
+    ret_argv[LM_LIST] = Strsave(current_list);
+    ret_argv[LM_MEMBER] = "nobody";
+
+    PromptWithDefault("Type of member (USER, LIST, or STRING)",
+                       ret_buf, BUFSIZ, "USER");
+    ret_argv[LM_TYPE]= Strsave(ret_buf);
+
+    status = sms_access("add_member_to_list", 3, ret_argv);
+    if (status == SMS_TYPE) {
+       Put_message("\"type\" must be one of 'STRING', 'LIST', or 'USER'.");
+       return(SUB_ERROR);
+    } else if (status) {
+       com_err(whoami, status, NULL);
+    }
+
+    sprintf(temp_buf,"Name of member to %s", action);
+    PromptWithDefault(temp_buf, ret_buf, BUFSIZ, user);
+    ret_argv[LM_MEMBER] = Strsave(ret_buf);
+    ret-args[LM_END] = NULL;           /* null terminat this list. */
+    return(SUB_NORMAL);
+}
+
+/*     Function Name: AddMember
+ *     Description: This function adds a member to a list.
+ *     Arguments: none.
+ *     Returns: DM_NORMAL.
+ */
+
+int
+AddMember()
+{
+    char *args[10];
+
+    if( GetMemberInfo("add", args) == SUB_ERROR )
+       return(DM_NORMAL);
+
+    if (status = sms_query("add_member_to_list", CountArgs(args), args,
+                          Scream, NULL) != 0)
+       com_err(whoami, status, " in AddMember\n");
+
+    FreeInfo(args);
+    return (DM_NORMAL);
+}
+
+/*     Function Name: DeleteMember
+ *     Description: This function deletes a member from a list.
+ *     Arguments: none.
+ *     Returns: DM_NORMAL
+ */
+
+int
+DeleteMember()
+{
+    char *args[10];
+
+    if( GetMemberInfo("delete", args) == SUB_ERROR )
+       return(DM_NORMAL);
+
+    if (Confirm("Are you sure you want to delete this member?") ) {
+       if (status = sms_query("delete_member_from_list", CountArgs(args),
+                              args, Scream, NULL))
+           com_err(whoami, status, " in DeleteMember\n");
+       else
+           Put_message("Deletion Completed.");
+    }
+    else 
+       Put_message("Deletion has been Aborted.");
+
+    FreeInfo(args);
+    return(DM_NORMAL);
+}
+
+
+/*     Function Name: InterRemoveItemFromLists
+ *     Description: This function allows interactive removal of an item
+ *                   (user, string, list) for all list  that it is on.
+ *     Arguments: none.
+ *     Returns: DM_NORMAL.
+ */
+
+int
+InterRemoveItemFromLists()
+{
+    char type[BUFSIZ], name[BUFSIZ], args[10];
+    qelem *top, *elem;
+
+    if ( !(PromptWithDefault("Type of member (user, list, string)? ", type, 
+                           BUFSIZ, "user")) )
+       return(DM_NORMAL);
+    
+    if ( !(PromptWithDefault("Name of member? ", name, BUFSIZ, user)) ) {
+       return(DM_NORMAL);
+    }
+
+    top = elem = GetListInfo(GLOM, type, name);
+
+    while(elem != NULL) {
+       info = (char **) elem->q_data;
+       sprintf(line, "Delete %s from the list \"%s\" [Y/N/Q]? ", name,
+               info[0]);
+       PromptWithDefault(line, buf, BUFSIZ, "N" );
+       if (buf[0] == 'y' || buf[0] == 'Y') {
+           Put_message("deleting...");
+           args[DM_LIST] = info[0];
+           args[DM_TYPE] = type;
+           args[DM_MEMBER] = name;
+           if ( (status = sms_query("delete_member_from_list", 3, args,
+                              Scream, (char *) NULL)) != 0)
+               /* should check to delete list. */
+               com_err(whoami, status, " in delete_member");
+       } 
+       else if (buf[0] == 'q' || buf[0] == 'Q') {
+           Put_message("Quitting.");
+           break;
+       }
+       elem = elem->q_forw;
+    }
+    FreeQueue(top);
+    return(DM_NORMAL);
+}
+
+/*-*-* LIST MENU *-*-*/
+
+/*     Function Name: ListByMember
+ *     Description: This gets all lists that a given member is a member of.
+ *     Arguments: argc, argv - agrv[1] contains the type.
+ *                              argv[2] contains the name of the member.
+ *     Returns: DM_NORMAL.
+ */
+
+int
+ListByMember(argc, argv)
+int argc;
+char **argv;
+{
+    char buf[BUFSIZ], *type, *name, **info;
+
+    if ( !(PromptWithDefault("Type of member (user, list, string)? ", buf, 
+                           BUFSIZ, "user")) )
+       return(DM_NORMAL);
+
+    sprintf(buf, "R%s", buf);  /* What we really want is a recursive search */
+    type = Strsave(buf);
+    
+    if ( !(PromptWithDefault("Name of member? ", buf, BUFSIZ, user)) ) {
+       free(type);
+       return(DM_NORMAL);
+    }
+    name = Strsave(buf);
+
+    maillist = YesNoQuestion("Show only Lists that are Maillists (y/n) ?",
+                            TRUE);
+    group = YesNoQuestion("Show only Lists that are Groups (y/n) ?", TRUE);
+
+    elem = top = GetListInfo(GLOM, type, name);
+
+    while (elem != NULL) {
+       info = (char**) elem->q_data;
+       if (maillist != TRUE || !strcmp(info[GLOM_MAILLIST], "1")) 
+           if (group != TRUE || !strcmp(info[GLOM_GROUP], "1")) 
+               Put_message(info[GLOM_NAME]);
+       elem = elem->q_forw;
+    }
+    FreeQueue(top);
+    return (DM_NORMAL);
+}
+
+/*     Function Name: ListByAdministrator
+ *     Description: This function prints all lists which a given user or
+ *                   group administers.
+ *     Arguments: argc, argv - type of the acl in argc[1].
+ *                              name of the acl in argc[2].
+ *     Returns: DM_NORMAL.
+ */
+
+int
+ListByAdministrator(argc, argv)
+int argc;
+char **argv;
+{
+    char buf[BUFSIZ], *type, *name, **info;
+
+    if ( !(PromptWithDefault("Type of member (user, list, string)? ", buf, 
+                           BUFSIZ, "user")) )
+       return(DM_NORMAL);
+
+    if ( YesNoQuestion("Do you want a recursive search?",TRUE) == 1 )
+       sprintf(buf,"R%s",buf); /* "USER" to "RUSER" etc. */
+    type = Strsave(buf);
+    
+    if ( !(PromptWithDefault("Name of member? ", buf, BUFSIZ, user)) ) {
+       free(type);
+       return(DM_NORMAL);
+    }
+    name = Strsave(buf);
+
+    top = elem = GetListInfo(ACL_USE, type, name);
+    while (elem != NULL) {
+       info = (char **) elem->q_data;
+       sprintf(buf, "Type: %s,\tName: %s", info[0], info[1]);
+       Put_message(buf);
+       elem = elem->q_forw;
+    }
+    FreeQueue(top);
+    return (DM_NORMAL);
+}
+
+/*     Function Name: ListAllGroups
+ *     Description: This function lists all visable groups.
+ *     Arguments: none.
+ *     Returns: DM_NORMAL.
+ */
+
+ListAllGroups()
+{
+    static char * args[] = {
+       "TRUE",                 /* active */
+       "DONTCARE",             /* public */
+       "FALSE",                /* hidden */
+       "DONTCARE",             /* maillist */
+       "TRUE",                 /* group. */
+    }
+
+    if (YesNoQuestion("This query will take a while, Do you wish to continue?",
+                      TRUE) )
+       if (status = sms_query("qualified_get_lists", 5, args,
+                              Print, (char *) NULL) != 0)
+           com_err(whoami, status, " in ListAllGroups\n");
+    return (DM_NORMAL);
+}
+
+/*     Function Name: ListAllMailLists
+ *     Description: This function lists all visable maillists.
+ *     Arguments: none
+ *     Returns: DM_NORMAL.
+ */
+
+ListAllMailLists()
+{
+    static char * args[] = {
+       "TRUE",                 /* active */
+       "DONTCARE",             /* public */
+       "FALSE",                /* hidden */
+       "TRUE",                 /* maillist */
+       "DONTCARE",             /* group. */
+    }
+
+    if (YesNoQuestion("This query will take a while. Do you wish to continue?",
+                      TRUE) )
+       if (status = sms_query("qualified_get_lists", 5, args,
+                              Print, (char *) NULL) != 0)
+           com_err(whoami, status, " in ListAllGroups\n");
+
+    return (DM_NORMAL);        
+}
+
+/*     Function Name: ListAllPublicMailLists
+ *     Description: This function lists all public mailing lists.
+ *     Arguments: none
+ *     Returns: DM_NORMAL.
+ */
+
+ListAllPublicMailLists()
+{
+    static char * args[] = {
+       "TRUE",                 /* active */
+       "TRUE",                 /* public */
+       "FALSE",                /* hidden */
+       "TRUE",                 /* maillist */
+       "DONTCARE",             /* group. */
+    }
+
+    if (YesNoQuestion("This query will take a while. Do you wish to continue?",
+                      TRUE) )
+       if (status = sms_query("qualified_get_lists", 5, args,
+                              Print, (char *) NULL) != 0)
+           com_err(whoami, status, " in ListAllGroups\n");
+
+    return (DM_NORMAL);        
+}
+
+/*
+ * 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:
+ */
diff --git a/clients/moira/main.c b/clients/moira/main.c
new file mode 100644 (file)
index 0000000..f970811
--- /dev/null
@@ -0,0 +1,149 @@
+#ifndef lint
+  static char rcsid_module_c[] = "$Header$";
+#endif lint
+
+/*     This is the file main.c for allmaint, the SMS client that allows
+ *      a user to maintaint most important parts of the SMS database.
+ *     It Contains:  The main driver for this program.
+ *     
+ *     Created:        4/12/88
+ *     By:             Chris D. Peterson
+ *
+ *      $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
+ */
+
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <strings.h>
+#include <sms.h>
+#include <menu.h>
+
+#include "mit-copyright.h"
+#include "allmaint.h"
+#include "globals.h"
+
+static void init_listmaint(), error_exit(), usage();
+void Put_message();
+char *getlogin();
+uid_t getuid();
+struct passwd *getpwuid();
+
+Bool use_menu = TRUE;          /* whether or not we are using a menu. */
+
+/*     Function Name: main
+ *     Description: The main driver for allmaint.
+ *     Arguments: argc, argv - standard command line args.
+ *     Returns: doesn't return.
+ */
+
+void
+main(argc, argv)
+    int argc;
+    char ** argv;
+{
+    char buf[BUFSIZ];
+
+    if ((user = getlogin()) == NULL) 
+       user = getpwuid((int) getuid())->pw_name;
+    user = (user && strlen(user)) ? Strsave(user) : "";
+
+    init_sms_err_tbl();
+    init_krb_err_tbl();
+
+    switch (argc) {
+    case 2:
+      if (strcmp(argv[1], "-nomenu") == 0)
+       use_menu = FALSE;
+      else
+       usage();
+                               /* Fall Through. */
+    case 1:
+      if ((program_name = rindex(argv[0], '/')) == NULL)
+       program_name = argv[0];
+      else
+       program_name++;
+      break;
+    default:
+      usage();
+      break;
+    }
+    
+    if ( status = sms_connect() ) 
+       error_exit("\nConnection to SMS server failed", status);
+
+    if ( status = sms_auth(argv[0]) ) 
+       error_exit("\nAuthorization failed -- please run kinit", status);
+
+/*
+ * These signals should not be set until just before we fire up the menu
+ * system. 
+ */
+    (void) signal(SIGHUP, signal_handler);
+    (void) signal(SIGINT, signal_handler);
+    (void) signal(SIGQUIT, signal_handler);
+
+    if (use_menu) {            /* Start menus that execute program */
+        Start_paging();
+       Start_menu(&allmaint_top_menu);
+       Stop_paging();
+    }
+    else                       /* Start program without menus. */
+       Start_no_menu(&allmaint_top_menu);
+
+    sms_disconnect();
+    exit(0);
+}
+
+/*     Function Name: error_exit
+ *     Description: This function does the error handling and exits.
+ *     Arguments: buf - the error message to print.
+ *                 status - the error code.
+ *     Returns: doesn't return.
+ */
+
+static void
+error_exit(buf,status);
+int status;
+char * whoami, *buf;    
+{
+    com_err(program_name, status, buf);
+    sms_disconnect();
+    exit(1);
+}
+
+/*     Function Name: usage
+ *     Description: Prints usage info and then exits.
+ *     Arguments: none
+ *     Returns: doesn't return.
+ */
+
+static void
+usage()
+{
+    fprintf(stderr, "Usage: %s [-nomenu]\n", program_name);
+    exit(1);
+}
+
+/*     Function Name: signal_handler
+ *     Description: This function cleans up from a signal interrupt.
+ *     Arguments: none.
+ *     Returns: doesn't
+ */
+
+static int *
+signal_handler()
+{
+    Put_message("Signal caught - exiting");
+    if (use_menu)
+      Cleanup_menu();
+    sms_disconnect();
+    exit(1);
+}
diff --git a/clients/moira/menus.c b/clients/moira/menus.c
new file mode 100644 (file)
index 0000000..96b5f82
--- /dev/null
@@ -0,0 +1,549 @@
+#ifndef lint
+  static char rcsid_module_c[] = "$Header$";
+#endif lint
+
+/*     This is the file menu.c for allmaint, the SMS client that allows
+ *      a user to maintaint most important parts of the SMS database.
+ *     It Contains: all menu definitions for allmaint.
+ *     
+ *     Created:        4/11/88
+ *     By:             Chris D. Peterson
+ *
+ *      $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
+ */
+
+#include <stdio.h>
+#include <menu.h>
+#include "mit-copyright.h"
+#include "allmaint.h"
+
+/*
+ * Attachmaint Menus
+ */
+
+Menu attachmaint_filemenu = {
+  NULLFUNC, 
+  NULLFUNC, 
+  "Filesystem Maintenance",
+  5,
+  {
+    { GetFS, NULLMENU, 2, {
+      {"get", "Get Filesystem Name Information"},
+      {"name", "Name of Filesystem: "}
+    } },
+    { AddFS, NULLMENU, 2, {
+      {"add", "Add New Filesystem to Database"},
+      {"name", "name: "},
+    } },
+    { ChangeFS, NULLMENU, 2, {
+      {"change", "Update Filesystem Information"},
+      {"name", "name: "},
+    } },
+    { RenameFS, NULLMENU, 2, {
+      {"rename", "Rename Filesystem"},
+      {"name", "Current (Old)  Name: "},
+    } },
+    { DeleteFS, NULLMENU, 2, {
+      {"delete", "Delete Filesystem"},
+      {"name", "Filesystem Name: "}
+    } } 
+  }
+};
+
+Menu attachmaint_top_menu = {
+  NULLFUNC, 
+  NULLFUNC, 
+  "Attach/Filesystem Maintenance", 
+  7,
+  {
+    SUBMENU("filesystem", "Filesystem Work", &filemenu),
+    { GetFSAlias, NULLMENU, 2, {
+      {"check", "Check An Association."},
+      {"name", "name (user/group/course): "}
+    } },
+    { CreateFSAlias, NULLMENU, 2, {
+      {"alais", "Associate with a Filesystem."},
+      {"name", "name (user/course/project): "},
+    } },
+    { DeleteFSAlias, NULLMENU, 2, {
+      {"unalias", "Disassociate from a Filesystem."},
+      {"name", "name (user/course/project): "},
+    } },
+    SIMPLEFUNC("verbose", "Toggle Verbosity of Delete.", ToggleVerboseMode),
+    SIMPLEFUNC("help", "Help ...", AttachHelp)
+  }
+};
+
+/*
+ * Clustermaint Menus
+ */
+
+Menu clustermaint_machine_menu = {
+  NULLFUNC,
+  NULLFUNC,
+  "Machine Maintenence",
+  7,
+  {
+    { ShowMachineInfo, NULLMENU, 2, {
+      {"ShowMachineInfo","Get machine information."},
+      {"name","Machine's Name: "}
+    } },
+    { AddMachine, NULLMENU, 2, {
+      {"AddMachine","Add a new machine."},
+      {"name","Machine's Name: "},
+    } },
+    { UpdateMachine, NULLMENU, 2, {
+      {"UpdateMachine","Update machine information."},
+      {"name","Machine's Name: "},
+    } },
+    { ChangeMachineName,  NULLMENU, 2, {
+      {"ChangeMachineName", "Change the name of machine"},
+      {"old", "Current (old) Machine's Name: "},
+    } },
+    { DeleteMachine, NULLMENU, 2, {
+      {"DeleteMachine","Delete this machine."},
+      {"name","Machine's Name: "}
+    } },
+    { AddMachineToCluster, NULLMENU, 3, {
+      {"AddMachineToCluster","Add this machine to a cluster."},
+      {"name","Machine's Name: "},
+      {"cluster","Name of the Cluster: "}
+    } },
+    { DeleteMachineFromAllClusters, NULLMENU, 2, {
+      {"DeleteMachineFromAllClusters",
+        "Delete this machine from all clusters."},
+      {"name","Machine's Name: "},
+    } },
+  }
+};
+
+Menu clustermaint_cluster_menu = {
+  NULLFUNC,
+  NULLFUNC,
+  "Cluster Information",
+  6,
+  {
+    { ShowClusterInfo, NULLMENU, 2, {
+      {"info", "Get cluster information."},
+      {"name", "Cluster's Name: "}
+    } },
+    { MachinesInCluster, NULLMENU, 2, {
+      {"machines", "List all machines in this cluster."},
+      {"clus", "Cluster's Name: "}
+    } }
+    { AddCluster, NULLMENU, 2, {
+      {"add", "Add a new cluster."},
+      {"name","Cluster's Name: "},
+    } },
+    { UpdateCluster, NULLMENU, 2, {
+      {"update", "Update cluster information."},
+      {"name","Cluster's Name: "},
+    } },
+    { ChangeClusterName,  NULLMENU, 2, {
+      {"cname", "Change the name of this cluster."},
+      {"old", "Current (old) Cluster's Name: "},
+    } },
+    { DeleteCluster, NULLMENU, 2, {
+      {"delete", "Delete this cluster."},
+      {"name", "Cluster's Name: "}
+    } },
+  }
+};
+
+Menu clustermaint_service_menu= {
+  NULLFUNC,
+  NULLFUNC,
+  "Service Cluster Maintenence",
+  3,
+  {
+    { ShowServicesForCluster, NULLMENU, 2, {
+      {"show_one", "Show a Service Cluster"},
+      {"clus", "Cluster's Name: "}
+    } },
+    { AddService, NULLMENU, 2, {
+      {"add", "Add a Service to a Cluster"},
+      {"clus", "Cluster Name: "},
+    } },
+    { DeleteService, NULLMENU, 2, {
+      {"delete", "Delete a Service from a Cluster"},
+      {"clus", "Cluster's Name: "},
+    } } 
+  }
+};
+
+Menu clusetermaint_top_menu = {
+  NULLFUNC,
+  NULLFUNC,
+  "Cluster Maintenence",
+  5,
+  {
+    SUBMENU("machine", "Work on Machines", &clustermaint_machine_menu),
+    SUBMENU("cluster", "Work on Clusters", &clustermaint_cluster_menu),
+    SUBMENU("service", "Service Clusters", &clustermaint_service_menu),
+    {MachineToClusterMap, NULLMENU, 3, {
+      {"map", "Machine to Cluster Mapping"},
+      {"machine", "Machine Name: "},
+      {"clus", "Cluster Name: "}
+    } },
+    SIMPLEFUNC("verbose", "Toggle Delete Confirmation", ToggleVerboseMode),
+  }
+};
+
+/*
+ * Dcmmaint menus
+ */
+
+/* Commenting out all DCM maint stuff. 
+
+Menu dcmmaint_service_menu = {
+  dcmmaint_service_menu_entry,
+  dcmmaint_service_menu_exit,
+  NULL,
+  5,
+  {
+    SIMPLEFUNC("show", "Show fields of service", show_service),
+    SIMPLEFUNC("interval", "Change the interval field", change_interval),
+    SIMPLEFUNC("target_path", "Change the target_path field",
+              change_target_path),
+    SIMPLEFUNC("script", "Change the script field", change_script),
+    SIMPLEFUNC("dfgen",
+              "Change the date of the latest generation of the db file", 
+              change_dfgen)
+  }
+};
+
+Menu dcmmaint_host_info_menu = {
+  dcmmaint_host_info_menu_entry,
+  dcmmaint_host_info_menu_exit,
+  NULL,
+  8,
+  {
+    SIMPLEFUNC("show", "Show values of entry", show_host_info),
+    SIMPLEFUNC("last_time", "Change the last_time field", change_last_time),
+    SIMPLEFUNC("success", "Change the success field", change_success),
+    SIMPLEFUNC("override", "Change the override field", change_override),
+    SIMPLEFUNC("enable", "Change the enable field", change_enable),
+    SIMPLEFUNC("value1", "Change the value1 field", change_value1),
+    SIMPLEFUNC("value2", "Change the value2 field", change_value2),
+    SIMPLEFUNC("rvdacls", "Change the RVD ACLs (for RVD servers only)",
+              update_rvd_server)
+  }
+};
+
+Menu dcmmaint_top_menu = {
+  NULLFUNC,
+  NULLFUNC,
+  "Data Control Manager Maintenance",
+  9,
+  {
+    SUBMENU("hi_change", "Modify a service-host entry", 
+           &dcmmaint_host_info_menu),
+    SIMPLEFUNC("hi_add", "Create new service-host entry", do_host_info),
+    SIMPLEFUNC("hi_delete", "Remove a service-host entry", do_host_info),
+    SIMPLEFUNC("hi_list", "List service-host entries", do_host_info),
+    SUBMENU("s_change", "Modify info for an existing service",
+           &dcmmaint_service_menu),
+    SIMPLEFUNC("s_add", "Create new service", do_service),
+    SIMPLEFUNC("s_delete", "Remove a service", do_service),
+    SIMPLEFUNC("s_list", "List services", do_service),
+    SIMPLEFUNC("help", "How to use this program", instructions)
+  }
+};
+
+Commenting out all DCM maint stuff. */
+
+/*
+ * Listmaint Menus 
+ */
+
+Menu listmaint_list_menu = {
+    NULLFUNC,
+    NULLFUNC,
+    "Lists",
+    5,
+    {
+        SIMPLEFUNC("member",
+                  "List all lists to which a given member belongs",
+                  ListByMember),
+       SIMPLEFUNC("administrator",
+                  "List all lists which a given user can administer",
+                  ListByAdministrator),
+       SIMPLEFUNC("groups", "List all lists which are groups",
+                  ListAllGroups),
+       SIMPLEFUNC("public", "List all public mailing lists",
+                  ListAllPublicMailLists),
+       SIMPLEFUNC("maillists", "List all mailing lists",
+                  ListAllMailLists)
+    }
+};
+
+Menu listmaint_member_menu = {
+    MemberMenuEntry,
+    MemberMenuExit,
+    NULL,
+    6,
+    {
+       SIMPLEFUNC("add", "Add a member to the list",
+                  AddMember),
+       SIMPLEFUNC("delete", "Delete a member from the list",
+                  DeleteMember),
+       SIMPLEFUNC("all", "Show the members of the list",
+                  ListMembers),
+       SIMPLEFUNC("user", "Show the members of type USER",
+                  ListUserMembers),
+       SIMPLEFUNC("list", "Show the members of type LIST",
+                  ListListMembers),
+       SIMPLEFUNC("string", "Show the members of type STRING",
+                  ListStringMembers)
+    } 
+};
+    
+Menu listmaint_top_menu = {
+    NULLFUNC,
+    NULLFUNC,
+    "List Maintenance Menu",
+    8,
+    {
+        { NULLFUNC, &listmaint_member_menu, 2, {
+           {"add", "Create new List"},
+           {"list name", "Name of list: "}
+       } },
+       { DeleteList, NULLMENU, 2, {
+           {"delete", "Delete a List"},
+           {"list name", "Name of list: "}
+       } },
+       { ShowListInfo, NULLMENU, 2, {
+           {"show", "Display information about a list"},
+           {"list name", "Name of list: "}
+       } },
+       { UpdateListInfo, NULLMENU, 2, {
+           {"update", "Update characteristics of a list"},
+           {"list name", "Name of list: "}
+       } },
+       { NULLFUNC, &listmaint_member_menu, 2, {
+           {"members", "Change/Display the membership of a list"},
+           {"list name", "Name of list: "}
+       } },
+       { DeleteUserFromLists, NULLMENU, 2, {
+           { "deluser", "Interactively query/delete user from all lists"},
+           { "user name", "Login name of user: "}
+       } },
+       SUBMENU("list_lists", "Display inventory of lists",
+               &listmaint_list_menu),
+       SIMPLEFUNC("help", "How to use this program", Instructions)
+    } 
+};
+
+/*
+ * NFSmaint menus.
+ */
+
+Menu nfsmaint_top_menu = {
+  NULLFUNC,
+  NULLFUNC,
+  "NFS Maintenence",
+  6,
+  {
+    { ShowNFSService, NULLMENU, 3, {
+      { "show", "Show an NFS server " },
+      { "machine", "Machine Name: "},
+      { "device", "Device: "}
+    } },
+    { AddNFSService, NULLMENU, 3, {
+      { "add", "Add NFS server" },
+      { "machine", "Machine Name: "},
+      { "device", "Device: "}
+    } },
+    { UpdateNFSService, NULLMENU, 3, {
+      { "update", "Update NFS server"},
+      { "machine", "Machine Name: "},
+      { "device", "Device: "}
+    } },
+    { DeleteNFSService, NULLMENU, 3, {
+      { "delete", "Delete NFS server"},
+      {"machine", "Machine Name: "},
+      {"device", "Device: "}
+    } },
+    SIMPLEFUNC("verbose", "Toggle Verbosity of Delete", ToggleVerboseMode),
+    SIMPLEFUNC("help", "Help", NFSHelp),
+  }
+};
+
+/*
+ * Portmaint menus.
+ */
+
+/* Queries have not been implemented yet :-( 
+
+Menu servmenu = {
+  NULLFUNC,
+  NULLFUNC,
+  "Server Maintenence",
+  8,
+  {
+    { getserv, NULLMENU, 2, {
+      {"get", "Services Info"},
+      {"serv", "Service Name: "}
+    } },
+    { addserv, NULLMENU, 4, {
+      {"add", "Add Service"},
+      {"srv", "Name: "},
+      {"proto", "Protocol: "},
+      {"port", "Port: "}
+    } },
+    { updserv, NULLMENU, 4, {
+      {"update", "Update Service"},
+      {"srv", "Name: "},
+      {"proto", "Protocol: "},
+      {"port", "Port: "}
+    } },
+    {delserv, NULLMENU, 3, {
+      {"delete", "Delete Service"},
+      {"serv", "Service Name: "},
+      {"proto", "Protocol: "}
+    } },
+    {  getassc, NULLMENU, 2, {
+      {"get_alias", "Get All Aliases for Service"},
+      {"srv", "Service Name: "}
+    } },
+    { alas, NULLMENU, 3, {
+      {"+", "Add Alias"},
+      {"srv", "Service Name: "},
+      {"als", "Alias: "}
+    } },
+    { alas, NULLMENU, 3, {
+      {"-", "Delete Alias"},
+      {"srv", "Service Name: "},
+      {"als", "Alias: "}
+    } },
+    SIMPLEFUNC("toggle", "Toggle Verbosity of Delete", toggle_verb)
+  }
+};
+
+*/
+/*
+ * smsmaint - TBS
+ */
+
+/* 
+ * Usermaint menu.
+ */
+
+Menu usermaint_quota_menu = {
+  NULLFUNC,
+  NULLFUNC,
+  "Edit User Quotas and Server Machines",
+  6,
+  {
+    SIMPLEFUNC("shdef", "Show default user quota (in KB)", ShowDefaultQuota),
+    {ShowUserQuota, NULLMENU, 2, {
+       {"shquota", "Show a user's quota (in KB)"},
+       {"login", "Login name: "}
+     } },
+    {ChangeDefaultQuota, NULLMENU, 2, {
+      {"chdef", "Change default user quota"},
+      {"quota", "New quota (in KB): "}
+    } },
+    {ChangeUserQuota, NULLMENU, 2, {
+      {"chquota", "Change a user's disk quota"},
+      {"user", "Login name: "}
+    } },
+    {AddUserLocker, NULLMENU, 5, {
+      {"create", "Create a quota & locker for a user"},
+      {"login", "User's login name: "},
+      {"machine", "Server host name: "},
+      {"device", "Physical device on host: "},
+      {"quota", "Quota in KB: "}
+    } },
+    {DeleteUserLocker, NULLMENU, 2, {
+      {"del", "Delete a user's quota & locker"},
+      {"login", "User's login: "}
+    } }
+  } 
+};
+
+Menu usermaint_top_menu = {
+  NULLFUNC,
+  NULLFUNC,
+  "SMS User Maintenance",
+  8,
+  {
+    {ShowUserByLogin, NULLMENU, 2, {
+       {"login", "Show user information by login name"},
+       {"login name", "Desired login name: "}
+     } },
+    {ShowUserByName, NULLMENU, 3, {
+      {"full", "Show user information by name (use * for wildcard)."},
+      {"first", "First name: "},
+      {"last", "Last name: "}
+    } },
+    {ShowUserByClass, NULLMENU, 2, {
+       {"login", "Show names of users in a give class."},
+       {"login name", "Desired class: "}
+     } },    
+    {ModifyUser, NULLMENU, 2, {
+      {"modify", "Change all user fields"},
+      {"login", "Login name: "}
+    } },
+/*    SIMPLEFUNC("chpw", "Change a user's password", change_user_password), */
+    {ChangeUserPOBox, NULLMENU, 2, {
+      {"chpobox", "Change a user's post office box"},
+      {"login name", "login name: "}
+    } },
+/*    {enter_user, NULLMENU, 6, {
+      {"enter", "Enter unregistered user"},
+      {"first", "User's first name: "},
+      {"middle", "User's middle initial: "},
+      {"last", "User's last name: "},
+      {"mit_id", "User's MIT ID: "},
+      {"mit_year", "User's MIT year: "}
+    } },
+    {reg_user, NULLMENU, 5, {
+      {"register", "Register unregistered user"},
+      {"first", "User's first name: "},
+      {"last", "User's last name: "},
+      {"mit_id", "User's MIT ID: "},
+      {"login", "Login name to assign: "}
+    } },
+ */
+    {DeleteUser, NULLMENU, 2, {
+      {"delete", "Delete user"},
+      {"login", "Login name: "}
+    } },
+    {DeleteUserByUid, NULLMENU, 2, {
+      {"udelete", "Delete user by uid"},
+      {"uid", "User ID (not MIT ID!): "}
+    } },
+    SUBMENU("quota", "User Quotas", &usermaint_quota_menu),
+  }
+};
+
+/* 
+ * Allmaint top menu
+ */
+
+Menu allmaint_top_menu = {
+  NULLFUNC,
+  NULLFUNC,
+  "All Maint Top Level Menu",
+  5,
+  {
+    SUBMENU("attachmaint","open the attachmaint menu",&attachmaint_top_menu),
+    SUBMENU("clustermaint","open the clustermaint menu",
+           &clustermaint_top_menu),
+/*    SUBMENU("dcmmaint","open the dcmmaint menu",&dcmmaint_top_menu), */
+    SUBMENU("listmaint","open the listmaint menu",&listmaint_top_menu),
+    SUBMENU("nfsmaint","open the nfsmaint menu",&nfsmaint_top_menu),
+/*    SUBMENU("portmaint","open the portmaint menu",&portmaint_top_menu), */
+/*    SUBMENU("smsmaint","open the smsmaint menu",&smsmaint_top_menu), */
+    SUBMENU("usermaint","open the usermaint menu",&usermaint_top_menu)
+  }
+};  
+       
diff --git a/clients/moira/nfs.c b/clients/moira/nfs.c
new file mode 100644 (file)
index 0000000..14750e3
--- /dev/null
@@ -0,0 +1,334 @@
+#ifndef lint
+  static char rcsid_module_c[] = "$Header$";
+#endif lint
+
+/*     This is the file nfs.c for allmaint, the SMS client that allows
+ *      a user to maintaint most important parts of the SMS database.
+ *     It Contains: The nfs maintanance code.
+ *     
+ *     Created:        5/6/88
+ *     By:             Chris D. Peterson
+ *
+ *      $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
+ */
+
+#include "mit-copyright.h"
+#include "allmaint.h"
+#include "globals.h"
+#include "infodefs.h"
+
+#include <stdio.h>
+#include <strings.h>
+#include <sms.h>
+#include <menu.h>
+
+/* #include <sys/types.h> */
+
+#define TYPE_NFS    "NFS"
+
+#define DEFAULT_DIR    "/mit"
+#define DEFAULT_STATUS "1"
+#define DEFAULT_ALLOC  "0"
+#define DEFAULT_SIZE   "400000"
+
+/*     Function Name: PrintNFSInfo
+ *     Description: Prints NFS Physical service information.
+ *     Arguments: info - the information.
+ *     Returns: none.
+ */
+
+void
+PrintNFSInfo(info)
+char ** info;
+{
+    char temp_buf[BUFSIZ];
+    int status = atoi(info[NFS_STATUS]);
+    
+    sprintf(temp_buf,"Machine: %s,\tDirectory: %s,\tDevice: %s",
+           info[NFS_NAME], info[NFS_DIR], info[NFS_DEVICE]);
+    Put_message(temp_buf);
+    sprintf(temp_buf, "Status: %s,\tQuota Allocated: %s.\tSize: %s",
+           status ? "Active" : "Inactive", info[NFS_ALLOC], info[NFS_SIZE]);
+    Put_message(temp_buf);
+    sprintf(temp_buf, "Last Modification by %s at %s with %s.",
+                  answer[U_MODBY], answer[U_MODTIME], answer[U_MODWITH]);
+    Put_message(temp_buf);
+}
+/*     Function Name: AskNFSInfo.
+ *     Description: This function askes the user for information about a 
+ *                   machine and saves it into a structure.
+ *     Arguments: info - a pointer the the structure to put the
+ *                             info into.
+ *     Returns: the arglist to make the update call with.
+ */
+
+char **
+AskNFSInfo(info);
+char ** info;
+{
+    /* Also need name of the machine in this structure. */
+
+    GetValueFromUser("Directory for filesystem:", &info[NFS_DIR]);
+    GetValueFromUser("Device for this filsystem", &info[NFS_DEVICE]); 
+
+    Put_message("\nTypes: Student, Faculty, Project, Staff, and Other.\n");
+    GetValueFromUser("Please enter one or more of the above types:"
+                    ,&info[NFS_STATUS]);
+
+    GetValueFromUser("Allocated Space for this filsystem:",&info[NFS_ALLOC]);
+    GetValueFromUser("Size of this Filsystem:",&info[NFS_SIZE]);
+
+    FreeAndClear(&info[NFS_MODTIME], TRUE);
+    FreeAndClear(&info[NFS_MODBY], TRUE);
+    FreeAndClear(&info[NFS_MODWITH], TRUE);
+    
+    return(info)
+}
+
+/*     Function Name: ShowNFSService
+ *     Description: This function prints all exported partitions.
+ *     Arguments: argc, argv - argv[1] - name of filesysytem.
+ *                              argv[2] - name of filesystem device.
+ *     Returns: DM_NORMAL.
+ */
+
+int 
+ShowNFSService(argc, argv)
+int argc;
+char **argv;   
+{
+    register int stat;
+    struct qelem * top, *elem = NULL;
+    
+    if ( (stat = sms_query("get_nfsphys", 2, argv + 1, 
+                          StoreInfo, (char *)  &elem)) != 0)
+       com_err(whoami, stat, " in ShowNFSServices.");
+
+    top = elem;
+    while (elem != NULL) {
+       info = (char **) elem->q_data;
+       PrintNFSInfo(info);
+       elem = elem->q_forw;
+    }
+    FreeQueue(top);
+    return (DM_NORMAL);
+}
+
+/*     Function Name: AddNFSService
+ *     Description: Adds a new partition to the nfsphys relation
+ *     Arguments: arc, argv - 
+ *                             argv[1] - machine name.
+ *                             argv[2] - device
+ *     Returns: DM_NORMAL.
+ */
+
+int
+AddNFSService(argc, argv)
+char **argv;
+int argc;
+{
+    char **args;
+    static char *info[MAX_ARGS_SIZE];
+    int stat;
+    
+    if ( (stat = sms_query("get_nfsphys", 2, argv + 1, 
+                          NullFunc, (char *) NULL)) == 0) {
+       Put_message("This service already exists.");
+       if (stat != SMS_NO_MATCH) 
+           com_err(whoami, stat, " in get_nfsphys.");
+    }
+    
+    if ( (info[NFS_NAME] = CanonicalizeHostname(argv[1])) == NULL) {
+       Put_message("Unknown host, try again...");
+       return(DM_NORMAL);
+    }
+
+    info[NFS_NAME]   = Strsave(info[NFS_NAME]);
+    info[NFS_DEVICE] = Strsave(argv[2]);
+    info[NFS_DIR]    = Strsave(DEFAULT_DIR);
+    info[NFS_STATUS] = Strsave(DEFAULT_STATUS);
+    info[NFS_ALLOC]  = Strsave(DEFAULT_ALLOC);
+    info[NFS_SIZE]   = Strsave(DEFAULT_SIZE);
+    info[NFS_SIZE + 1] = NULL; /* NULL terminate. */
+
+    args = AskNFSInfo(info);
+    
+    if ((stat = sms_query("add_nfsphys", CountArgs(args), args,
+                          Scream, (char *) NULL)) != 0) 
+       com_err(whoami, stat, " in AdsNFSService");
+    
+    FreeInfo(info);
+    return (DM_NORMAL);
+}
+
+/*     Function Name: UpdateNFSService
+ *     Description: Update the values for an nfsphys entry.
+ *     Arguments: argc, argv -
+ *                             argv[1] - machine name.
+ *                             argv[2] - device
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED. */
+int
+UpdateNFSService(argc, argv)
+char **argv;
+int argc;
+{
+    register int stat;
+    Bool update, one_service;
+    char **args, **info, buf[BUFSIZ];
+    struct qelem *elem, *top;
+    elem = NULL;
+
+    if ( (argv[1] = CanonicalizeHostname(argv[1])) == NULL) {
+       Put_message("Unknown host, try again...");
+       return(DM_NORMAL);
+    }
+
+    if ( (stat = sms_query("get_nfsphys", 2, argv + 1,
+                          StoreInfo, (char *) &elem)) != 0) {
+       com_err(whoami, stat, " in UpdateNFSService.");
+       return (DM_NORMAL);
+    }
+
+    top = elem;
+    one_service = ( QueueCount(top) == 1 );
+    while (elem != NULL) {
+       info = (char **) elem->q_data;
+       if (!one_service) {     /* If more than one then query through them. */
+           sprintf(buf,"Update - %s\tDirectory: %s? (y/n/q)", info[NFS_NAME],
+                   info[NFS_DIR]);
+           switch( YesNoQuitQuestion(buf, FALSE)) {
+           case TRUE:
+               update = TRUE;
+               break;
+           case FALSE:
+               update = FALSE;
+               break;
+           case QUIT:
+               FreeQueue(top);
+               Put_message("Aborting update.");
+               Return(DM_NORMAL);
+               break;
+           }
+       }
+       else
+           update = TRUE;
+
+       if (update) {           /* actually perform update */
+           args = AskNFSInfo(info);
+           if ((stat = sms_query("update_nfsphys", num_args, args,
+                                 abort, (char *)NULL)) != 0) 
+               com_err(whoami, stat, (char *) NULL);
+       }
+       elem = elem->q_next;
+    }
+
+    FreeQueue(top);
+    return (DM_NORMAL);
+}
+
+/* stop CDP 6/7/88 */
+
+/*     Function Name: DeleteCheck
+ *     Description: This checks to see if we should delete this nfs
+ *     Arguments: argc, argv - 
+ *                              argv[0] - name of file system.
+ *                              argv[1] - type of file system.
+ *                              argv[3] - packname of fulsys
+ *                data - a filled info structure.
+ *     Returns: SMS_CONT.
+ */
+
+DeleteCheck(argc, argv, date)
+int argc;
+char **argv, *data;
+{
+    char buf[BUFSIZ];
+    NFS_info *info = (NFS_info *) data;
+
+    return(SMS_CONT);
+}
+
+/*     Function Name: DeleteNFSService
+ *     Description: Delete an nfsphys entry.
+ *     Arguments: argc, argv - name of file system in argv[1].
+ *                              directory of file system in argv[2].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+DeleteNFSService(argc, argv)
+int argc;
+char **argv;
+{
+    register int stat;
+    struct qelem *elem, *top;
+    char * dir = argv[2];
+    int length;
+    Bool delete_ok = TRUE;
+
+    elem = NULL;
+    argv[1] = CanonicalizeHostname(argv[1]);
+
+    stat = sms_query("get_nfsphys", 2, argv + 1, NullFunc, (char *) NULL);
+    if (stat == SMS_NO_MATCH) {
+       Put_message("This filsystem does not exist!");
+       return(DM_NORMAL);
+    }
+    if (stat) {
+       com_err(whoami, stat, " in DeleteNFSService");
+       return(DM_NORMAL);
+    }
+    
+    stat = sms_query("get_filesys_by_machine", 1, argv + 1, StoreInfo, 
+                    &elem);
+    if (stat && stat != SMS_NO_MATCH)
+       com_err(whoami, stat, " while checking usage of partition");
+
+    length = strlen( dir );
+    top = elem;
+    while (elem != NULL) {
+       info = (char ** ) elem->q_data;
+       if ( (strcmp(info[FS_TYPE], TYPE_NFS) == 0) && 
+            (strcmp(info[FS_PACK], dir, length) == 0) ) {
+           sprintf(buf, "Filesystem %s uses that partition", info[FS_NAME]);
+           Put_message(buf);
+           delete_ok = FALSE;
+       }
+       elem = elem->q_forw;
+    }
+
+    if ( delete_ok && 
+       Confirm("Do you really want to delete this Filesystem? (y/n) ")) {
+       if ( (stat = sms_query("delete_nfsphys", 2, argv + 1,
+                              Scream, (char *) NULL )) !=0 )
+           com_err(whoami, stat, " in DeleteNFSService");
+    }
+    else
+       Put_message("Operation Aborted.\n");
+
+    FreeQueue(top);
+    return(DM_NORMAL);
+}
+
+
+/*
+ * 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:
+ */
diff --git a/clients/moira/user.c b/clients/moira/user.c
new file mode 100644 (file)
index 0000000..f3484b2
--- /dev/null
@@ -0,0 +1,696 @@
+ifndef lint
+  static char rcsid_module_c[] = "$Header$";
+#endif lint
+
+/*     This is the file user.c for allmaint, the SMS client that allows
+ *      a user to maintaint most important parts of the SMS database.
+ *     It Contains: the functions for usermaint.
+ *     
+ *     Created:        5/9/88
+ *     By:             Chris D. Peterson
+ *
+ *      $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
+ */
+
+#include "mit-copyright.h"
+#include "allmaint.h"
+#include "infodefs.h"
+
+#include <stdio.h>
+#include <strings.h>
+#include <ctype.h>
+
+/* SMS includes */
+
+#include <sms.h>
+#include <sms_app.h>
+#include <menu.h>
+
+#define LOGIN 0
+#define UID   1
+#define NAME  2
+#define QUOTA 3
+#define CLASS 4
+
+/*     Function Name: AskUserInfo.
+ *     Description: This function askes the user for information about a 
+ *                   machine and saves it into a structure.
+ *     Arguments: info - a pointer the the structure to put the info into.
+ *                 flags - Flags asking us which info we want.
+ *     Returns: the args to pass to the query.
+ *      NOTES: the return args are not necessarily in the correct order to
+ *             use the #defined names (e.g args[UID] is not the uid anymore).
+ */
+
+void
+AskUserInfo(info, name);
+char ** info;
+Bool name;
+{
+    char * temp_buf, *newname;
+
+    int counter;
+
+    sprintf(temp_buf,"\nChanging Attributes of user %s.\n",info[NAME]);
+    Put_message(temp_buf);
+
+    if (name) {
+       newname = Strsave(info[U_NAME]);
+       GetValueFromUser("The new login name for this user.", &newname);
+    }
+    GetValueFromUser("User's UID:", &info[U_UID]);
+    GetValueFromUser("User's shell:", &info[U_SHELL]);
+    GetValueFromUser("User's last name:", &info[U_LAST]);
+    GetValueFromUser("User's first name:", &info[U_FIRST]);
+    GetValueFromUser("User's middle name:", &info[U_MIDDLE]);
+    GetValueFromUser("User's status:", &info[U_STATE]);
+    GetValueFromUser("User's MIT ID number:", &info[U_MITID]);
+    RemoveHyphens(info[U_MITID]); /* zap'em */
+    GetValueFromUser("User's MIT Year (class):", &info[U_CLASS]);
+    
+    FreeAndClear(&info[U_MODTIME], TRUE);
+    FreeAndClear(&info[U_MODBY], TRUE);
+    FreeAndClear(&info[U_MODWITH], TRUE);
+
+/* 
+ * Slide the newname into the #2 slot, this screws up all future references 
+ * to this list, since we slip the pointer into a info list it gets freed 
+ * when the rest of the list gets freed.
+ */
+    if (name)                  
+       SlipInNewName(info, newname);
+
+    return(info);
+}
+
+/*     Function Name: GetUserInfo
+ *     Description: Stores the user information in a queue.
+ *     Arguments: type - type of field given to get info, one of:
+ *                        LOGIN, UID, NAME, CLASS.
+ *                 name1 - name of thing specified by type (wildcards okay)
+ *                 name2 - other name, only used in get user by first and last.
+ *                         (wildcards okay).
+ *     Returns: the first element of the queue containing the user info.
+ */
+
+struct qelem *
+GetUserInfo(type, name1, name2);
+int type;
+char *name1, *name2;
+{
+    char * args[2];
+    struct quelem * elem = NULL;
+
+    switch(type) {
+    case LOGIN:
+       args[0] = name1;
+       if ( (status = sms_query("get_user_by_login", 1, args,
+                              StoreInfo, (caddr_t) &elem)) != 0) {
+           com_err(whoami, status, " when attempting to get_use_by_login.");
+           return (NULL);               
+       }
+       break;
+    case UID:
+       args[0] = name1;
+       if ( (status = sms_query("get_user_by_uid", 1, args,
+                              StoreInfo, (caddr_t) &elem)) != 0) {
+           com_err(whoami, status, " when attempting to get_use_by_uid.");
+           return (NULL);      
+       }
+       break;
+    case NAME:
+       args[0] = name1;
+       args[1] = name2;    
+       if ( (status = sms_query("get_user_by_name", 1, args,
+                              StoreInfo, (caddr_t) &elem)) != 0) {
+           com_err(whoami, status, " when attempting to get_use_by_name.");
+           return (NULL);      
+       }
+       break;
+    case CLASS:
+       args[0] = name1;
+       if ( (status = sms_query("get_user_by_class", 1, args,
+                              StoreInfo, (caddr_t) &elem)) != 0) {
+           com_err(whoami, status, " when attempting to get_use_by_class.");
+           return (NULL);      
+       }
+       break;
+    case QUOTA:
+       args[0] = name1;
+       if ( (status = sms_query("get_nquotas_by_user", 1, args,
+                              StoreInfo, (char *) &elem)) != 0) {
+           com_err(whoami, status, " in get_nfs_quotas_by_user");
+           return (DM_NORMAL);
+       }
+       break;
+    }
+    return( QueueTop(elem) );
+}
+
+/* -------------------------- Change Menu -------------------------- */
+
+/*     Function Name: ModifyUser
+ *     Description: Modify some of the information about a user.
+ *     Arguments: argc, argv - login name of the user in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+ModifyUser(argc, argv)
+int argc;
+char **argv;
+{
+    int num_args;
+    char ** info;
+    char *temp_buf;
+    struct qelem * user, * local;
+
+    user = GetUserInfo(LOGIN, argv[1], (char *) NULL);
+
+    local = user;
+    while (local != NULL) {
+       info = (char **) local->q_data;
+       info = AskUserInfo(info, TRUE);
+       num_args = CountArgs(info);
+
+       if ( (status = sms_query("update_user", 
+                                num_args, info, Scream, NULL)) != 0) {
+           com_err(whoami, status, " in ModifyFields");
+           if (local->next == NULL)
+               temp_buf = "";
+           else
+               temp_buf = ", Continuing to next user";
+           sprintf(error_buf,"User %s not updated due to error%s.",
+                   info[NAME], temp_buf);
+           Put_message(error_buf);
+       }
+       local = local->next;
+    }
+    FreeQueue(user);
+    return(DM_NORMAL);
+}
+
+
+/*     Function Name: POType
+ *     Description: Asks the SMS server if it is of type pop, of
+ *                   of type local. If neither, we assume that it's 
+ *                   of type foreign. 
+ *     Arguments: machine - a canonicalized machine name, 
+ *     Returns: the PO Type, one of: pop, local, foreign.
+ */
+
+char *
+POType(machine)
+char *machine;
+{
+    int status;
+    char * type;
+    struct qelem *top, *elem = NULL;
+
+    match = 0;
+    type = "pop";
+    status = sms_query("get_server_locations", 1, &type,
+                      StoreInfo, &elem);
+    if (status && (status != SMS_NO_MATCH)) {
+       com_err(whoami, status, (char *) NULL);
+       return( (char *) NULL);
+    }
+
+    top = elem;
+    while (elem != NULL) {
+       info = (char **) elem->q_data;
+       if (strcmp (info[1], machine) == 0) {
+           FreeQueue(top);
+           return( Strsave("POP") );
+       }
+       elem = elem->q_forw;
+    }
+    FreeQueue(top);
+    return ( Strsave("SMTP") );
+}
+
+/*     Function Name: ChangeUserPOBox
+ *     Description: Changes The P.O. Box for a user.
+ *     Arguments: argc, argv - the login name of the user in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/*ARGSUSED*/
+int
+ChangeUserPOBox(argc, argv)
+int argc;
+char **argv;
+{
+    struct qelem * poqueue, *local;
+    char *type, buf[BUFSIZ];
+    extern int po_callbk(), PrintPOBoxes();
+    static char *po[4];
+    poqueue = NULL;
+
+    sprintf(buf,"Current pobox for user %s: \n", argv[1]); 
+    Put_message(buf);
+    status = sms_query("get_pobox", 1, argv + 1, PrintPOBoxes, NULL);
+    if (status != SMS_NO_MATCH && status != 0) {
+       com_err(whoami, status, "in ChangeUserPOBox.");
+        return(DM_NORMAL);
+    }
+    else if (status == SMS_NO_MATCH) 
+       Put_message("This user has no P.O. Box.");
+    
+    if (YesNoQuestion("Shall we use the least loaded Post Office?", TRUE)) {
+       po[0] = "pop";
+       po[1] = "*";
+       post_office.host = NULL;
+       post_office.least_full = -1;
+       if ( status = sms_query ("get_server_host_info", 2, po,
+                                StoreInfo, (caddr_t) &poqueue) != 0) {
+           com_err(whoami, status, 
+                   " in ChangeUserPOBox (get_server_host_info).");
+           return(DM_NORMAL);
+       }
+       local = poqueue;
+       while (local != NULL) {
+           if ( !isdigit(*argv[6]) || !isdigit(*argv[7]) )
+               put_message(
+                   "non-digit value in server_host_info, this is a bug");
+           else {
+               new_space = atoi(argv[7]) - atoi(argv[6]);
+               if ( new_space < old_space ) {
+                   old_space = new_space;
+               pohost = argv[1];
+               }
+           }
+           local = local->next;
+       }
+       FreeQueue(poqueue);
+       type = "POP";
+       (void) sprintf(buf, "The Post Office %s was chosen.",
+                      pohost);
+       Put_message(buf);
+    }
+    else if( (Prompt_input("Which Machine for Post Office?", 
+                          buf, BUFSIZ)) ) {
+       if ( (pohost = CanonicalizeHostname(buf)) == NULL) {
+           Put_message("\nNameserver doesn't know that machine, sorry.");
+           return (DM_NORMAL);
+       }
+       type = POType(pohost); 
+    }
+    
+    sprintf(buf, "%s %s's %s %s?", "Are you sure that you want to replace all",
+           argv[1], "P.O. Boxes\n with ** ONE ** on the machine", pohost);
+
+    if(Confirm(buf)) {
+       po[0] = argv[1];
+       po[1] = type;
+       po[2] = pohost;
+       po[3] = po[0];
+       if (status = sms_query("set_pobox", 4, po, Scream, NULL) != 0 )
+           com_err(whoami, status, " in ChangeUserPOBox");
+    } else 
+       PutMessage("Operation Aborted.");
+
+    return (DM_NORMAL);
+}
+
+/* ------------------------- Top Menu ------------------------- */
+
+/* delete user in delete.c */
+
+/*     Function Name: DeleteUserByUid
+ *     Description: Deletes the user given a uid number.
+ *     Arguments: argc, argv - uid if user in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/*ARGSUSED*/
+int
+DeleteUserByUid(argc, argv)
+int argc;
+char **argv;
+{
+    if (Confirm("Are you sure you want to remove this user"))
+       if ( (status = sms_query("delete_user_by_uid", 1, argv+1, Scream,
+                              (char * ) NULL)) != 0)
+           com_err(whoami, status, " in DeleteUserByUid");
+
+    return(DM_NORMAL);
+} 
+
+/* ------------------------- Show Quota Info ------------------------- */
+
+/*     Function Name: ShowDefaultQuota
+ *     Description: This prints out a default quota for the system.
+ *     Arguments: none
+ *     Returns: DM_NORMAL.
+ */
+
+int
+ShowDefaultQuota()
+{
+    extern int printit();
+    static char *val[] = {"def_quota"};
+
+    if (status = sms_query("get_value", 1, val, Print, (char *) NULL) != 0)
+       com_err(whoami, status, " in ShowDefaultQuota");
+
+    return (DM_NORMAL);
+}
+
+/*     Function Name: ShowUserQuota
+ *     Description: Shows the quota of a user.
+ *     Arguments: argc, argv - users login name is argv[1].
+ *     Returns: DM_NORMAL
+ */
+
+/*ARGSUSED*/
+int
+ShowUserQuota(argc, argv)
+int argc;
+char **argv;
+{
+    extern int PrintQuota();
+
+    if (status = sms_query("get_nfs_quotas_by_user", 1, argv+1, PrintQuota,
+                      (char *) NULL) != 0)
+       com_err(whoami, status, " in ShowUserQuota);
+
+    return (DM_NORMAL);
+}
+
+/*     Function Name: ChangeDefaultQuota
+ *     Description: Changes the System Wide default quota.
+ *     Arguments: argc, argv - New quota in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/*ARGSUSED*/
+int
+ChangeDefaultQuota(argc, argv)
+int argc;
+char *argv[];
+{
+    static char *newval[] = {
+       "update_value", "def_quota", NULL,
+    };
+
+    sprintf(buf,"%s%s",
+           "Are you sure that you want to change the default quota\n"
+           "for all new users");
+    if(!Confirm(buf)) {
+       newval[2] = argv[1];
+       if (status = sms_query("update_value", 3, newval, Scream, NULL) != 0)
+           com_err(whoami, status, " in update_value");
+    }
+    else
+       Put_message("Quota not changed.");
+
+    return (DM_NORMAL);
+}
+
+/* ---------------------- User Locker Manipultation -------------------- */
+
+/*     Function Name: AddUserLocker
+ *     Description: Add a new locker for a user.
+ *     Arguments: arc, argv - 
+ *                             argv[1] login name of user.
+ *                             argv[2] server host name.
+ *                             argv[3] physical device on host.
+ *                             argv[4] quota in Kb.
+ *     Returns: DM_NORMAL.
+ */
+
+/*ARGSUSED*/
+int
+AddUserLocker(argc, argv)
+int argc;
+char **argv;
+{
+    extern char *CanonicalizeHostname();
+    char *tuple[4];
+
+    args[0] = argv[1];
+    args[2] = argv[3];
+    args[3] = argv[4];
+    
+    args[1] = CanonicalizeHostname(argv[2]);
+    if (args[1] == (char *)NULL) {
+       Put_message("Could not canonicalize hostname; continuing..");
+       args[1] = argv[2];
+    }
+    
+    if (status = sms_query("add_locker", 4, args, Scream, NULL) != 0)
+       com_err(whoami, status, " in add_user_locker");
+
+    return(DM_NORMAL);
+}
+
+/*     Function Name: DeleteUserLocker
+ *     Description: Deletes a locker - BOOM.
+ *     Arguments: arc, argv - the name of the locker in argv[1]/
+ *     Returns: DM_NORMAL.
+ */
+
+/*ARGSUSED*/
+int
+DeleteUserLocker(argc, argv)
+int argc;
+char **argv;
+{
+    if (status = sms_query("delete_locker", 1, argv + 1,
+                          scream, (char *)NULL) != 0) 
+           com_err(whoami, status, " in delete_locker");
+
+    return(DM_NORMAL);
+}
+
+/*     Function Name: ChangeUserQuota
+ *     Description: This function allows all quotas to be updated for a user.
+ *     Arguments: arg, argv - the name of the user in argv[1].
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+ChangeUserQuota(argc, argv)
+int argc;
+char *argv[];
+{
+    int i;
+    struct qelem *elem, *local;
+    
+    elem = GetUserInfo(QUOTA, argv[1], (char *) NULL);
+
+    local = elem;
+    while (local != NULL) {
+       char *info[4], buf[BUFSIZ];
+       info = (char **) local->q_data;
+       PrintQuota(info);
+       if( !PromptWithDefault("New quota (in KB): ", buf, sizeof(buf), 
+                              quot_array[2]) )
+           return(DM_NORMAL);
+       
+       /* Reorganize for update nfs_quota. */
+       info[3] = info[2];
+       info[2] = argv[1];
+    
+       if (status = sms_query("update_nfs_quota", 4, info,
+                              Scream, (char *) NULL) != 0) {
+           com_err(whoami, status, " in update_nfs_quota");
+           sprintf(error_buf,"Could not perform quota change on %s",info[0]); 
+           Put_message(error_buf);
+       }
+       local = local->q_forw;
+    }
+    FreeQueue(elem);
+    return (DM_NORMAL);
+}
+
+/*     Function Name: ShowUserByLogin
+ *     Description: Shows user information given a login name.
+ *     Arguments: argc, argv - login name in argv[1].
+ *     Returns: DM_NORMAL
+ */
+
+/* ARGSUSED */
+int
+ShowUserByLogin(argc, argv)
+int argc;
+char *argv[];
+{
+    struct qelem *top, *elem;
+
+    elem = top = GetUserInfo(LOGIN, argv[1], (char *) NULL);
+    while (elem != NULL) {
+       PrintUserInfo( (char **) elem->q_data, FALSE);
+       elem = elem->q_forw;
+    }
+
+    FreeQueue(top);
+    return (DM_NORMAL);
+}
+
+/*     Function Name: RetrieveUserByName
+ *     Description: Show information on a user give fist and/or last name.
+ *     Arguments: argc, argv - argv[1] - first name.
+ *                              argv[2] - last name.
+ *     Returns: DM_NORMAL.
+ */
+
+/* ARGSUSED */
+int
+ShowUserByName(argc, argv)
+int argc;
+char *argv[];
+{
+    struct qelem *top, *elem;
+    char buf, temp_buf[BUFSIZ];
+
+    elem = top = GetUserInfo(NAME, argv[1], argv[2]);
+
+    if (!PromptWithDefault("Print full information, or just the names (F/N)?",
+                          &buf, 1, "F"))
+       return(DM_NORMAL);
+
+    while (elem != NULL) {
+       switch(buf) {
+       case 'F':
+       case 'f':
+           PrintUserInfo( (char **) elem->q_data, FALSE);
+           break;
+       case 'N':
+       case 'n':
+           break;
+           PrintUserInfo( (char **) elem->q_data, TRUE);
+       }
+       elem = elem->q_next;
+    }
+
+    FreeQueue(top);
+    return (DM_NORMAL);
+}
+
+/*     Function Name: ShowUserByClass
+ *     Description: Shows real and login names of all users in class.
+ *     Arguments: argc, argv - argv[1] contains the class.
+ *     Returns: none.
+ */
+
+int
+ShowUserByClass(argc, argv)
+int argc;
+char **argv;
+{
+    struct qelem *top, *elem;
+    char buf, temp_buf[BUFSIZ];
+
+    elem = top = GetUserInfo(CLASS, argv[1], (char *) NULL);
+
+    while (elem != NULL) {
+       PrintUserInfo( (char **) elem->q_data, TRUE);
+       elem = elem->q_next;
+    }
+
+    FreeQueue(top);
+    return (DM_NORMAL);
+}
+
+
+/*     Function Name: PrintQuota
+ *     Description: Prints a users quota information.
+ *     Arguments: info - a pointer to the quota information:
+ *     Returns: none.
+ */
+
+static void
+PrintQuota(info)
+char ** info;
+{
+    sprintf(buf, "Machine: %s\t\tDevice: %s\t\tQuota: %s",
+                  info[Q_MACHINE], info[Q_DEVICE], info[Q_QUOTA]);
+    Put_message(buf);
+}
+
+/*     Function Name: PrintPOBoxes
+ *     Description: Yet another specialized print function.
+ *     Arguments: argc, argv - 
+ *                             argv[0] - login name.
+ *                             argv[1] - type.
+ *                             argv[2] - machine.
+ *                             argv[3] - box name.
+ *                 junk.  - NOT USED
+ *     Returns: SMS_CONT
+ */
+
+/* ARGSUSED */
+int
+PrintPOBoxes(argc, argv, junk)
+int argc;
+char **argv;
+caddr_t junk;
+{
+    /* no newline 'cause Put_message adds one */
+
+    (void) sprintf(buf, "Address: %s@%s\t\tType: %s", argv[PO_BOX],
+                  argv[PO_MACHINE], argv[PO_TYPE]);
+    (void) Put_message(buf);
+
+    return (SMS_CONT);
+}
+
+/*     Function Name: PrintUserInfo
+ *     Description: Prints Information about a user.
+ *     Arguments: answer - an argument list with the user information
+ *                          in it.
+ *                 name_only - if TRUE then print only the users name.
+ *     Returns: none
+ */
+
+void
+PrintUserInfo(answer, name_only)
+char ** answer;
+Bool name_only;
+{
+    if (name_only) {
+       sprintf(temp_buf, "%s, %s %s", info[U_LAST],
+               info[U_FIRST], info[U_MIDDLE]);
+       sprintf(temp_buf, "%-40s/tUser Name: %s", temp_buf, info[U_NAME]);
+       Put_message(temp_buf);
+    }
+    else {
+       (void) sprintf(temp_buf, 
+                      "Login name: %-10s/tUser id: %-10s\tLogin shell %s",
+                      answer[U_NAME], answer[U_UID], answer[U_SHELL]);
+       (void) Put_message(temp_buf);
+       (void) sprintf(temp_buf, "Full name: %s %s %s\tClass: %s", 
+                      answer[U_FIRST], answer[U_MIDDLE], 
+                      answer[U_LAST], answer[U_CLASS]);
+       (void) Put_message(temp_buf);
+       (void) sprintf(temp_buf,
+                      "Account status: %2s\tEncrypted MIT ID number: %s",
+                      answer[U_STATUS], answer[U_MITID]);
+       (void) Put_message(temp_buf);
+       (void) sprintf(temp_buf, "Last Modification by %s at %s with %s.",
+                      answer[U_MODBY], answer[U_MODTIME], answer[U_MODWITH]);
+       (void) Put_message(temp_buf);
+    }
+}
+
+/*
+ * 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:
+ */
diff --git a/clients/moira/utils.c b/clients/moira/utils.c
new file mode 100644 (file)
index 0000000..a3ab665
--- /dev/null
@@ -0,0 +1,612 @@
+#ifndef lint
+  static char rcsid_module_c[] = "$Header$";
+#endif lint
+
+/*     This is the file utils.c for allmaint, the SMS client that allows
+ *      a user to maintaint most important parts of the SMS database.
+ *     It Contains: Many utilities used by allmaint.
+ *     
+ *     Created:        4/25/88
+ *     By:             Chris D. Peterson
+ *
+ *      $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
+ */
+
+
+#include <stdio.h>
+#include <strings.h>
+#include <sms.h>
+#include <menu.h>
+
+#include "mit-copyright.h"
+#include "allmaint.h"
+#include "globals.h"
+#include "infodefs.h"
+
+#include <netdb.h>             /* for gethostbyname. */
+/* #include <ctype.h> */
+/* #include <varargs.h> */
+/* #include <sys/types.h> */
+
+/*     Function Name: FreeInfo
+ *     Description: Frees all elements of a NULL terminated arrary of char*'s
+ *     Arguments: info - array who's elements we are to free.
+ *     Returns: none.
+ */
+
+void
+FreeInfo(info)
+char ** info;
+{
+    char *pointer = *info;
+    while (pointer != NULL) 
+       free(pointer++);
+}
+
+/*     Function Name: FreeQueueElem
+ *     Description: Frees one element of the queue.
+ *     Arguments: elem - the elem to free.
+ *     Returns: none
+ */
+
+void
+FreeQueueElem(elem)
+struct queue * elem;
+{
+    if (elem->q_data != (char *) NULL) {
+       FreeInfo( (char **) elem->q_data); /* free info fields */
+       free(elem->q_data);             /* free info array itself. */
+    }
+    rmqueue(elem);             /* remove this element from the queue */
+    free(elem);                        /* free its space. */
+}
+
+/*     Function Name: FreeQueue
+ *     Description: Cleans up the queue
+ *     Arguments: elem - any element of the queue.
+ *     Returns: none.
+ */
+
+void
+FreeQueue(elem)
+struct queue * elem;
+{
+    struct queue *temp, *local = QueueTop(elem); 
+
+    while(local != NULL) {
+       temp = local->q_forw;
+       FreeQueueElem(local);
+       local = temp;
+    }
+}
+
+/*     Function Name: QueueCount
+ *     Description: Counts the number of elements in a queue
+ *     Arguments: elem - any element in the queue.
+ *     Returns: none.
+ */
+
+int
+QueueCount(elem)
+struct qelem * elem;
+{
+    int count = 0;
+    elem = QueueTop(elem);
+    while (elem != NULL) {
+       count ++;
+       elem = elem->q_forw;
+    }
+    return(count);
+}
+
+/*     Function Name: QueueTop
+ *     Description: returns a qelem pointer that points to the top of
+ *                   a queue.
+ *     Arguments: elem - any element of a queue.
+ *     Returns: top element of a queue.
+ */
+    
+struct qelem * 
+QueueTop(elem)
+struct qelem * elem;
+{
+    if (elem == NULL)          /* NULL returns NULL.  */
+       return(NULL);
+    while (elem->q_back != NULL) 
+       elem = elem->q_back;
+    return(elem);
+}
+
+/* ARGSUSED */
+int
+StoreInfo(argc, argv, data)
+int argc;
+char ** argv;
+caddr_t data;
+{
+    char ** info = (char **) malloc( MAX_ARGS_SIZE * sizeof(char *) );
+    struct qelem ** old_elem = (struct qelem **) data;
+    struct qelem * new_elem = (struct qelem *) malloc (sizeof (struct qelem));
+    int count;
+
+    for (count = 0; count < argc; count++)
+       info[count] = Strsave(argv[count]);
+    info[count] = NULL;                /* NULL terminate this sucker. */
+
+    if (* old_elem == (struct qelem **) NULL) {         /* first elem. */
+       new_elem->q_data = (char *) info;
+       new_elem->q_forw = new_elem->q_back = (struct qelem *) NULL;
+    }
+    else {                     /* all other elements. */
+       new_elem->q_data = (char *) info;
+       insque(new_elem, *old_elem);
+    }
+
+    *old_elem = new_elem;
+    return(SMS_CONT);
+}
+
+/*     Function Name: CountArgs
+ *     Description:  Retrieve the number of args in a null terminated
+ *                     arglist.
+ *     Arguments: info - the argument list.
+ *     Returns: number if args in the list.
+ */
+
+int
+CountArgs(info);
+char ** info;
+{
+    int number = 0;
+    
+    while (*info != NULL)
+       number++;
+
+    return(number);
+}    
+
+/*     Function Name: Scream
+ *     Description: Bitch Loudly and exit, it is intended as a callback
+ *                   function for queries that should never return a value.
+ *     Arguments: none
+ *     Returns: doesn't exit.
+ */
+
+static int
+Scream()
+{
+    com_err(whoami, status,
+           "\nAn SMS update returned a value -- programmer botch\n");
+    sms_disconnect();
+    exit(1);
+}
+
+/*     Function Name: BoolAnswer
+ *     Description: returns TRUE or FALSE in arg, depending upon
+ *                   the value of the string in argv[0].
+ *     Arguments: argc, argv - argv[0] contains "true" or "false".
+ *     Returns: SMS_CONT.
+ */
+
+/*ARGSUSED*/
+static int 
+BoolAnswer(argc, argv, arg)
+int argc;
+char *argv[];
+caddr_t arg;
+
+{
+    int *result = (int *) arg;
+
+    if (strcmp(argv[0], "true") == 0)
+       *result = TRUE;
+    else 
+       *result = FALSE;
+    return(SMS_CONT);
+}
+
+/*     Function Name: BoolQuery
+ *     Description: This function makes the query, but returns TRUE or FALSE
+ *                   instead of SMS_CONT or SMS_QUIT.
+ *     Arguments: name - name of query
+ *                 argc, argv - args to pass to query.
+ *     Returns: TRUE or FALSE.
+ */
+
+Bool
+BoolQuery(name, argc, argv)
+char *name;
+int argc;
+char *argv[];
+{
+    sms_query(name, argc, argv, BoolAnswer, (caddr_t) & result);
+    return(result);
+}
+
+/*     Function Name: PromptWithDefault
+ *     Description: allows a user to be prompted for input, and given a 
+ *                   default choice.
+ *     Arguments: prompt - the prompt string.
+ *                 buf, buflen - buffer to be returned and its MAX size?
+ *                 default value for the answer.
+ *     Returns: the value returned by prompt_input.
+ */
+
+int
+PromptWithDefault(prompt, buf, buflen, def)
+char *prompt, *buf;
+int buflen;
+char *def;
+{
+    char tmp[BUFSIZ];
+    int ans;
+
+    (void) sprintf(tmp, "%s [%s]: ", prompt, def ? def : "");
+    ans = Prompt_input(tmp, buf, buflen);
+    if (IS_EMPTY(buf))
+       (void) strcpy(buf, def);
+    return(ans);
+}
+
+/*     Function Name: YesNoQuestion
+ *     Description: This prompts the user for the answer to a yes-no or
+ *                   true-false question.
+ *     Arguments: prompt - the prompt for the user.
+ *                 bool_def - the default value either TRUE or FALSE.
+ *     Returns: TRUE or FALSE or -1 on error
+ */
+
+Bool
+YesNoQuestion(prompt, bool_def)
+char *prompt;
+int bool_def;
+{
+    char ans;
+
+    while (TRUE) {
+       if (!PromptWithDefault(prompt, &ans, 1, bool_def ? "y" : "n"))
+           return(-1);
+       switch (ans) {
+       case 'n':
+       case 'N':
+           return(FALSE);
+           break;
+       case 'y':
+       case 'Y':
+           return(TRUE);
+           break;
+       default:
+           Put_message("Please answer 'y' or 'n'.");
+           break;
+       }
+    }
+}
+/*     Function Name: YesNoQuitQuestion
+ *     Description: This prompts the user for the answer to a yes-no or
+ *                   true-false question, with a quit option.
+ *     Arguments: prompt - the prompt for the user.
+ *                 bool_def - the default value either TRUE or FALSE.
+ *     Returns: TRUE or FALSE or -1 on error or QUIT
+ *      NOTE: It is not possible to have quit the default, but then I don't
+ *            seem to need this functionality.
+ */
+
+Bool
+YesNoQuestion(prompt, bool_def)
+char *prompt;
+int bool_def;
+{
+    char ans;
+
+    while (TRUE) {
+       if (!PromptWithDefault(prompt, &ans, 1, bool_def ? "y" : "n"))
+           return(-1);
+       switch (ans) {
+       case 'n':
+       case 'N':
+           return(FALSE);
+           break;
+       case 'y':
+       case 'Y':
+           return(TRUE);
+           break;
+       case 'q':
+       case 'Q':
+           return(-1);
+           break;
+       default:
+           Put_message("Please answer 'y', 'n' or 'q'.");
+           break;
+       }
+    }
+}
+
+/*     Function Name: Confirm
+ *     Description:   This function asks the user to confirm the action
+ *                     he is about to take, used for things like deleting.
+ *     Arguments: prompt - the prompt string.
+ *     Returns:   TRUE/FALSE - wether or not the confirmation occured.
+ */
+
+static int
+Confirm(prompt)
+char * prompt;
+{
+  return( ~verbose || YesNoQuestion(prompt,FALSE) );
+}
+
+/*     Function Name: ValidName
+ *     Description: This function checks to see if we have a valid list name.
+ *     Arguments: s - the list name.
+ *     Returns: TRUE if Valid.
+ */
+
+Bool
+ValidName(s)
+    char *s;
+{
+    if (IS_EMPTY(s))
+       Put_message("Please use a non-empty name.");
+    else if (index(s, ' '))
+       Put_message("You cannot use space (' ') in this name.");
+    else
+       return TRUE;
+    return FALSE;
+}
+
+/*     Function Name: ToggleVerboseMode
+ *     Description: This function toggles the verbose mode.
+ *     Arguments: none
+ *     Returns: DM_NORMAL.
+ */
+
+int 
+ToggleVerboseMode()
+{
+
+  if(verbose)
+    Put_message("Delete functions will be silent\n");
+  else {
+    Put_message("Delete functions will first confirm\n");
+
+  verbose ~= verbose;
+
+  return(DM_NORMAL);
+}
+
+/*     Function Name: NullFunc
+ *     Description:  dummy callback routine 
+ *     Arguments: none
+ *     Returns: SMS_CONT
+ */
+
+int
+NullFunc()
+{
+    return(SMS_CONT);
+}
+
+/*     Function Name: SlipInNewName
+ *     Description: Slips the new name into the number 2 slot of a list, and
+ *                   returns a pointer to the new list.
+ *     Arguments: info - list that needs this name slipped into it.
+ *                 name - the name to slip into the list.
+ *     Returns: a pointer to the new list.
+ *      NOTE:  This screws up the numbers if the elements of the array in a
+ *             big way.
+ */
+
+SlipInNewName(info, name);
+char ** info;
+
+char * name;
+{
+    register int i;
+
+    /* This also pushes the NULL down. */
+    for (i = CountArgs(info); i > 1; i--) { 
+       info[i+i] = info[i];
+    }
+    info[1] = Strsave(name);   /* now slip in the name. */
+}
+
+/*     Function Name: FreeAndClear        - I couldn't resist the name.
+ *     Description: Clears pointer and optionially frees it.
+ *     Arguments: pointer - pointer to work with.
+ *                 free - if TRUE then free pointer.
+ *     Returns: none.
+ */
+
+FreeAndClear(pointer, free)
+caddr_t pointer;
+Bool free;
+{
+    if (pointer == NULL)
+       return();
+    else if (free)
+       free(pointer);
+
+    pointer = NULL;
+}
+
+/*     Function Name: GetValueFromUser
+ *     Description: This function gets a value from a user for the field
+ *                   specified.
+ *     Arguments: prompt - prompt for user.
+ *                 pointer - pointer to default value, will be returned
+ *                          as new value.
+ *     Returns: none.
+ */
+
+void
+GetValueFromUser(prompt, pointer)
+char * prompt, * pointer;
+{
+    char buf[BUFSIZ];
+
+    PromptWithDefault(prompt, buf, BUFSIZ, pointer);
+    if ( pointer != NULL)
+       free(pointer);
+    pointer = Strsave(buf);
+}
+
+/*     Function Name: CanonicalizeHostname
+ *     Description: This function takes a machine name and canonicalize's it.
+ *     Arguments: machine - name of the machine to work on.
+ *     Returns: new name or NULL if nameserver returns error
+ */
+
+char *
+CanonicalizeHostname(machine)
+char *machine;
+{
+    struct hostent *hostinfo;
+
+    hostinfo = gethostbyname(machine);
+    if (hostinfo != (struct hostent *) NULL)
+       machine = hostinfo->h_name;
+    else                       
+/*
+ *  gethostbyname failed.  This should be very rare, since we're
+ *  dealing with local hosts, so no fancy error recovery. 
+ */
+       machine = (char *) NULL;
+    return (machine);
+}
+
+/*     Function Name: Strsave
+ *     Description: save a string.
+ *     Arguments: string  - the string to save.
+ *     Returns: The malloced string, now safely saved, or NULL.
+ */
+
+char *
+Strsave(str)
+char *str;
+{
+    register char *newstr = malloc((unsigned) strlen(str) + 1);
+
+    if (newstr == (char *) NULL)
+       return ((char *) NULL);
+    else
+       return (strcpy(newstr, str));
+}
+
+/*     Function Name: EncryptMITID
+ *     Description: Encrypts an mit ID number. 
+ *     Arguments: sbuf - the buffer to return the encrypted number in.
+ *                 idnumber - the id number (string).
+ *                 first, last - name of the person.
+ *     Returns: none.
+ */
+
+void
+EncryptMITID(sbuf, idnumber, first, last)
+char *sbuf, *idnumber, *first, *last;
+{
+    char salt[3];
+    extern char *crypt();
+
+#define _tolower(c) ((c)|0x60)
+
+    salt[0] = _tolower(last[0]);
+    salt[1] = _tolower(first[0]);
+    salt[2] = 0;
+
+    (void) strcpy(sbuf, crypt(&idnumber[2], salt));
+}
+
+/*     Function Name: RemoveHyphens
+ *     Description: Removes all hyphens from the string passed to it.
+ *     Arguments: str - the string to remove the hyphes from
+ *     Returns: none
+ */
+
+void
+RemoveHyphens(str)
+char *str;
+{
+    char *hyphen;
+
+    while ((hyphen = index(str, '-')) != NULL)
+       (void) strcpy(hyphen, hyphen + 1);
+}
+
+/*     Function Name: Print
+ *     Description: prints out all the arguments on a single line.
+ *     Arguments: argc, argv - the standard SMS arguments.
+ *                 callback - the callback function - NOT USED.
+ *     Returns: SMS_CONT
+ */
+
+/* ARGSUSED */
+int
+Print(argc, argv, callback)
+int argc;
+char **argv, *callback;
+{
+    char buf[BUFSIZ];
+
+    found_some = TRUE;
+    (void) strcpy(buf,argv[0]);        /* no newline 'cause Put_message adds one */
+    for (i = 1; i < argc; i++)
+       (void) sprintf(buf,"%s %s",buf,argv[i]);
+    (void) Put_message(buf);
+
+    return (SMS_CONT);
+}
+
+/*     Function Name: PrintByType
+ *     Description: This function prints all members of the type specified
+ *                   by the callback arg, unless the callback is NULL, in which
+ *                   case it prints all members.
+ *     Arguments: argc, argc - normal arguments for sms_callback function. 
+ *                 callback - either a type of member or NULL.
+ *     Returns: SMS_CONT or SMS_QUIT.
+ */
+
+/*ARGSUSED*/
+int
+PrintByType(argc, argv, callback)
+int argc;
+char **argv, *callback;
+{
+    if (callback == NULL)
+       return( Print(argc, argv, callback) );
+    if (strcmp(argv[0], callback) == 0) 
+       return( Print(1, argv + 1, callback) );
+    return(SMS_CONT);
+}
+
+/*     Function Name: PrintHelp
+ *     Description: Prints Help Information in a NULL terminated
+ *                   char **.
+ *     Arguments: message.
+ *     Returns: DM_NORMAL.
+ */
+
+int
+PrintHelp(message);
+char ** message;
+{
+    Print(CountArgs(message), message, (char *) NULL);
+    return(DM_NORMAL);
+}
+
+/*
+ * 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:
+ */
diff --git a/include/moira_site.h b/include/moira_site.h
new file mode 100644 (file)
index 0000000..39c9ff5
--- /dev/null
@@ -0,0 +1,149 @@
+/*     This is the file infodefs.h for allmaint, the SMS client that allows
+ *      a user to maintaint most important parts of the SMS database.
+ *     It Contains: Definitions
+ *     
+ *     Created:        6/8/88
+ *     By:             Chris D. Peterson
+ *
+ *      $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
+ */
+
+/*
+ *     This file contains all the definitions that allow easy access to 
+ * elements returned by most of the SMS queries that return information.
+ *
+ *     If order of the arguments in the SMS queries change (again) then all
+ * that need to be changed is the values of these items and all
+ * should be well.
+ *
+ *                                 Chris D. Peterson - kit@athena
+ *                                   6/8/88
+ */
+
+#ifndef _infodefs_
+#define _infodefs_
+
+#include "mit-copyright.h"
+
+
+/* Machine information queries */
+
+#define M_NAME       0
+#define M_TYPE       1
+#define M_MODTIME    2
+#define M_MODBY      3
+#define M_MODWITH    4
+#define M_END        5
+
+/*  Machine to Cluster mapping */
+
+#define MAP_MACHINE  0
+#define MAP_CLUSTER  1
+#define MAP_END      2
+
+/* Cluster information queries */
+
+#define C_NAME       0
+#define C_DESCRIPT   1
+#define C_LOCATION   2
+#define C_MODTIME    3
+#define C_MODBY      4
+#define C_MODWITH    5
+#define C_END        6
+
+/* Cluster Data information queries */
+
+#define CD_NAME      0
+#define CD_LABEL     1
+#define CD_DATA      2
+#define CD_END       3
+
+/* General List information Queries. */
+
+#define L_NAME     0
+#define L_ACTIVE   1
+#define L_PUBLIC   2
+#define L_HIDDEN   3
+#define L_MAILLIST 4
+#define L_GROUP    5
+#define L_GID      6
+#define L_ACL_TYPE 7
+#define L_ACL_NAME 8
+#define L_DESC     9
+#define L_MODTIME  10
+#define L_MODWHO   11
+#define L_MODWITH  12
+#define L_END      13
+
+/* Get List Of Member queries. */
+
+#define GLOM_NAME     0
+#define GLOM_ACTIVE   1
+#define GLOM_PUBLIC   2
+#define GLOM_HIDDEN   3
+#define GLOM_MAILLIST 4
+#define GLOM_GROUP    5
+#define GLOM_END         6
+
+/* List Member information queries. */
+
+#define LM_LIST   0
+#define LM_TYPE   1
+#define LM_MEMBER 2
+#define LM_END    3
+#define LM_END     4
+
+/*  NFS phys. queries. */
+
+#define NFS_NAME    0
+#define NFS_DIR     1
+#define NFS_DEVICE  2
+#define NFS_STATUS  3
+#define NFS_ALLOC   4
+#define NFS_SIZE    5
+#define NFS_MODTIME 6
+#define NFS_MODBY   7
+#define NFS_MODWITH 8
+#define NFS_END     9
+
+/* Quota queries */
+
+#define Q_MACHINE 0 
+#define Q_DEVICE  1
+#define Q_QUOTA   2
+#define Q_END     3
+
+/* PO box infomarion queries */
+
+#define PO_NAME    0
+#define PO_TYPE    1
+#define PO_MACHINE 2
+#define PO_BOX     3
+#define PO_END     4
+
+/* User Information queries */
+
+#define U_NAME    0
+#define U_NEWNAME 1
+#define U_UID     2
+#define U_SHELL   3
+#define U_LAST    4
+#define U_FIRST   5
+#define U_MIDDLE  6
+#define U_STATE   7  
+#define U_MITID   8
+#define U_CLASS   9
+#define U_MODTIME 10
+#define U_MODBY   11
+#define U_MODWITH 12
+#define U_END     13
+
+#endif _infodefs_              /* Do not add anything after this line. */
+
This page took 0.272264 seconds and 5 git commands to generate.