]> andersk Git - moira.git/blob - clients/moira/utils.c
Initial revision
[moira.git] / clients / moira / utils.c
1 #if (!defined(lint) && !defined(SABER))
2   static char rcsid_module_c[] = "$Header$";
3 #endif lint
4
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.
8  *      
9  *      Created:        4/25/88
10  *      By:             Chris D. Peterson
11  *
12  *      $Source$
13  *      $Author$
14  *      $Header$
15  *      
16  *      Copyright 1988 by the Massachusetts Institute of Technology.
17  *
18  *      For further information on copyright and distribution 
19  *      see the file mit-copyright.h
20  */
21
22 #include <stdio.h>
23 #include <strings.h>
24 #include <sms.h>
25 #include <menu.h>
26
27 #include "mit-copyright.h"
28 #include "defs.h"
29 #include "f_defs.h"
30 #include "globals.h"
31 #include "infodefs.h"
32
33 #include <netdb.h>              /* for gethostbyname. */
34
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
41 static void
42 AddQueue(elem, pred)
43 struct 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
61 static void
62 RemoveQueue(elem)
63 struct 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
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
77 void
78 FreeInfo(info)
79 char ** info;
80 {
81     while (*info != NULL)
82         FreeAndClear(info++, TRUE);
83 }
84
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
92 void
93 FreeAndClear(pointer, free_it)
94 char ** pointer;
95 Bool 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     
111 struct qelem * 
112 QueueTop(elem)
113 struct 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
122 /*      Function Name: FreeQueueElem
123  *      Description: Frees one element of the queue.
124  *      Arguments: elem - the elem to free.
125  *      Returns: none
126  */
127
128 static void
129 FreeQueueElem(elem)
130 struct qelem * elem;
131 {
132     char ** info = (char **) elem->q_data;
133
134     if (info != (char **) NULL) {
135         FreeInfo( info ); /* free info fields */
136         free(elem->q_data);             /* free info array itself. */
137     }
138     RemoveQueue(elem);          /* remove this element from the queue */
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
148 void
149 FreeQueue(elem)
150 struct qelem * elem;
151 {
152     struct qelem *temp, *local = QueueTop(elem); 
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
167 int
168 QueueCount(elem)
169 struct 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
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
192 int
193 StoreInfo(argc, argv, data)
194 int argc;
195 char ** argv;
196 char * data;
197 {
198     char ** info = (char **) malloc( MAX_ARGS_SIZE * sizeof(char *));
199     struct qelem ** old_elem = (struct qelem **) data;
200     struct qelem * new_elem = (struct qelem *) malloc (sizeof (struct qelem));
201     int count;
202
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
210     for (count = 0; count < argc; count++)
211         info[count] = Strsave(argv[count]);
212     info[count] = NULL;         /* NULL terminate this sucker. */
213
214     new_elem->q_data = (char *) info;
215     AddQueue(new_elem, *old_elem);
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
228 int
229 CountArgs(info)
230 char ** info;
231 {
232     int number = 0;
233     
234     while (*info != NULL) {
235         number++;
236         info++;
237     }
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
249 int
250 Scream()
251 {
252     com_err(program_name, 0,
253             "\nAn SMS update returned a value -- programmer botch\n");
254     sms_disconnect();
255     exit(1);
256 }
257
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
267 int
268 PromptWithDefault(prompt, buf, buflen, def)
269 char *prompt, *buf;
270 int buflen;
271 char *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
291 Bool
292 YesNoQuestion(prompt, bool_def)
293 char *prompt;
294 int bool_def;
295 {
296     char ans[2];
297
298     while (TRUE) {
299         if (!PromptWithDefault(prompt, ans, 2, bool_def ? "y" : "n"))
300             return(-1);
301         switch (ans[0]) {
302         case 'n':
303         case 'N':
304             return(FALSE);
305         case 'y':
306         case 'Y':
307             return(TRUE);
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
324 Bool
325 YesNoQuitQuestion(prompt, bool_def)
326 char *prompt;
327 int bool_def;
328 {
329     char ans[2];
330
331     while (TRUE) {
332         if (!PromptWithDefault(prompt, ans, 2, bool_def ? "y" : "n"))
333             return(-1);
334         switch (ans[0]) {
335         case 'n':
336         case 'N':
337             return(FALSE);
338         case 'y':
339         case 'Y':
340             return(TRUE);
341         case 'q':
342         case 'Q':
343             return(-1);
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
358 Bool
359 Confirm(prompt)
360 char * prompt;
361 {
362   return( !verbose || (YesNoQuestion(prompt,FALSE) == TRUE) );
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
371 Bool
372 ValidName(s)
373 char *s;
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.");
379     else if (index(s, WILDCARD))
380         Put_message("Wildcards not accepted here.");
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
392 int 
393 ToggleVerboseMode()
394 {
395
396   verbose = !verbose;
397
398   if (verbose)
399     Put_message("Delete functions will first confirm\n");
400   else
401     Put_message("Delete functions will be silent\n");
402     
403   return(DM_NORMAL);
404 }
405
406 /*      Function Name: NullFunc
407  *      Description:  dummy callback routine 
408  *      Arguments: none
409  *      Returns: SMS_CONT
410  */
411
412 int
413 NullFunc()
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.
424  *      NOTE:  This screws up the numbers of the elements of the array in a
425  *             big way.
426  */
427
428 void
429 SlipInNewName(info, name)
430 char ** info;
431 char * name;
432 {
433     register int i;
434
435     /* This also pushes the NULL down. */
436     for (i = CountArgs(info); i > 1; i--) { 
437         info[i] = info[i-1];
438     }
439     info[1] = name;     /* now slip in the name. */
440 }
441
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.
448  *      Returns: SUB_ERROR if break hit (^C).
449  */
450
451 int
452 GetValueFromUser(prompt, pointer)
453 char * prompt, ** pointer;
454 {
455     char buf[BUFSIZ];
456
457     if (PromptWithDefault(prompt, buf, BUFSIZ, *pointer) == -1)
458         return(SUB_ERROR);
459
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);
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
483 int
484 GetYesNoValueFromUser(prompt, pointer)
485 char * 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);
501         *pointer = Strsave(DEFAULT_YES);
502         break;
503     case FALSE:
504         if (*pointer != NULL)
505             free(*pointer);
506         *pointer = Strsave(DEFAULT_NO);
507         break;
508     case -1:
509     default:
510         return(SUB_ERROR);
511     }
512     return(SUB_NORMAL);
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
524 static Bool
525 GetFSVal(name, mask, current, new)
526 char * name;
527 int 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
549 int
550 GetFSTypes(current)
551 char **  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);
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
582 char *
583 CanonicalizeHostname(machine)
584 char *machine;
585 {
586     struct hostent *hostinfo;
587
588     hostinfo = gethostbyname(machine);
589 /* If this fails then we just return what we were passed. */
590     if (hostinfo != (struct hostent *) NULL)
591         machine = hostinfo->h_name;
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
601 char *
602 Strsave(str)
603 char *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: Print
614  *      Description: prints out all the arguments on a single line.
615  *      Arguments: argc, argv - the standard SMS arguments.
616  *                 callback - the callback function - NOT USED.
617  *      Returns: SMS_CONT
618  */
619
620 /* ARGSUSED */
621 int
622 Print(argc, argv, callback)
623 int argc;
624 char **argv, *callback;
625 {
626     char buf[BUFSIZ];
627     register int i;
628
629     found_some = TRUE;
630     (void) strcpy(buf,argv[0]); /* no newline 'cause Put_message adds one */
631     for (i = 1; i < argc; i++)
632         (void) sprintf(buf,"%s %s",buf,argv[i]);
633     (void) Put_message(buf);
634
635     return (SMS_CONT);
636 }
637
638 /*      Function Name: PrintByType
639  *      Description: This function prints all members of the type specified
640  *                   by the callback arg, unless the callback is NULL, in which
641  *                   case it prints all members.
642  *      Arguments: argc, argc - normal arguments for sms_callback function. 
643  *                 callback - either a type of member or NULL.
644  *      Returns: SMS_CONT or SMS_QUIT.
645  */
646
647 /*ARGSUSED*/
648 int
649 PrintByType(argc, argv, callback)
650 int argc;
651 char **argv, *callback;
652 {
653     if (callback == NULL)
654         return( Print(argc, argv, callback) );
655     if (strcmp(argv[0], callback) == 0) 
656         return( Print(argc, argv, callback) );
657     return(SMS_CONT);
658 }
659
660 /*      Function Name: PrintHelp
661  *      Description: Prints Help Information in a NULL terminated
662  *                   char **.
663  *      Arguments: message.
664  *      Returns: DM_NORMAL.
665  */
666
667 int
668 PrintHelp(message)
669 char ** message;
670 {
671     Print(CountArgs(message), message, (char *) NULL);
672     return(DM_NORMAL);
673 }
674
675 /*      Function Name: Loop
676  *      Description: This function goes through the entire queue, and
677  *                   and executes the given function on each element.
678  *      Arguments: elem - top element of the queue.
679  *                 func - the function to execute.
680  *      Returns: none.
681  */
682
683 void
684 Loop(elem, func)
685 FVoid func;
686 struct qelem * elem;
687 {
688     while (elem != NULL) {
689         char ** info = (char **) elem->q_data;
690         (*func) (info);
691         elem = elem->q_forw;
692     }
693 }
694
695
696 /*      Function Name: QueryLoop
697  *      Description: This functions loops through a queue containing
698  *                   information about some item that we want to perform
699  *                   an operation on, and then calls the correct routine
700  *                   perform that operation.
701  *      Arguments: top - top of the queue of information.
702  *                 print_func - print function.
703  *                 op_function - operation to be performed.
704  *                 query_string - string the prompts the user whether or not
705  *                                to perform this operation.
706  *      Returns: none.
707  *      NOTES:
708  *               print_opt - should expect one arguent, the info array
709  *                           of char *'s.
710  *                           is expected to return the name of the item.
711  *               op_func   - should expect two arguments.
712  *                           1) the info array of char *'s.
713  *                           2) a boolean the is true if there only
714  *                              one item in this queue, used for delete
715  *                              confirmation.
716  *               query_string - this should be of such a form that when the
717  *                              name of the object and '(y/n/q) ?' are appended
718  *                              then it should still make sense, an example is
719  *                              "Delete the list"
720  */
721
722 void
723 QueryLoop(elem, print_func, op_func, query_string)
724 struct qelem *elem;
725 FVoid op_func;
726 FCharStar print_func;
727 char * query_string;
728 {
729     Bool one_item;
730     char temp_buf[BUFSIZ], *name;
731
732     one_item = (QueueCount(elem) == 1);
733     while (elem != NULL) {
734         char **info = (char **) elem->q_data;
735         
736         if (one_item)
737             (*op_func) (info, one_item);
738         else {
739             name = (*print_func) (info); /* call print function. */
740             sprintf(temp_buf,"%s %s (y/n/q)", query_string, name);
741             switch(YesNoQuitQuestion(temp_buf, FALSE)) {
742             case TRUE:
743                 (*op_func) (info, one_item);
744                 break;
745             case FALSE:
746                 break;
747             default:            /* Quit. */
748                 Put_message("Aborting...");
749                 return;
750             }
751         }
752         elem = elem->q_forw;
753     }
754 }
755
756 /*      Function Name: NullPrint
757  *      Description: print function that returns nothing.
758  *      Arguments: info - a pointer to the info array - Not used.
759  *      Returns: none.
760  */
761
762 char *
763 NullPrint(info)
764 char ** info;
765 {
766     return(info[NAME]);
767 }
768
769 /*
770  * Local Variables:
771  * mode: c
772  * c-indent-level: 4
773  * c-continued-statement-offset: 4
774  * c-brace-offset: -4
775  * c-argdecl-indent: 4
776  * c-label-offset: -4
777  * End:
778  */
This page took 0.093088 seconds and 5 git commands to generate.