]> andersk Git - moira.git/blame - clients/moira/utils.c
use different top level menus depending on argv[0]
[moira.git] / clients / moira / utils.c
CommitLineData
402461ad 1#if (!defined(lint) && !defined(SABER))
08345b74 2 static char rcsid_module_c[] = "$Header$";
3#endif lint
4
0a2c64cb 5/* This is the file utils.c for the SMS Client, which allows a nieve
6 * user to quickly and easily maintain most parts of the SMS database.
7 * It Contains: Many useful utility functions.
08345b74 8 *
9 * Created: 4/25/88
10 * By: Chris D. Peterson
11 *
12 * $Source$
13 * $Author$
14 * $Header$
15 *
0a2c64cb 16 * Copyright 1988 by the Massachusetts Institute of Technology.
08345b74 17 *
18 * For further information on copyright and distribution
19 * see the file mit-copyright.h
20 */
21
08345b74 22#include <stdio.h>
23#include <strings.h>
24#include <sms.h>
25#include <menu.h>
26
27#include "mit-copyright.h"
0a2c64cb 28#include "defs.h"
29#include "f_defs.h"
08345b74 30#include "globals.h"
31#include "infodefs.h"
32
33#include <netdb.h> /* for gethostbyname. */
08345b74 34
0a2c64cb 35/* Function Name: AddQueue
36 * Description: Adds an element to a queue
37 * Arguments: elem, pred - element and its predecessor.
38 * Returns: none.
39 */
40
41static void
42AddQueue(elem, pred)
43struct qelem * elem, *pred;
44{
45 if (pred == NULL) {
46 elem->q_forw = NULL;
47 elem->q_back = NULL;
48 return;
49 }
50 elem->q_back = pred;
51 elem->q_forw = pred->q_forw;
52 pred->q_forw = elem;
53}
54
55/* Function Name: RemoveQueue
56 * Description: removes an element from a queue.
57 * Arguments: elem.
58 * Returns: none.
59 */
60
61static void
62RemoveQueue(elem)
63struct qelem *elem;
64{
65 if (elem->q_forw != NULL)
66 (elem->q_forw)->q_back = elem->q_back;
67 if (elem->q_back != NULL)
68 (elem->q_back)->q_forw = elem->q_forw;
69}
70
08345b74 71/* Function Name: FreeInfo
72 * Description: Frees all elements of a NULL terminated arrary of char*'s
73 * Arguments: info - array who's elements we are to free.
74 * Returns: none.
75 */
76
77void
78FreeInfo(info)
79char ** info;
80{
85ca828a 81 while (*info != NULL)
82 FreeAndClear(info++, TRUE);
08345b74 83}
84
461c03b6 85/* Function Name: FreeAndClear - I couldn't resist the name.
86 * Description: Clears pointer and optionially frees it.
87 * Arguments: pointer - pointer to work with.
88 * free_it - if TRUE then free pointer.
89 * Returns: none.
90 */
91
92void
93FreeAndClear(pointer, free_it)
94char ** pointer;
95Bool free_it;
96{
97 if (*pointer == NULL)
98 return;
99 else if (free_it)
100 free(*pointer);
101 *pointer = NULL;
102}
103
104/* Function Name: QueueTop
105 * Description: returns a qelem pointer that points to the top of
106 * a queue.
107 * Arguments: elem - any element of a queue.
108 * Returns: top element of a queue.
109 */
110
111struct qelem *
112QueueTop(elem)
113struct qelem * elem;
114{
115 if (elem == NULL) /* NULL returns NULL. */
116 return(NULL);
117 while (elem->q_back != NULL)
118 elem = elem->q_back;
119 return(elem);
120}
121
08345b74 122/* Function Name: FreeQueueElem
123 * Description: Frees one element of the queue.
124 * Arguments: elem - the elem to free.
125 * Returns: none
126 */
127
0a2c64cb 128static void
08345b74 129FreeQueueElem(elem)
461c03b6 130struct qelem * elem;
08345b74 131{
461c03b6 132 char ** info = (char **) elem->q_data;
133
134 if (info != (char **) NULL) {
135 FreeInfo( info ); /* free info fields */
08345b74 136 free(elem->q_data); /* free info array itself. */
137 }
85ca828a 138 RemoveQueue(elem); /* remove this element from the queue */
08345b74 139 free(elem); /* free its space. */
140}
141
142/* Function Name: FreeQueue
143 * Description: Cleans up the queue
144 * Arguments: elem - any element of the queue.
145 * Returns: none.
146 */
147
148void
149FreeQueue(elem)
461c03b6 150struct qelem * elem;
08345b74 151{
461c03b6 152 struct qelem *temp, *local = QueueTop(elem);
08345b74 153
154 while(local != NULL) {
155 temp = local->q_forw;
156 FreeQueueElem(local);
157 local = temp;
158 }
159}
160
161/* Function Name: QueueCount
162 * Description: Counts the number of elements in a queue
163 * Arguments: elem - any element in the queue.
164 * Returns: none.
165 */
166
167int
168QueueCount(elem)
169struct qelem * elem;
170{
171 int count = 0;
172 elem = QueueTop(elem);
173 while (elem != NULL) {
174 count ++;
175 elem = elem->q_forw;
176 }
177 return(count);
178}
179
0a2c64cb 180/* Function Name: StoreInfo
181 * Description: Stores information from an sms query into a queue.
182 * Arguments: argc, argv, - information returned from the query returned
183 * in argv.
184 * data - the previous element on the queue, this data will be
185 * stored in a qelem struct immediatly after this elem.
186 * If NULL then a new queue will be created. This value
187 * is updated to the current element at the end off the
188 * call.
189 * Returns: SMS_CONT, or SMS_ABORT if it has problems.
190 */
191
08345b74 192int
193StoreInfo(argc, argv, data)
194int argc;
195char ** argv;
461c03b6 196char * data;
08345b74 197{
402461ad 198 char ** info = (char **) malloc( MAX_ARGS_SIZE * sizeof(char *));
08345b74 199 struct qelem ** old_elem = (struct qelem **) data;
200 struct qelem * new_elem = (struct qelem *) malloc (sizeof (struct qelem));
201 int count;
202
402461ad 203 if ( (new_elem == (struct qelem *) NULL) || (info == (char **) NULL) ) {
204 Put_message("Could Not allocate more memory.");
205 FreeQueue(*old_elem);
206 *old_elem = (struct qelem *) NULL;
207 return(SMS_ABORT);
208 }
209
08345b74 210 for (count = 0; count < argc; count++)
211 info[count] = Strsave(argv[count]);
212 info[count] = NULL; /* NULL terminate this sucker. */
213
85ca828a 214 new_elem->q_data = (char *) info;
215 AddQueue(new_elem, *old_elem);
08345b74 216
217 *old_elem = new_elem;
218 return(SMS_CONT);
219}
220
221/* Function Name: CountArgs
222 * Description: Retrieve the number of args in a null terminated
223 * arglist.
224 * Arguments: info - the argument list.
225 * Returns: number if args in the list.
226 */
227
228int
461c03b6 229CountArgs(info)
08345b74 230char ** info;
231{
232 int number = 0;
233
461c03b6 234 while (*info != NULL) {
08345b74 235 number++;
461c03b6 236 info++;
237 }
08345b74 238
239 return(number);
240}
241
242/* Function Name: Scream
243 * Description: Bitch Loudly and exit, it is intended as a callback
244 * function for queries that should never return a value.
245 * Arguments: none
246 * Returns: doesn't exit.
247 */
248
461c03b6 249int
08345b74 250Scream()
251{
461c03b6 252 com_err(program_name, 0,
08345b74 253 "\nAn SMS update returned a value -- programmer botch\n");
254 sms_disconnect();
255 exit(1);
256}
257
08345b74 258/* Function Name: PromptWithDefault
259 * Description: allows a user to be prompted for input, and given a
260 * default choice.
261 * Arguments: prompt - the prompt string.
262 * buf, buflen - buffer to be returned and its MAX size?
263 * default value for the answer.
264 * Returns: the value returned by prompt_input.
265 */
266
267int
268PromptWithDefault(prompt, buf, buflen, def)
269char *prompt, *buf;
270int buflen;
271char *def;
272{
273 char tmp[BUFSIZ];
274 int ans;
275
276 (void) sprintf(tmp, "%s [%s]: ", prompt, def ? def : "");
277 ans = Prompt_input(tmp, buf, buflen);
278 if (IS_EMPTY(buf))
279 (void) strcpy(buf, def);
280 return(ans);
281}
282
283/* Function Name: YesNoQuestion
284 * Description: This prompts the user for the answer to a yes-no or
285 * true-false question.
286 * Arguments: prompt - the prompt for the user.
287 * bool_def - the default value either TRUE or FALSE.
288 * Returns: TRUE or FALSE or -1 on error
289 */
290
291Bool
292YesNoQuestion(prompt, bool_def)
293char *prompt;
294int bool_def;
295{
3c1a8806 296 char ans[2];
08345b74 297
298 while (TRUE) {
3c1a8806 299 if (!PromptWithDefault(prompt, ans, 2, bool_def ? "y" : "n"))
08345b74 300 return(-1);
3c1a8806 301 switch (ans[0]) {
08345b74 302 case 'n':
303 case 'N':
304 return(FALSE);
08345b74 305 case 'y':
306 case 'Y':
307 return(TRUE);
08345b74 308 default:
309 Put_message("Please answer 'y' or 'n'.");
310 break;
311 }
312 }
313}
314/* Function Name: YesNoQuitQuestion
315 * Description: This prompts the user for the answer to a yes-no or
316 * true-false question, with a quit option.
317 * Arguments: prompt - the prompt for the user.
318 * bool_def - the default value either TRUE or FALSE.
319 * Returns: TRUE or FALSE or -1 on error or QUIT
320 * NOTE: It is not possible to have quit the default, but then I don't
321 * seem to need this functionality.
322 */
323
324Bool
461c03b6 325YesNoQuitQuestion(prompt, bool_def)
08345b74 326char *prompt;
327int bool_def;
328{
3c1a8806 329 char ans[2];
08345b74 330
331 while (TRUE) {
3c1a8806 332 if (!PromptWithDefault(prompt, ans, 2, bool_def ? "y" : "n"))
08345b74 333 return(-1);
3c1a8806 334 switch (ans[0]) {
08345b74 335 case 'n':
336 case 'N':
337 return(FALSE);
08345b74 338 case 'y':
339 case 'Y':
340 return(TRUE);
08345b74 341 case 'q':
342 case 'Q':
343 return(-1);
08345b74 344 default:
345 Put_message("Please answer 'y', 'n' or 'q'.");
346 break;
347 }
348 }
349}
350
351/* Function Name: Confirm
352 * Description: This function asks the user to confirm the action
353 * he is about to take, used for things like deleting.
354 * Arguments: prompt - the prompt string.
355 * Returns: TRUE/FALSE - wether or not the confirmation occured.
356 */
357
0a2c64cb 358Bool
08345b74 359Confirm(prompt)
360char * prompt;
361{
0a2c64cb 362 return( !verbose || (YesNoQuestion(prompt,FALSE) == TRUE) );
08345b74 363}
364
365/* Function Name: ValidName
366 * Description: This function checks to see if we have a valid list name.
367 * Arguments: s - the list name.
368 * Returns: TRUE if Valid.
369 */
370
371Bool
372ValidName(s)
0a2c64cb 373char *s;
08345b74 374{
375 if (IS_EMPTY(s))
376 Put_message("Please use a non-empty name.");
377 else if (index(s, ' '))
378 Put_message("You cannot use space (' ') in this name.");
402461ad 379 else if (index(s, WILDCARD))
380 Put_message("Wildcards not accepted here.");
08345b74 381 else
382 return TRUE;
383 return FALSE;
384}
385
386/* Function Name: ToggleVerboseMode
387 * Description: This function toggles the verbose mode.
388 * Arguments: none
389 * Returns: DM_NORMAL.
390 */
391
392int
393ToggleVerboseMode()
394{
395
85ca828a 396 verbose = !verbose;
08345b74 397
461c03b6 398 if (verbose)
399 Put_message("Delete functions will first confirm\n");
400 else
401 Put_message("Delete functions will be silent\n");
402
08345b74 403 return(DM_NORMAL);
404}
405
406/* Function Name: NullFunc
407 * Description: dummy callback routine
408 * Arguments: none
409 * Returns: SMS_CONT
410 */
411
412int
413NullFunc()
414{
415 return(SMS_CONT);
416}
417
418/* Function Name: SlipInNewName
419 * Description: Slips the new name into the number 2 slot of a list, and
420 * returns a pointer to the new list.
421 * Arguments: info - list that needs this name slipped into it.
422 * name - the name to slip into the list.
423 * Returns: a pointer to the new list.
85ca828a 424 * NOTE: This screws up the numbers of the elements of the array in a
08345b74 425 * big way.
426 */
427
0a2c64cb 428void
461c03b6 429SlipInNewName(info, name)
08345b74 430char ** info;
08345b74 431char * name;
432{
433 register int i;
434
435 /* This also pushes the NULL down. */
436 for (i = CountArgs(info); i > 1; i--) {
85ca828a 437 info[i] = info[i-1];
08345b74 438 }
85ca828a 439 info[1] = name; /* now slip in the name. */
08345b74 440}
441
08345b74 442/* Function Name: GetValueFromUser
443 * Description: This function gets a value from a user for the field
444 * specified.
445 * Arguments: prompt - prompt for user.
446 * pointer - pointer to default value, will be returned
447 * as new value.
075fe5bb 448 * Returns: SUB_ERROR if break hit (^C).
08345b74 449 */
450
075fe5bb 451int
08345b74 452GetValueFromUser(prompt, pointer)
461c03b6 453char * prompt, ** pointer;
08345b74 454{
455 char buf[BUFSIZ];
456
075fe5bb 457 if (PromptWithDefault(prompt, buf, BUFSIZ, *pointer) == -1)
0a2c64cb 458 return(SUB_ERROR);
075fe5bb 459
0a2c64cb 460/*
461 * If these are the same then there is no need to allocate a new string.
462 *
463 * a difference that makes no difference, IS no difference.
464 */
465
466 if (strcmp(buf, *pointer) != 0) {
467 if (*pointer != NULL)
468 free(*pointer);
469 *pointer = Strsave(buf);
470 }
471 return(SUB_NORMAL);
075fe5bb 472}
473
474/* Function Name: GetYesNoValueFromUser
475 * Description: This function gets a value from a user for the field
476 * specified.
477 * Arguments: prompt - prompt for user.
478 * pointer - pointer to default value, will be returned
479 * as new value.
480 * Returns: SUB_ERROR if break hit (^C).
481 */
482
483int
484GetYesNoValueFromUser(prompt, pointer)
485char * prompt, ** pointer;
486{
487 char user_prompt[BUFSIZ];
488 Bool default_val;
489
490 if ( strcmp (*pointer, DEFAULT_YES) == 0 )
491 default_val = TRUE;
492 else
493 default_val = FALSE;
494
495 sprintf(user_prompt, "%s (y/n)", prompt);
496
497 switch (YesNoQuestion(user_prompt, default_val)) {
498 case TRUE:
499 if (*pointer != NULL)
500 free(*pointer);
0a2c64cb 501 *pointer = Strsave(DEFAULT_YES);
075fe5bb 502 break;
503 case FALSE:
504 if (*pointer != NULL)
505 free(*pointer);
0a2c64cb 506 *pointer = Strsave(DEFAULT_NO);
075fe5bb 507 break;
508 case -1:
509 default:
0a2c64cb 510 return(SUB_ERROR);
075fe5bb 511 }
0a2c64cb 512 return(SUB_NORMAL);
075fe5bb 513}
514
515/* Function Name: GetFSVal
516 * Description: asks about a specific filesystem value.
517 * Arguments: name - string for this type of filesystem.
518 * mask - mask for this type of filesystem.
519 * current - current filesystem state. (for defaults).
520 * new - new filesystem state.
521 * Returns: TRUE if successful.
522 */
523
524static Bool
525GetFSVal(name, mask, current, new)
526char * name;
527int mask, current, *new;
528{
529 char temp_buf[BUFSIZ];
530 sprintf(temp_buf, "Is this a %s filsystem", name);
531 switch (YesNoQuestion(temp_buf, ( (mask & current) == mask) )) {
532 case TRUE:
533 *new |= mask;
534 break;
535 case FALSE:
536 break; /* zero by default. */
537 default:
538 return(FALSE);
539 }
540 return(TRUE);
541}
542
543/* Function Name: GetFSTypes
544 * Description: Allows user to specify filsystem types.
545 * Arguments: current - current value of filsystem, freed here.
546 * Returns: SUB_ERROR on ^C.
547 */
548
549int
550GetFSTypes(current)
551char ** current;
552{
553 int c_value, new_val = 0; /* current value of filesys type (int). */
554 char ret_value[BUFSIZ];
555
556 if (*current == NULL)
557 c_value = 0;
558 else
559 c_value = atoi(*current);
560
561 if (GetFSVal("student", SMS_FS_STUDENT, c_value, &new_val) == FALSE)
562 return(SUB_ERROR);
563 if (GetFSVal("faculty", SMS_FS_FACULTY, c_value, &new_val) == FALSE)
564 return(SUB_ERROR);
565 if (GetFSVal("staff", SMS_FS_STAFF, c_value, &new_val) == FALSE)
566 return(SUB_ERROR);
567 if (GetFSVal("miscellaneous", SMS_FS_MISC, c_value, &new_val) == FALSE)
568 return(SUB_ERROR);
569
570 FreeAndClear(current, TRUE);
571 sprintf(ret_value, "%d", new_val);
572 *current = Strsave(ret_value);
573 return(SUB_NORMAL);
08345b74 574}
575
576/* Function Name: CanonicalizeHostname
577 * Description: This function takes a machine name and canonicalize's it.
578 * Arguments: machine - name of the machine to work on.
579 * Returns: new name or NULL if nameserver returns error
580 */
581
582char *
583CanonicalizeHostname(machine)
584char *machine;
585{
586 struct hostent *hostinfo;
587
588 hostinfo = gethostbyname(machine);
85ca828a 589/* If this fails then we just return what we were passed. */
08345b74 590 if (hostinfo != (struct hostent *) NULL)
591 machine = hostinfo->h_name;
08345b74 592 return (machine);
593}
594
595/* Function Name: Strsave
596 * Description: save a string.
597 * Arguments: string - the string to save.
598 * Returns: The malloced string, now safely saved, or NULL.
599 */
600
601char *
602Strsave(str)
603char *str;
604{
605 register char *newstr = malloc((unsigned) strlen(str) + 1);
606
607 if (newstr == (char *) NULL)
608 return ((char *) NULL);
609 else
610 return (strcpy(newstr, str));
611}
612
613/* Function Name: EncryptMITID
614 * Description: Encrypts an mit ID number.
615 * Arguments: sbuf - the buffer to return the encrypted number in.
616 * idnumber - the id number (string).
617 * first, last - name of the person.
618 * Returns: none.
619 */
620
621void
622EncryptMITID(sbuf, idnumber, first, last)
623char *sbuf, *idnumber, *first, *last;
624{
625 char salt[3];
626 extern char *crypt();
627
628#define _tolower(c) ((c)|0x60)
629
630 salt[0] = _tolower(last[0]);
631 salt[1] = _tolower(first[0]);
632 salt[2] = 0;
633
634 (void) strcpy(sbuf, crypt(&idnumber[2], salt));
635}
636
637/* Function Name: RemoveHyphens
638 * Description: Removes all hyphens from the string passed to it.
639 * Arguments: str - the string to remove the hyphes from
640 * Returns: none
641 */
642
643void
644RemoveHyphens(str)
645char *str;
646{
647 char *hyphen;
648
649 while ((hyphen = index(str, '-')) != NULL)
650 (void) strcpy(hyphen, hyphen + 1);
651}
652
653/* Function Name: Print
654 * Description: prints out all the arguments on a single line.
655 * Arguments: argc, argv - the standard SMS arguments.
656 * callback - the callback function - NOT USED.
657 * Returns: SMS_CONT
658 */
659
660/* ARGSUSED */
661int
662Print(argc, argv, callback)
663int argc;
664char **argv, *callback;
665{
666 char buf[BUFSIZ];
461c03b6 667 register int i;
08345b74 668
669 found_some = TRUE;
670 (void) strcpy(buf,argv[0]); /* no newline 'cause Put_message adds one */
671 for (i = 1; i < argc; i++)
672 (void) sprintf(buf,"%s %s",buf,argv[i]);
673 (void) Put_message(buf);
674
675 return (SMS_CONT);
676}
677
678/* Function Name: PrintByType
679 * Description: This function prints all members of the type specified
680 * by the callback arg, unless the callback is NULL, in which
681 * case it prints all members.
682 * Arguments: argc, argc - normal arguments for sms_callback function.
683 * callback - either a type of member or NULL.
684 * Returns: SMS_CONT or SMS_QUIT.
685 */
686
687/*ARGSUSED*/
688int
689PrintByType(argc, argv, callback)
690int argc;
691char **argv, *callback;
692{
693 if (callback == NULL)
694 return( Print(argc, argv, callback) );
695 if (strcmp(argv[0], callback) == 0)
0a2c64cb 696 return( Print(argc, argv, callback) );
08345b74 697 return(SMS_CONT);
698}
699
700/* Function Name: PrintHelp
701 * Description: Prints Help Information in a NULL terminated
702 * char **.
703 * Arguments: message.
704 * Returns: DM_NORMAL.
705 */
706
707int
461c03b6 708PrintHelp(message)
08345b74 709char ** message;
710{
711 Print(CountArgs(message), message, (char *) NULL);
712 return(DM_NORMAL);
713}
714
402461ad 715/* Function Name: Loop
716 * Description: This function goes through the entire queue, and
717 * and executes the given function on each element.
718 * Arguments: elem - top element of the queue.
719 * func - the function to execute.
720 * Returns: none.
721 */
722
723void
724Loop(elem, func)
725FVoid func;
726struct qelem * elem;
727{
728 while (elem != NULL) {
729 char ** info = (char **) elem->q_data;
730 (*func) (info);
731 elem = elem->q_forw;
732 }
733}
734
735
736/* Function Name: QueryLoop
737 * Description: This functions loops through a queue containing
738 * information about some item that we want to perform
739 * an operation on, and then calls the correct routine
740 * perform that operation.
741 * Arguments: top - top of the queue of information.
742 * print_func - print function.
743 * op_function - operation to be performed.
744 * query_string - string the prompts the user whether or not
745 * to perform this operation.
746 * Returns: none.
747 * NOTES:
748 * print_opt - should expect one arguent, the info array
749 * of char *'s.
750 * is expected to return the name of the item.
751 * op_func - should expect two arguments.
752 * 1) the info array of char *'s.
753 * 2) a boolean the is true if there only
754 * one item in this queue, used for delete
755 * confirmation.
756 * query_string - this should be of such a form that when the
757 * name of the object and '(y/n/q) ?' are appended
758 * then it should still make sense, an example is
759 * "Delete the list"
760 */
761
762void
763QueryLoop(elem, print_func, op_func, query_string)
764struct qelem *elem;
765FVoid op_func;
766FCharStar print_func;
767char * query_string;
768{
769 Bool one_item;
770 char temp_buf[BUFSIZ], *name;
771
772 one_item = (QueueCount(elem) == 1);
773 while (elem != NULL) {
774 char **info = (char **) elem->q_data;
775
776 if (one_item)
777 (*op_func) (info, one_item);
778 else {
779 name = (*print_func) (info); /* call print function. */
0a2c64cb 780 sprintf(temp_buf,"%s %s (y/n/q)", query_string, name);
402461ad 781 switch(YesNoQuitQuestion(temp_buf, FALSE)) {
782 case TRUE:
783 (*op_func) (info, one_item);
784 break;
785 case FALSE:
786 break;
787 default: /* Quit. */
788 Put_message("Aborting...");
789 return;
790 }
791 }
792 elem = elem->q_forw;
793 }
794}
795
796/* Function Name: NullPrint
797 * Description: print function that returns nothing.
798 * Arguments: info - a pointer to the info array - Not used.
799 * Returns: none.
800 */
801
802char *
803NullPrint(info)
804char ** info;
805{
806 return(info[NAME]);
807}
808
08345b74 809/*
810 * Local Variables:
811 * mode: c
812 * c-indent-level: 4
813 * c-continued-statement-offset: 4
814 * c-brace-offset: -4
815 * c-argdecl-indent: 4
816 * c-label-offset: -4
817 * End:
818 */
This page took 0.290414 seconds and 5 git commands to generate.