]> andersk Git - moira.git/blob - clients/moira/utils.c
don't get cluster data for a delete
[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 (ans == 0) {
279         if (YesNoQuestion("Are you sure you want to exit", 1))
280             exit(0);
281         Put_message("Continuing input...");
282         return(PromptWithDefault(prompt, buf, buflen, def));
283     }
284     if (IS_EMPTY(buf))
285         (void) strcpy(buf, def);
286     else if (!strcmp(buf, "\"\""))
287         *buf = 0;
288     return(ans);
289 }
290
291 /*      Function Name: YesNoQuestion
292  *      Description: This prompts the user for the answer to a yes-no or
293  *                   true-false question.
294  *      Arguments: prompt - the prompt for the user.
295  *                 bool_def - the default value either TRUE or FALSE.
296  *      Returns: TRUE or FALSE or -1 on error
297  */
298
299 Bool
300 YesNoQuestion(prompt, bool_def)
301 char *prompt;
302 int bool_def;
303 {
304     char ans[2];
305
306     while (TRUE) {
307         if (!PromptWithDefault(prompt, ans, 2, bool_def ? "y" : "n"))
308             return(-1);
309         switch (ans[0]) {
310         case 'n':
311         case 'N':
312             return(FALSE);
313         case 'y':
314         case 'Y':
315             return(TRUE);
316         default:
317             Put_message("Please answer 'y' or 'n'.");
318             break;
319         }
320     }
321 }
322 /*      Function Name: YesNoQuitQuestion
323  *      Description: This prompts the user for the answer to a yes-no or
324  *                   true-false question, with a quit option.
325  *      Arguments: prompt - the prompt for the user.
326  *                 bool_def - the default value either TRUE or FALSE.
327  *      Returns: TRUE or FALSE or -1 on error or QUIT
328  *      NOTE: It is not possible to have quit the default, but then I don't
329  *            seem to need this functionality.
330  */
331
332 Bool
333 YesNoQuitQuestion(prompt, bool_def)
334 char *prompt;
335 int bool_def;
336 {
337     char ans[2];
338
339     while (TRUE) {
340         if (!PromptWithDefault(prompt, ans, 2, bool_def ? "y" : "n"))
341             return(-1);
342         switch (ans[0]) {
343         case 'n':
344         case 'N':
345             return(FALSE);
346         case 'y':
347         case 'Y':
348             return(TRUE);
349         case 'q':
350         case 'Q':
351             return(-1);
352         default:
353             Put_message("Please answer 'y', 'n' or 'q'.");
354             break;
355         }
356     }
357 }
358
359 /*      Function Name: Confirm
360  *      Description:   This function asks the user to confirm the action
361  *                     he is about to take, used for things like deleting.
362  *      Arguments: prompt - the prompt string.
363  *      Returns:   TRUE/FALSE - wether or not the confirmation occured.
364  */
365
366 Bool
367 Confirm(prompt)
368 char * prompt;
369 {
370   return( !verbose || (YesNoQuestion(prompt,FALSE) == TRUE) );
371 }
372
373 /*      Function Name: ValidName
374  *      Description: This function checks to see if we have a valid list name.
375  *      Arguments: s - the list name.
376  *      Returns: TRUE if Valid.
377  */
378
379 Bool
380 ValidName(s)
381 char *s;
382 {
383     if (IS_EMPTY(s))
384         Put_message("Please use a non-empty name.");
385     else if (index(s, ' '))
386         Put_message("You cannot use space (' ') in this name.");
387     else if (index(s, WILDCARD))
388         Put_message("Wildcards not accepted here.");
389     else
390         return TRUE;
391     return FALSE;
392 }
393
394 /*      Function Name: ToggleVerboseMode
395  *      Description: This function toggles the verbose mode.
396  *      Arguments: none
397  *      Returns: DM_NORMAL.
398  */
399
400 int 
401 ToggleVerboseMode()
402 {
403
404   verbose = !verbose;
405
406   if (verbose)
407     Put_message("Delete functions will first confirm\n");
408   else
409     Put_message("Delete functions will be silent\n");
410     
411   return(DM_NORMAL);
412 }
413
414 /*      Function Name: NullFunc
415  *      Description:  dummy callback routine 
416  *      Arguments: none
417  *      Returns: SMS_CONT
418  */
419
420 int
421 NullFunc()
422 {
423     return(SMS_CONT);
424 }
425
426 /*      Function Name: SlipInNewName
427  *      Description: Slips the new name into the number 2 slot of a list, and
428  *                   returns a pointer to the new list.
429  *      Arguments: info - list that needs this name slipped into it.
430  *                 name - the name to slip into the list.
431  *      Returns: a pointer to the new list.
432  *      NOTE:  This screws up the numbers of the elements of the array in a
433  *             big way.
434  */
435
436 void
437 SlipInNewName(info, name)
438 char ** info;
439 char * name;
440 {
441     register int i;
442
443     /* This also pushes the NULL down. */
444     for (i = CountArgs(info); i > 1; i--) { 
445         info[i] = info[i-1];
446     }
447     info[1] = name;     /* now slip in the name. */
448 }
449
450 /*      Function Name: GetValueFromUser
451  *      Description: This function gets a value from a user for the field
452  *                   specified.
453  *      Arguments: prompt - prompt for user.
454  *                 pointer - pointer to default value, will be returned
455  *                          as new value.
456  *      Returns: SUB_ERROR if break hit (^C).
457  */
458
459 int
460 GetValueFromUser(prompt, pointer)
461 char * prompt, ** pointer;
462 {
463     char buf[BUFSIZ];
464
465     if (PromptWithDefault(prompt, buf, BUFSIZ, *pointer) == -1)
466         return(SUB_ERROR);
467
468 /* 
469  * If these are the same then there is no need to allocate a new string.
470  *
471  * a difference that makes no difference, IS no difference.
472  */
473
474     if (strcmp(buf, *pointer) != 0) { 
475         if (*pointer != NULL)
476             free(*pointer);
477         *pointer = Strsave(buf);
478     }
479     return(SUB_NORMAL);
480 }
481
482 /*      Function Name: GetYesNoValueFromUser
483  *      Description: This function gets a value from a user for the field
484  *                   specified.
485  *      Arguments: prompt - prompt for user.
486  *                 pointer - pointer to default value, will be returned
487  *                          as new value.
488  *      Returns: SUB_ERROR if break hit (^C).
489  */
490
491 int
492 GetYesNoValueFromUser(prompt, pointer)
493 char * prompt, ** pointer;
494 {
495     char user_prompt[BUFSIZ];
496     Bool default_val;
497
498     if ( strcmp (*pointer, DEFAULT_YES) == 0 )
499         default_val = TRUE;
500     else
501         default_val = FALSE;
502     
503     sprintf(user_prompt, "%s (y/n)", prompt);
504
505     switch (YesNoQuestion(user_prompt, default_val)) {
506     case TRUE:
507         if (*pointer != NULL)
508             free(*pointer);
509         *pointer = Strsave(DEFAULT_YES);
510         break;
511     case FALSE:
512         if (*pointer != NULL)
513             free(*pointer);
514         *pointer = Strsave(DEFAULT_NO);
515         break;
516     case -1:
517     default:
518         return(SUB_ERROR);
519     }
520     return(SUB_NORMAL);
521 }
522
523 /*      Function Name: GetFSVal
524  *      Description: asks about a specific filesystem value.
525  *      Arguments: name - string for this type of filesystem.
526  *                 mask - mask for this type of filesystem.
527  *                 current - current filesystem state. (for defaults).
528  *                 new - new filesystem state.
529  *      Returns: TRUE if successful.
530  */
531
532 static Bool
533 GetFSVal(name, mask, current, new)
534 char * name;
535 int mask, current, *new;
536 {
537     char temp_buf[BUFSIZ];
538     sprintf(temp_buf, "Is this a %s filsystem", name);
539     switch (YesNoQuestion(temp_buf, ( (mask & current) == mask) )) {
540     case TRUE:
541         *new |= mask;
542         break;
543     case FALSE:
544         break;                  /* zero by default. */
545     default:
546         return(FALSE);
547     }
548     return(TRUE);
549 }
550
551 /*      Function Name: GetFSTypes
552  *      Description: Allows user to specify filsystem types.
553  *      Arguments: current - current value of filsystem, freed here.
554  *      Returns: SUB_ERROR on ^C.
555  */
556
557 int
558 GetFSTypes(current)
559 char **  current;
560 {
561     int c_value, new_val = 0;   /* current value of filesys type (int). */
562     char ret_value[BUFSIZ];
563
564     if (*current == NULL)
565         c_value = 0;
566     else 
567         c_value = atoi(*current);
568
569     if (GetFSVal("student", SMS_FS_STUDENT, c_value, &new_val) == FALSE)
570         return(SUB_ERROR);
571     if (GetFSVal("faculty", SMS_FS_FACULTY, c_value, &new_val) == FALSE)
572         return(SUB_ERROR);
573     if (GetFSVal("staff", SMS_FS_STAFF, c_value, &new_val) == FALSE)
574         return(SUB_ERROR);
575     if (GetFSVal("miscellaneous", SMS_FS_MISC, c_value, &new_val) == FALSE)
576         return(SUB_ERROR);
577
578     FreeAndClear(current, TRUE);
579     sprintf(ret_value, "%d", new_val);
580     *current = Strsave(ret_value);
581     return(SUB_NORMAL);
582 }
583
584 /*      Function Name: CanonicalizeHostname
585  *      Description: This function takes a machine name and canonicalize's it.
586  *      Arguments: machine - name of the machine to work on.
587  *      Returns: new name or NULL if nameserver returns error
588  */
589
590 char *
591 CanonicalizeHostname(machine)
592 char *machine;
593 {
594     struct hostent *hostinfo;
595
596     hostinfo = gethostbyname(machine);
597 /* If this fails then we just return what we were passed. */
598     if (hostinfo != (struct hostent *) NULL)
599         machine = hostinfo->h_name;
600     return (machine);
601 }
602
603 /*      Function Name: Strsave
604  *      Description: save a string.
605  *      Arguments: string  - the string to save.
606  *      Returns: The malloced string, now safely saved, or NULL.
607  */
608
609 char *
610 Strsave(str)
611 char *str;
612 {
613     register char *newstr = malloc((unsigned) strlen(str) + 1);
614
615     if (newstr == (char *) NULL)
616         return ((char *) NULL);
617     else
618         return (strcpy(newstr, str));
619 }
620
621 /*      Function Name: Print
622  *      Description: prints out all the arguments on a single line.
623  *      Arguments: argc, argv - the standard SMS arguments.
624  *                 callback - the callback function - NOT USED.
625  *      Returns: SMS_CONT
626  */
627
628 /* ARGSUSED */
629 int
630 Print(argc, argv, callback)
631 int argc;
632 char **argv, *callback;
633 {
634     char buf[BUFSIZ];
635     register int i;
636
637     found_some = TRUE;
638     (void) strcpy(buf,argv[0]); /* no newline 'cause Put_message adds one */
639     for (i = 1; i < argc; i++)
640         (void) sprintf(buf,"%s %s",buf,argv[i]);
641     (void) Put_message(buf);
642
643     return (SMS_CONT);
644 }
645
646 /*      Function Name: PrintByType
647  *      Description: This function prints all members of the type specified
648  *                   by the callback arg, unless the callback is NULL, in which
649  *                   case it prints all members.
650  *      Arguments: argc, argc - normal arguments for sms_callback function. 
651  *                 callback - either a type of member or NULL.
652  *      Returns: SMS_CONT or SMS_QUIT.
653  */
654
655 /*ARGSUSED*/
656 int
657 PrintByType(argc, argv, callback)
658 int argc;
659 char **argv, *callback;
660 {
661     if (callback == NULL)
662         return( Print(argc, argv, callback) );
663     if (strcmp(argv[0], callback) == 0) 
664         return( Print(argc, argv, callback) );
665     return(SMS_CONT);
666 }
667
668 /*      Function Name: PrintHelp
669  *      Description: Prints Help Information in a NULL terminated
670  *                   char **.
671  *      Arguments: message.
672  *      Returns: DM_NORMAL.
673  */
674
675 int
676 PrintHelp(message)
677 char ** message;
678 {
679     Print(CountArgs(message), message, (char *) NULL);
680     return(DM_NORMAL);
681 }
682
683 /*      Function Name: Loop
684  *      Description: This function goes through the entire queue, and
685  *                   and executes the given function on each element.
686  *      Arguments: elem - top element of the queue.
687  *                 func - the function to execute.
688  *      Returns: none.
689  */
690
691 void
692 Loop(elem, func)
693 FVoid func;
694 struct qelem * elem;
695 {
696     while (elem != NULL) {
697         char ** info = (char **) elem->q_data;
698         (*func) (info);
699         elem = elem->q_forw;
700     }
701 }
702
703
704 /*      Function Name: QueryLoop
705  *      Description: This functions loops through a queue containing
706  *                   information about some item that we want to perform
707  *                   an operation on, and then calls the correct routine
708  *                   perform that operation.
709  *      Arguments: top - top of the queue of information.
710  *                 print_func - print function.
711  *                 op_function - operation to be performed.
712  *                 query_string - string the prompts the user whether or not
713  *                                to perform this operation.
714  *      Returns: none.
715  *      NOTES:
716  *               print_opt - should expect one arguent, the info array
717  *                           of char *'s.
718  *                           is expected to return the name of the item.
719  *               op_func   - should expect two arguments.
720  *                           1) the info array of char *'s.
721  *                           2) a boolean the is true if there only
722  *                              one item in this queue, used for delete
723  *                              confirmation.
724  *               query_string - this should be of such a form that when the
725  *                              name of the object and '(y/n/q) ?' are appended
726  *                              then it should still make sense, an example is
727  *                              "Delete the list"
728  */
729
730 void
731 QueryLoop(elem, print_func, op_func, query_string)
732 struct qelem *elem;
733 FVoid op_func;
734 FCharStar print_func;
735 char * query_string;
736 {
737     Bool one_item;
738     char temp_buf[BUFSIZ], *name;
739
740     one_item = (QueueCount(elem) == 1);
741     while (elem != NULL) {
742         char **info = (char **) elem->q_data;
743         
744         if (one_item)
745             (*op_func) (info, one_item);
746         else {
747             name = (*print_func) (info); /* call print function. */
748             sprintf(temp_buf,"%s %s (y/n/q)", query_string, name);
749             switch(YesNoQuitQuestion(temp_buf, FALSE)) {
750             case TRUE:
751                 (*op_func) (info, one_item);
752                 break;
753             case FALSE:
754                 break;
755             default:            /* Quit. */
756                 Put_message("Aborting...");
757                 return;
758             }
759         }
760         elem = elem->q_forw;
761     }
762 }
763
764 /*      Function Name: NullPrint
765  *      Description: print function that returns nothing.
766  *      Arguments: info - a pointer to the info array - Not used.
767  *      Returns: none.
768  */
769
770 char *
771 NullPrint(info)
772 char ** info;
773 {
774     return(info[NAME]);
775 }
776
777 /*
778  * Local Variables:
779  * mode: c
780  * c-indent-level: 4
781  * c-continued-statement-offset: 4
782  * c-brace-offset: -4
783  * c-argdecl-indent: 4
784  * c-label-offset: -4
785  * End:
786  */
This page took 0.098912 seconds and 5 git commands to generate.