-#ifndef lint
+#if (!defined(lint) && !defined(SABER))
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.
+/* This is the file utils.c for the SMS Client, which allows a nieve
+ * user to quickly and easily maintain most parts of the SMS database.
+ * It Contains: Many useful utility functions.
*
* Created: 4/25/88
* By: Chris D. Peterson
* $Author$
* $Header$
*
- * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
+ * Copyright 1988 by the Massachusetts Institute of Technology.
*
* For further information on copyright and distribution
* see the file mit-copyright.h
*/
-
#include <stdio.h>
#include <strings.h>
#include <sms.h>
#include <menu.h>
+#include <ctype.h>
#include "mit-copyright.h"
-#include "allmaint.h"
-#include "allmaint_funcs.h"
+#include "defs.h"
+#include "f_defs.h"
#include "globals.h"
#include "infodefs.h"
#include <netdb.h> /* for gethostbyname. */
-/* #include <ctype.h> */
-/* #include <varargs.h> */
-/* #include <sys/types.h> */
+
+/* Function Name: AddQueue
+ * Description: Adds an element to a queue
+ * Arguments: elem, pred - element and its predecessor.
+ * Returns: none.
+ */
+
+static void
+AddQueue(elem, pred)
+struct qelem * elem, *pred;
+{
+ if (pred == NULL) {
+ elem->q_forw = NULL;
+ elem->q_back = NULL;
+ return;
+ }
+ elem->q_back = pred;
+ elem->q_forw = pred->q_forw;
+ pred->q_forw = elem;
+}
+
+/* Function Name: RemoveQueue
+ * Description: removes an element from a queue.
+ * Arguments: elem.
+ * Returns: none.
+ */
+
+static void
+RemoveQueue(elem)
+struct qelem *elem;
+{
+ if (elem->q_forw != NULL)
+ (elem->q_forw)->q_back = elem->q_back;
+ if (elem->q_back != NULL)
+ (elem->q_back)->q_forw = elem->q_forw;
+}
/* Function Name: FreeInfo
* Description: Frees all elements of a NULL terminated arrary of char*'s
* Returns: none
*/
-void
+static void
FreeQueueElem(elem)
struct qelem * elem;
{
}
}
-/* Function Name: AddQueue
- * Description: Adds an element to a queue
- * Arguments: elem, pred - element and its predecessor.
- * Returns: none.
- */
-
-AddQueue(elem, pred)
-struct qelem * elem, *pred;
-{
- if (pred == NULL) {
- elem->q_forw = NULL;
- elem->q_back = NULL;
- return;
- }
- elem->q_back = pred;
- elem->q_forw = pred->q_forw;
- pred->q_forw = elem;
-}
-
-/* Function Name: RemoveQueue
- * Description: removes an element from a queue.
- * Arguments: elem.
- * Returns: none.
- */
-
-RemoveQueue(elem)
-struct qelem *elem;
-{
- if (elem->q_forw != NULL)
- (elem->q_forw)->q_back = elem->q_back;
- if (elem->q_back != NULL)
- (elem->q_back)->q_forw = elem->q_forw;
-}
-
/* Function Name: QueueCount
* Description: Counts the number of elements in a queue
* Arguments: elem - any element in the queue.
return(count);
}
+/* Function Name: StoreInfo
+ * Description: Stores information from an sms query into a queue.
+ * Arguments: argc, argv, - information returned from the query returned
+ * in argv.
+ * data - the previous element on the queue, this data will be
+ * stored in a qelem struct immediatly after this elem.
+ * If NULL then a new queue will be created. This value
+ * is updated to the current element at the end off the
+ * call.
+ * Returns: SMS_CONT, or SMS_ABORT if it has problems.
+ */
+
int
StoreInfo(argc, argv, data)
int argc;
char ** argv;
char * data;
{
- char ** info = (char **) malloc( MAX_ARGS_SIZE * sizeof(char *) );
+ 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;
+ if ( (new_elem == (struct qelem *) NULL) || (info == (char **) NULL) ) {
+ Put_message("Could Not allocate more memory.");
+ FreeQueue(*old_elem);
+ *old_elem = (struct qelem *) NULL;
+ return(SMS_ABORT);
+ }
+
for (count = 0; count < argc; count++)
info[count] = Strsave(argv[count]);
info[count] = NULL; /* NULL terminate this sucker. */
(void) sprintf(tmp, "%s [%s]: ", prompt, def ? def : "");
ans = Prompt_input(tmp, buf, buflen);
+ if (ans == 0) {
+ if (YesNoQuestion("Are you sure you want to exit", 1)) {
+ Cleanup_menu();
+ exit(0);
+ }
+ Put_message("Continuing input...");
+ return(PromptWithDefault(prompt, buf, buflen, def));
+ }
if (IS_EMPTY(buf))
(void) strcpy(buf, def);
+ else if (!strcmp(buf, "\"\""))
+ *buf = 0;
return(ans);
}
char *prompt;
int bool_def;
{
- char ans;
+ char ans[2];
while (TRUE) {
- if (!PromptWithDefault(prompt, &ans, 1, bool_def ? "y" : "n"))
+ if (!PromptWithDefault(prompt, ans, 2, bool_def ? "y" : "n"))
return(-1);
- switch (ans) {
+ switch (ans[0]) {
case 'n':
case 'N':
return(FALSE);
char *prompt;
int bool_def;
{
- char ans;
+ char ans[2];
while (TRUE) {
- if (!PromptWithDefault(prompt, &ans, 1, bool_def ? "y" : "n"))
+ if (!PromptWithDefault(prompt, ans, 2, bool_def ? "y" : "n"))
return(-1);
- switch (ans) {
+ switch (ans[0]) {
case 'n':
case 'N':
return(FALSE);
* Returns: TRUE/FALSE - wether or not the confirmation occured.
*/
-int
+Bool
Confirm(prompt)
char * prompt;
{
- return( !verbose || YesNoQuestion(prompt,FALSE) );
+ return( !verbose || (YesNoQuestion(prompt,FALSE) == TRUE) );
}
/* Function Name: ValidName
Bool
ValidName(s)
- char *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 if (index(s, WILDCARD))
+ Put_message("Wildcards not accepted here.");
else
return TRUE;
return FALSE;
* big way.
*/
+void
SlipInNewName(info, name)
char ** info;
char * name;
* Arguments: prompt - prompt for user.
* pointer - pointer to default value, will be returned
* as new value.
- * Returns: none.
+ * Returns: SUB_ERROR if break hit (^C).
*/
-void
+int
GetValueFromUser(prompt, pointer)
char * prompt, ** pointer;
{
char buf[BUFSIZ];
- PromptWithDefault(prompt, buf, BUFSIZ, *pointer);
- if (*pointer != NULL)
- free(*pointer);
- *pointer = Strsave(buf);
+ if (PromptWithDefault(prompt, buf, BUFSIZ, *pointer) == -1)
+ return(SUB_ERROR);
+
+/*
+ * If these are the same then there is no need to allocate a new string.
+ *
+ * a difference that makes no difference, IS no difference.
+ */
+
+ if (strcmp(buf, *pointer) != 0) {
+ if (*pointer != NULL)
+ free(*pointer);
+ *pointer = Strsave(buf);
+ }
+ return(SUB_NORMAL);
+}
+
+/* Function Name: GetYesNoValueFromUser
+ * 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: SUB_ERROR if break hit (^C).
+ */
+
+int
+GetYesNoValueFromUser(prompt, pointer)
+char * prompt, ** pointer;
+{
+ char user_prompt[BUFSIZ];
+ Bool default_val;
+
+ if ( strcmp (*pointer, DEFAULT_YES) == 0 )
+ default_val = TRUE;
+ else
+ default_val = FALSE;
+
+ sprintf(user_prompt, "%s (y/n)", prompt);
+
+ switch (YesNoQuestion(user_prompt, default_val)) {
+ case TRUE:
+ if (*pointer != NULL)
+ free(*pointer);
+ *pointer = Strsave(DEFAULT_YES);
+ break;
+ case FALSE:
+ if (*pointer != NULL)
+ free(*pointer);
+ *pointer = Strsave(DEFAULT_NO);
+ break;
+ case -1:
+ default:
+ return(SUB_ERROR);
+ }
+ return(SUB_NORMAL);
+}
+
+/* Function Name: GetFSVal
+ * Description: asks about a specific filesystem value.
+ * Arguments: name - string for this type of filesystem.
+ * mask - mask for this type of filesystem.
+ * current - current filesystem state. (for defaults).
+ * new - new filesystem state.
+ * Returns: TRUE if successful.
+ */
+
+static Bool
+GetFSVal(name, mask, current, new)
+char * name;
+int mask, current, *new;
+{
+ char temp_buf[BUFSIZ];
+ sprintf(temp_buf, "Is this a %s filsystem", name);
+ switch (YesNoQuestion(temp_buf, ( (mask & current) == mask) )) {
+ case TRUE:
+ *new |= mask;
+ break;
+ case FALSE:
+ break; /* zero by default. */
+ default:
+ return(FALSE);
+ }
+ return(TRUE);
+}
+
+/* Function Name: GetFSTypes
+ * Description: Allows user to specify filsystem types.
+ * Arguments: current - current value of filsystem, freed here.
+ * Returns: SUB_ERROR on ^C.
+ */
+
+int
+GetFSTypes(current)
+char ** current;
+{
+ int c_value, new_val = 0; /* current value of filesys type (int). */
+ char ret_value[BUFSIZ];
+
+ if (*current == NULL)
+ c_value = 0;
+ else
+ c_value = atoi(*current);
+
+ if (GetFSVal("student", SMS_FS_STUDENT, c_value, &new_val) == FALSE)
+ return(SUB_ERROR);
+ if (GetFSVal("faculty", SMS_FS_FACULTY, c_value, &new_val) == FALSE)
+ return(SUB_ERROR);
+ if (GetFSVal("staff", SMS_FS_STAFF, c_value, &new_val) == FALSE)
+ return(SUB_ERROR);
+ if (GetFSVal("miscellaneous", SMS_FS_MISC, c_value, &new_val) == FALSE)
+ return(SUB_ERROR);
+
+ FreeAndClear(current, TRUE);
+ sprintf(ret_value, "%d", new_val);
+ *current = Strsave(ret_value);
+ return(SUB_NORMAL);
}
/* Function Name: CanonicalizeHostname
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.
if (callback == NULL)
return( Print(argc, argv, callback) );
if (strcmp(argv[0], callback) == 0)
- return( Print(1, argv + 1, callback) );
+ return( Print(argc, argv, callback) );
return(SMS_CONT);
}
return(DM_NORMAL);
}
+/* Function Name: Loop
+ * Description: This function goes through the entire queue, and
+ * and executes the given function on each element.
+ * Arguments: elem - top element of the queue.
+ * func - the function to execute.
+ * Returns: none.
+ */
+
+void
+Loop(elem, func)
+FVoid func;
+struct qelem * elem;
+{
+ while (elem != NULL) {
+ char ** info = (char **) elem->q_data;
+ (*func) (info);
+ elem = elem->q_forw;
+ }
+}
+
+
+/* Function Name: QueryLoop
+ * Description: This functions loops through a queue containing
+ * information about some item that we want to perform
+ * an operation on, and then calls the correct routine
+ * perform that operation.
+ * Arguments: top - top of the queue of information.
+ * print_func - print function.
+ * op_function - operation to be performed.
+ * query_string - string the prompts the user whether or not
+ * to perform this operation.
+ * Returns: none.
+ * NOTES:
+ * print_opt - should expect one arguent, the info array
+ * of char *'s.
+ * is expected to return the name of the item.
+ * op_func - should expect two arguments.
+ * 1) the info array of char *'s.
+ * 2) a boolean the is true if there only
+ * one item in this queue, used for delete
+ * confirmation.
+ * query_string - this should be of such a form that when the
+ * name of the object and '(y/n/q) ?' are appended
+ * then it should still make sense, an example is
+ * "Delete the list"
+ */
+
+void
+QueryLoop(elem, print_func, op_func, query_string)
+struct qelem *elem;
+FVoid op_func;
+FCharStar print_func;
+char * query_string;
+{
+ Bool one_item;
+ char temp_buf[BUFSIZ], *name;
+
+ one_item = (QueueCount(elem) == 1);
+ while (elem != NULL) {
+ char **info = (char **) elem->q_data;
+
+ if (one_item)
+ (*op_func) (info, one_item);
+ else {
+ name = (*print_func) (info); /* call print function. */
+ sprintf(temp_buf,"%s %s (y/n/q)", query_string, name);
+ switch(YesNoQuitQuestion(temp_buf, FALSE)) {
+ case TRUE:
+ (*op_func) (info, one_item);
+ break;
+ case FALSE:
+ break;
+ default: /* Quit. */
+ Put_message("Aborting...");
+ return;
+ }
+ }
+ elem = elem->q_forw;
+ }
+}
+
+/* Function Name: NullPrint
+ * Description: print function that returns nothing.
+ * Arguments: info - a pointer to the info array - Not used.
+ * Returns: none.
+ */
+
+char *
+NullPrint(info)
+char ** info;
+{
+ return(info[NAME]);
+}
+
+
+/* Function Name: GetTypeValues
+ * Description: gets legal values for a typed object, keeping a cache
+ * Arguments: type name
+ * Returns: argv of values
+ */
+
+struct qelem *
+GetTypeValues(tname)
+char *tname;
+{
+ int stat;
+ char *argv[3], *p, **pp, *strsave();
+ struct qelem *elem, *oelem;
+ static struct qelem *cache = NULL;
+ struct cache_elem { char *cache_name; struct qelem *cache_data; } *ce;
+
+ for (elem = cache; elem; elem = elem->q_forw) {
+ ce = (struct cache_elem *)elem->q_data;
+ if (!strcmp(ce->cache_name, tname))
+ return(ce->cache_data);
+ }
+
+ argv[0] = tname;
+ argv[1] = "TYPE";
+ argv[2] = "*";
+ elem = NULL;
+ if (stat = sms_query("get_alias", 3, argv, StoreInfo, (char *)&elem)) {
+ com_err(program_name, stat, " in GetTypeValues");
+ return(NULL);
+ }
+ oelem = elem;
+ for (elem = QueueTop(elem); elem; elem = elem->q_forw) {
+ pp = (char **) elem->q_data;
+ p = strsave(pp[2]);
+ FreeInfo(pp);
+ elem->q_data = p;
+ }
+ elem = (struct qelem *) malloc(sizeof(struct qelem));
+ ce = (struct cache_elem *) malloc(sizeof(struct cache_elem));
+ ce->cache_name = tname;
+ ce->cache_data = QueueTop(oelem);
+ elem->q_data = (char *)ce;
+ AddQueue(elem, cache);
+ cache = QueueTop(elem);
+ return(ce->cache_data);
+}
+
+
+/* Function Name: GetTypeFromUser
+ * Description: gets a typed value from the user
+ * Arguments: prompt string, type name, buffer pointer
+ * Returns:
+ */
+
+GetTypeFromUser(prompt, tname, pointer)
+char *prompt;
+char *tname;
+char **pointer;
+{
+ char def[BUFSIZ], buffer[BUFSIZ], *p, *argv[3];
+ struct qelem *elem;
+ int stat;
+
+ strcpy(def, *pointer);
+ strcpy(buffer, prompt);
+ strcat(buffer, " (");
+ for (elem = GetTypeValues(tname); elem; elem = elem->q_forw) {
+ strcat(buffer, elem->q_data);
+ if (elem->q_forw)
+ strcat(buffer, ", ");
+ }
+ strcat(buffer, ")");
+ if (strlen(buffer) > 64)
+ sprintf(buffer, "%s (? for help)", prompt);
+ GetValueFromUser(buffer, pointer);
+ if (**pointer == '?') {
+ sprintf(buffer, "Type %s is one of:", tname);
+ Put_message(buffer);
+ for (elem = GetTypeValues(tname); elem; elem = elem->q_forw) {
+ Put_message(elem->q_data);
+ }
+ *pointer = strsave(def);
+ return(GetTypeFromUser(prompt, tname, pointer));
+ }
+ for (elem = GetTypeValues(tname); elem; elem = elem->q_forw) {
+ if (!cistrcmp(elem->q_data, *pointer))
+ return(SUB_NORMAL);
+ }
+ sprintf(buffer, "\"%s\" is not a legal value for %s. Use one of:",
+ *pointer, tname);
+ Put_message(buffer);
+ for (elem = GetTypeValues(tname); elem; elem = elem->q_forw) {
+ Put_message(elem->q_data);
+ }
+ sprintf(buffer, "Are you sure you want \"%s\" to be a legal %s",
+ *pointer, tname);
+ if (YesNoQuestion("Do you want this to be a new legal value", 0) &&
+ YesNoQuestion(buffer, 0)) {
+ argv[0] = tname;
+ argv[1] = "TYPE";
+ argv[2] = *pointer;
+ for (p = argv[2]; *p; p++)
+ if (islower(*p))
+ *p = toupper(*p);
+ if (stat = sms_query("add_alias", 3, argv, Scream, NULL)) {
+ com_err(program_name, stat, " in add_alias");
+ } else {
+ elem = (struct qelem *) malloc(sizeof(struct qelem));
+ elem->q_data = strsave(*pointer);
+ AddQueue(elem, GetTypeValues(tname));
+ Put_message("Done.");
+ }
+ }
+ *pointer = strsave(def);
+ return(GetTypeFromUser(prompt, tname, pointer));
+}
+
+
/*
* Local Variables:
* mode: c