--- /dev/null
+#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:
+ */
--- /dev/null
+#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:
+ */
+
+
+
--- /dev/null
+#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:
+ */
--- /dev/null
+#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. */
+
--- /dev/null
+/* 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 */
--- /dev/null
+#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, ¤t_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:
+ */
--- /dev/null
+#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);
+}
--- /dev/null
+#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)
+ }
+};
+
--- /dev/null
+#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:
+ */
--- /dev/null
+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:
+ */
--- /dev/null
+#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:
+ */
--- /dev/null
+/* 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. */
+