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