]> andersk Git - moira.git/blob - clients/moira/utils.c
Diane Delgado's changes for a fixed table-locking order
[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 MOIRA Client, which allows a nieve
6  *      user to quickly and easily maintain most parts of the MOIRA 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 <string.h>
24 #include <moira.h>
25 #include <moira_site.h>
26 #include <menu.h>
27 #include <ctype.h>
28
29 #include "mit-copyright.h"
30 #include "defs.h"
31 #include "f_defs.h"
32 #include "globals.h"
33 #include <netdb.h>              /* for gethostbyname. */
34 #include <sys/types.h>
35 #include <netinet/in.h>
36
37
38 /*      Function Name: AddQueue
39  *      Description: Adds an element to a queue
40  *      Arguments: elem, pred - element and its predecessor.
41  *      Returns: none.
42  */
43
44 static void
45 AddQueue(elem, pred)
46 struct qelem * elem, *pred;
47 {
48     if (pred == NULL) {
49         elem->q_forw = NULL;
50         elem->q_back = NULL;
51         return;
52     }
53     elem->q_back = pred;
54     elem->q_forw = pred->q_forw;
55     pred->q_forw = elem;
56 }
57
58 /*      Function Name: RemoveQueue
59  *      Description: removes an element from a queue.
60  *      Arguments: elem.
61  *      Returns: none.
62  */
63
64 static void
65 RemoveQueue(elem)
66 struct qelem *elem;
67 {
68     if (elem->q_forw != NULL) 
69         (elem->q_forw)->q_back = elem->q_back;
70     if (elem->q_back != NULL)
71         (elem->q_back)->q_forw = elem->q_forw;
72 }
73
74
75 /* CopyInfo: allocates memory for a copy of a NULL terminated array of 
76  * strings <and returns a pointer to the copy.
77  */
78
79 char **CopyInfo(info)
80 char **info;
81 {
82     char **ret;
83     int i;
84
85     ret = (char **) malloc(sizeof(char *) * (CountArgs(info) + 1));
86     if (ret == NULL)
87       return(ret);
88     for (i = 0; info[i]; i++)
89       ret[i] = Strsave(info[i]);
90     ret[i] = NULL;
91     return(ret);
92 }
93
94
95 /*      Function Name: FreeInfo
96  *      Description: Frees all elements of a NULL terminated arrary of char*'s
97  *      Arguments: info - array who's elements we are to free.
98  *      Returns: none.
99  */
100
101 void
102 FreeInfo(info)
103 char ** info;
104 {
105     while (*info != NULL)
106         FreeAndClear(info++, TRUE);
107 }
108
109 /*      Function Name: FreeAndClear        - I couldn't resist the name.
110  *      Description: Clears pointer and optionially frees it.
111  *      Arguments: pointer - pointer to work with.
112  *                 free_it - if TRUE then free pointer.
113  *      Returns: none.
114  */
115
116 void
117 FreeAndClear(pointer, free_it)
118 char ** pointer;
119 Bool free_it;
120 {
121     if (*pointer == NULL)
122         return;
123     else if (free_it)
124         free(*pointer);
125     *pointer = NULL;
126 }
127
128 /*      Function Name: QueueTop
129  *      Description: returns a qelem pointer that points to the top of
130  *                   a queue.
131  *      Arguments: elem - any element of a queue.
132  *      Returns: top element of a queue.
133  */
134     
135 struct qelem * 
136 QueueTop(elem)
137 struct qelem * elem;
138 {
139     if (elem == NULL)           /* NULL returns NULL.  */
140         return(NULL);
141     while (elem->q_back != NULL) 
142         elem = elem->q_back;
143     return(elem);
144 }
145
146 /*      Function Name: FreeQueueElem
147  *      Description: Frees one element of the queue.
148  *      Arguments: elem - the elem to free.
149  *      Returns: none
150  */
151
152 static void
153 FreeQueueElem(elem)
154 struct qelem * elem;
155 {
156     char ** info = (char **) elem->q_data;
157
158     if (info != (char **) NULL) {
159         FreeInfo( info ); /* free info fields */
160         free(elem->q_data);             /* free info array itself. */
161     }
162     RemoveQueue(elem);          /* remove this element from the queue */
163     free(elem);                 /* free its space. */
164 }
165
166 /*      Function Name: FreeQueue
167  *      Description: Cleans up the queue
168  *      Arguments: elem - any element of the queue.
169  *      Returns: none.
170  */
171
172 void
173 FreeQueue(elem)
174 struct qelem * elem;
175 {
176     struct qelem *temp, *local = QueueTop(elem); 
177
178     while(local != NULL) {
179         temp = local->q_forw;
180         FreeQueueElem(local);
181         local = temp;
182     }
183 }
184
185 /*      Function Name: QueueCount
186  *      Description: Counts the number of elements in a queue
187  *      Arguments: elem - any element in the queue.
188  *      Returns: none.
189  */
190
191 int
192 QueueCount(elem)
193 struct qelem * elem;
194 {
195     int count = 0;
196     elem = QueueTop(elem);
197     while (elem != NULL) {
198         count ++;
199         elem = elem->q_forw;
200     }
201     return(count);
202 }
203
204 /*      Function Name: StoreInfo
205  *      Description: Stores information from an moira query into a queue.
206  *      Arguments: argc, argv, - information returned from the query returned
207  *                               in argv.
208  *                 data - the previous element on the queue, this data will be
209  *                        stored in a qelem struct immediatly after this elem.
210  *                        If NULL then a new queue will be created.  This value
211  *                        is updated to the current element at the end off the
212  *                        call.
213  *      Returns: MR_CONT, or MR_ABORT if it has problems.
214  */
215
216 int
217 StoreInfo(argc, argv, data)
218 int argc;
219 char ** argv;
220 char * data;
221 {
222     char ** info = (char **) malloc( MAX_ARGS_SIZE * sizeof(char *));
223     struct qelem ** old_elem = (struct qelem **) data;
224     struct qelem * new_elem = (struct qelem *) malloc (sizeof (struct qelem));
225     int count;
226
227     if ( (new_elem == (struct qelem *) NULL) || (info == (char **) NULL) ) {
228         Put_message("Could Not allocate more memory.");
229         FreeQueue(*old_elem);
230         *old_elem = (struct qelem *) NULL;
231         return(MR_ABORT);
232     }
233
234     for (count = 0; count < argc; count++)
235         info[count] = Strsave(argv[count]);
236     info[count] = NULL;         /* NULL terminate this sucker. */
237
238     new_elem->q_data = (char *) info;
239     AddQueue(new_elem, *old_elem);
240
241     *old_elem = new_elem;
242     return(MR_CONT);
243 }
244
245 /*      Function Name: CountArgs
246  *      Description:  Retrieve the number of args in a null terminated
247  *                     arglist.
248  *      Arguments: info - the argument list.
249  *      Returns: number if args in the list.
250  */
251
252 int
253 CountArgs(info)
254 char ** info;
255 {
256     int number = 0;
257     
258     while (*info != NULL) {
259         number++;
260         info++;
261     }
262
263     return(number);
264 }    
265
266 /*      Function Name: Scream
267  *      Description: Bitch Loudly and exit, it is intended as a callback
268  *                   function for queries that should never return a value.
269  *      Arguments: none
270  *      Returns: doesn't exit.
271  */
272
273 int
274 Scream()
275 {
276     com_err(program_name, 0,
277             "\nA Moira update returned a value -- programmer botch\n");
278     mr_disconnect();
279     exit(1);
280     /*NOTREACHED*/
281     return(-1);
282 }
283
284 /*      Function Name: PromptWithDefault
285  *      Description: allows a user to be prompted for input, and given a 
286  *                   default choice.
287  *      Arguments: prompt - the prompt string.
288  *                 buf, buflen - buffer to be returned and its MAX size?
289  *                 default value for the answer.
290  *      Returns: zero on failure
291  */
292
293 int
294 PromptWithDefault(prompt, buf, buflen, def)
295 char *prompt, *buf;
296 int buflen;
297 char *def;
298 {
299     char tmp[BUFSIZ];
300     int ans;
301
302     if (parsed_argc > 0) {
303         parsed_argc--;
304         strncpy(buf, parsed_argv[0], buflen);
305         sprintf(tmp, "%s: %s", prompt, buf);
306         Put_message(tmp);
307         parsed_argv++;
308         return(1);
309     }
310
311     (void) sprintf(tmp, "%s [%s]: ", prompt, def ? def : "");
312     ans = Prompt_input(tmp, buf, buflen);
313     if (IS_EMPTY(buf))
314         (void) strcpy(buf, def);
315     else if (!strcmp(buf, "\"\""))
316         *buf = 0;
317     return(ans);
318 }
319
320 /*      Function Name: YesNoQuestion
321  *      Description: This prompts the user for the answer to a yes-no or
322  *                   true-false question.
323  *      Arguments: prompt - the prompt for the user.
324  *                 bool_def - the default value either TRUE or FALSE.
325  *      Returns: TRUE or FALSE or -1 on error
326  */
327
328 Bool
329 YesNoQuestion(prompt, bool_def)
330 char *prompt;
331 int bool_def;
332 {
333     char ans[2];
334
335     while (TRUE) {
336         if (!PromptWithDefault(prompt, ans, 2, bool_def ? "y" : "n"))
337             return(-1);
338         switch (ans[0]) {
339         case 'n':
340         case 'N':
341             return(FALSE);
342         case 'y':
343         case 'Y':
344             return(TRUE);
345         default:
346             Put_message("Please answer 'y' or 'n'.");
347             break;
348         }
349     }
350 }
351 /*      Function Name: YesNoQuitQuestion
352  *      Description: This prompts the user for the answer to a yes-no or
353  *                   true-false question, with a quit option.
354  *      Arguments: prompt - the prompt for the user.
355  *                 bool_def - the default value either TRUE or FALSE.
356  *      Returns: TRUE or FALSE or -1 on error or QUIT
357  *      NOTE: It is not possible to have quit the default, but then I don't
358  *            seem to need this functionality.
359  */
360
361 Bool
362 YesNoQuitQuestion(prompt, bool_def)
363 char *prompt;
364 int bool_def;
365 {
366     char ans[2];
367
368     while (TRUE) {
369         if (!PromptWithDefault(prompt, ans, 2, bool_def ? "y" : "n"))
370             return(-1);
371         switch (ans[0]) {
372         case 'n':
373         case 'N':
374             return(FALSE);
375         case 'y':
376         case 'Y':
377             return(TRUE);
378         case 'q':
379         case 'Q':
380             return(-1);
381         default:
382             Put_message("Please answer 'y', 'n' or 'q'.");
383             break;
384         }
385     }
386 }
387
388 /*      Function Name: Confirm
389  *      Description:   This function asks the user to confirm the action
390  *                     he is about to take, used for things like deleting.
391  *      Arguments: prompt - the prompt string.
392  *      Returns:   TRUE/FALSE - wether or not the confirmation occured.
393  */
394
395 Bool
396 Confirm(prompt)
397 char * prompt;
398 {
399   return( !verbose || (YesNoQuestion(prompt,FALSE) == TRUE) );
400 }
401
402 /*      Function Name: ValidName
403  *      Description: This function checks to see if we have a valid list name.
404  *      Arguments: s - the list name.
405  *      Returns: TRUE if Valid.
406  */
407
408 Bool
409 ValidName(s)
410 char *s;
411 {
412     if (IS_EMPTY(s))
413         Put_message("Please use a non-empty name.");
414     else if (strchr(s, ' '))
415         Put_message("You cannot use space (' ') in this name.");
416     else if (strchr(s, '*') || strchr(s, '?') || strchr(s, '['))
417         Put_message("Wildcards not accepted here.");
418     else
419         return TRUE;
420     return FALSE;
421 }
422
423 /*      Function Name: ToggleVerboseMode
424  *      Description: This function toggles the verbose mode.
425  *      Arguments: none
426  *      Returns: DM_NORMAL.
427  */
428
429 int 
430 ToggleVerboseMode()
431 {
432
433   verbose = !verbose;
434
435   if (verbose)
436     Put_message("Delete functions will first confirm\n");
437   else
438     Put_message("Delete functions will be silent\n");
439     
440   return(DM_NORMAL);
441 }
442
443 /*      Function Name: NullFunc
444  *      Description:  dummy callback routine 
445  *      Arguments: none
446  *      Returns: MR_CONT
447  */
448
449 int
450 NullFunc()
451 {
452     return(MR_CONT);
453 }
454
455 /*      Function Name: SlipInNewName
456  *      Description: Slips the new name into the number 2 slot of a list, and
457  *                   returns a pointer to the new list.
458  *      Arguments: info - list that needs this name slipped into it.
459  *                 name - the name to slip into the list.
460  *      Returns: a pointer to the new list.
461  *      NOTE:  This screws up the numbers of the elements of the array in a
462  *             big way.
463  */
464
465 void
466 SlipInNewName(info, name)
467 char ** info;
468 char * name;
469 {
470     register int i;
471
472     /* This also pushes the NULL down. */
473     for (i = CountArgs(info); i > 0; i--) { 
474         info[i+1] = info[i];
475     }
476     info[1] = name;     /* now slip in the name. */
477 }
478
479 /*      Function Name: GetValueFromUser
480  *      Description: This function gets a value from a user for the field
481  *                   specified.
482  *      Arguments: prompt - prompt for user.
483  *                 pointer - pointer to default value, will be returned
484  *                          as new value.
485  *      Returns: SUB_ERROR if break hit (^C).
486  */
487
488 int
489 GetValueFromUser(prompt, pointer)
490 char * prompt, ** pointer;
491 {
492     char buf[BUFSIZ];
493
494     if (PromptWithDefault(prompt, buf, BUFSIZ, *pointer) == 0)
495         return(SUB_ERROR);
496
497 /* 
498  * If these are the same then there is no need to allocate a new string.
499  *
500  * a difference that makes no difference, IS no difference.
501  */
502
503     if (*pointer != NULL) {
504         if (strcmp(buf, *pointer) != 0) { 
505             free(*pointer);
506             *pointer = Strsave(buf);
507         }
508     }
509     return(SUB_NORMAL);
510 }
511
512 /*      Function Name: GetYesNoValueFromUser
513  *      Description: This function gets a value from a user for the field
514  *                   specified.
515  *      Arguments: prompt - prompt for user.
516  *                 pointer - pointer to default value, will be returned
517  *                          as new value.
518  *      Returns: SUB_ERROR if break hit (^C).
519  */
520
521 int
522 GetYesNoValueFromUser(prompt, pointer)
523 char * prompt, ** pointer;
524 {
525     char user_prompt[BUFSIZ];
526     Bool default_val;
527
528     if ( strcmp (*pointer, DEFAULT_YES) == 0 )
529         default_val = TRUE;
530     else
531         default_val = FALSE;
532     
533     sprintf(user_prompt, "%s (y/n)", prompt);
534
535     switch (YesNoQuestion(user_prompt, default_val)) {
536     case TRUE:
537         if (*pointer != NULL)
538             free(*pointer);
539         *pointer = Strsave(DEFAULT_YES);
540         break;
541     case FALSE:
542         if (*pointer != NULL)
543             free(*pointer);
544         *pointer = Strsave(DEFAULT_NO);
545         break;
546     case -1:
547     default:
548         return(SUB_ERROR);
549     }
550     return(SUB_NORMAL);
551 }
552
553 /*      Function Name: GetFSVal
554  *      Description: asks about a specific filesystem value.
555  *      Arguments: name - string for this type of filesystem.
556  *                 mask - mask for this type of filesystem.
557  *                 current - current filesystem state. (for defaults).
558  *                 new - new filesystem state.
559  *      Returns: TRUE if successful.
560  */
561
562 static Bool
563 GetFSVal(name, mask, current, new)
564 char * name;
565 int mask, current, *new;
566 {
567     char temp_buf[BUFSIZ];
568     sprintf(temp_buf, "Is this a %s filsystem", name);
569     switch (YesNoQuestion(temp_buf, ( (mask & current) == mask) )) {
570     case TRUE:
571         *new |= mask;
572         break;
573     case FALSE:
574         break;                  /* zero by default. */
575     default:
576         return(FALSE);
577     }
578     return(TRUE);
579 }
580
581 /*      Function Name: GetFSTypes
582  *      Description: Allows user to specify filsystem types.
583  *      Arguments: current - current value of filsystem, freed here.
584  *      Returns: SUB_ERROR on ^C.
585  */
586
587 int
588 GetFSTypes(current, options)
589 char **  current;
590 int options;
591 {
592     int c_value, new_val = 0;   /* current value of filesys type (int). */
593     char ret_value[BUFSIZ];
594
595     if (*current == NULL)
596         c_value = 0;
597     else 
598         c_value = atoi(*current);
599
600     if (GetFSVal("student", MR_FS_STUDENT, c_value, &new_val) == FALSE)
601         return(SUB_ERROR);
602     if (GetFSVal("faculty", MR_FS_FACULTY, c_value, &new_val) == FALSE)
603         return(SUB_ERROR);
604     if (GetFSVal("staff", MR_FS_STAFF, c_value, &new_val) == FALSE)
605         return(SUB_ERROR);
606     if (GetFSVal("miscellaneous", MR_FS_MISC, c_value, &new_val) == FALSE)
607         return(SUB_ERROR);
608     if (options) {
609         if (GetFSVal("Group Quotas", MR_FS_GROUPQUOTA, c_value, &new_val) ==
610             FALSE)
611           return(SUB_ERROR);
612     }
613
614     FreeAndClear(current, TRUE);
615     sprintf(ret_value, "%d", new_val);
616     *current = Strsave(ret_value);
617     return(SUB_NORMAL);
618 }
619
620 /*      Function Name: Strsave
621  *      Description: save a string.
622  *      Arguments: string  - the string to save.
623  *      Returns: The malloced string, now safely saved, or NULL.
624  */
625
626 char *
627 Strsave(str)
628 char *str;
629 {
630     register char *newstr = malloc((unsigned) strlen(str) + 1);
631
632     if (newstr == (char *) NULL)
633         return ((char *) NULL);
634     else
635         return (strcpy(newstr, str));
636 }
637
638
639 /* atot: convert ASCII integer unix time into human readable date string */
640
641 char *atot(itime)
642 char *itime;
643 {
644     int time;
645     char *ct, *ctime();
646
647     time = atoi(itime);
648     ct = ctime(&time);
649     ct[24] = 0;
650     return(&ct[4]);
651 }
652
653
654 /*      Function Name: Print
655  *      Description: prints out all the arguments on a single line.
656  *      Arguments: argc, argv - the standard MR arguments.
657  *                 callback - the callback function - NOT USED.
658  *      Returns: MR_CONT
659  */
660
661 /* ARGSUSED */
662 int
663 Print(argc, argv, callback)
664 int argc;
665 char **argv, *callback;
666 {
667     char buf[BUFSIZ];
668     register int i;
669
670     found_some = TRUE;
671     (void) strcpy(buf,argv[0]); /* no newline 'cause Put_message adds one */
672     for (i = 1; i < argc; i++)
673         (void) sprintf(buf,"%s %s",buf,argv[i]);
674     (void) Put_message(buf);
675
676     return (MR_CONT);
677 }
678
679 /*      Function Name: PrintByType
680  *      Description: This function prints all members of the type specified
681  *                   by the callback arg, unless the callback is NULL, in which
682  *                   case it prints all members.
683  *      Arguments: argc, argc - normal arguments for mr_callback function. 
684  *                 callback - either a type of member or NULL.
685  *      Returns: MR_CONT or MR_QUIT.
686  */
687
688 /*ARGSUSED*/
689 int
690 PrintByType(argc, argv, callback)
691 int argc;
692 char **argv, *callback;
693 {
694     if (callback == NULL)
695         return( Print(argc, argv, callback) );
696     if (strcmp(argv[0], callback) == 0) 
697         return( Print(argc, argv, callback) );
698     return(MR_CONT);
699 }
700
701 /*      Function Name: PrintHelp
702  *      Description: Prints Help Information in a NULL terminated
703  *                   char **.
704  *      Arguments: message.
705  *      Returns: DM_NORMAL.
706  */
707
708 int
709 PrintHelp(message)
710 char ** message;
711 {
712     register int i;
713
714     for (i = 0; i < CountArgs(message); i++)
715       Put_message(message[i]);
716
717     return(DM_NORMAL);
718 }
719
720 /*      Function Name: Loop
721  *      Description: This function goes through the entire queue, and
722  *                   and executes the given function on each element.
723  *      Arguments: elem - top element of the queue.
724  *                 func - the function to execute.
725  *      Returns: none.
726  */
727
728 void
729 Loop(elem, func)
730 FVoid func;
731 struct qelem * elem;
732 {
733     while (elem != NULL) {
734         char ** info = (char **) elem->q_data;
735         (*func) (info);
736         elem = elem->q_forw;
737     }
738 }
739
740
741 /*      Function Name: QueryLoop
742  *      Description: This functions loops through a queue containing
743  *                   information about some item that we want to perform
744  *                   an operation on, and then calls the correct routine
745  *                   perform that operation.
746  *      Arguments: top - top of the queue of information.
747  *                 print_func - print function.
748  *                 op_function - operation to be performed.
749  *                 query_string - string the prompts the user whether or not
750  *                                to perform this operation.
751  *      Returns: none.
752  *      NOTES:
753  *               print_opt - should expect one arguent, the info array
754  *                           of char *'s.
755  *                           is expected to return the name of the item.
756  *               op_func   - should expect two arguments.
757  *                           1) the info array of char *'s.
758  *                           2) a boolean the is true if there only
759  *                              one item in this queue, used for delete
760  *                              confirmation.
761  *               query_string - this should be of such a form that when the
762  *                              name of the object and '(y/n/q) ?' are appended
763  *                              then it should still make sense, an example is
764  *                              "Delete the list"
765  */
766
767 void
768 QueryLoop(elem, print_func, op_func, query_string)
769 struct qelem *elem;
770 FVoid op_func;
771 FCharStar print_func;
772 char * query_string;
773 {
774     Bool one_item;
775     char temp_buf[BUFSIZ], *name;
776
777     elem = QueueTop(elem);
778     one_item = (QueueCount(elem) == 1);
779     while (elem != NULL) {
780         char **info = (char **) elem->q_data;
781         
782         if (one_item)
783             (*op_func) (info, one_item);
784         else {
785             name = (*print_func) (info); /* call print function. */
786             sprintf(temp_buf,"%s %s (y/n/q)", query_string, name);
787             switch(YesNoQuitQuestion(temp_buf, FALSE)) {
788             case TRUE:
789                 (*op_func) (info, one_item);
790                 break;
791             case FALSE:
792                 break;
793             default:            /* Quit. */
794                 Put_message("Aborting...");
795                 return;
796             }
797         }
798         elem = elem->q_forw;
799     }
800 }
801
802 /*      Function Name: NullPrint
803  *      Description: print function that returns nothing.
804  *      Arguments: info - a pointer to the info array - Not used.
805  *      Returns: none.
806  */
807
808 char *
809 NullPrint(info)
810 char ** info;
811 {
812     return(info[NAME]);
813 }
814
815
816 /*      Function Name: GetTypeValues
817  *      Description: gets legal values for a typed object, keeping a cache
818  *      Arguments: type name
819  *      Returns: argv of values
820  */
821
822 struct qelem *
823 GetTypeValues(tname)
824 char *tname;
825 {
826     int stat;
827     char *argv[3], *p, **pp, *strsave();
828     struct qelem *elem, *oelem;
829     static struct qelem *cache = NULL;
830     struct cache_elem { char *cache_name; struct qelem *cache_data; } *ce;
831
832     for (elem = cache; elem; elem = elem->q_forw) {
833         ce = (struct cache_elem *)elem->q_data;
834         if (!strcmp(ce->cache_name, tname))
835             return(ce->cache_data);
836     }
837
838     argv[0] = tname;
839     argv[1] = "TYPE";
840     argv[2] = "*";
841     elem = NULL;
842     if (stat = do_mr_query("get_alias", 3, argv, StoreInfo, (char *)&elem)) {
843         com_err(program_name, stat, " in GetTypeValues");
844         return(NULL);
845     }
846     oelem = elem;
847     for (elem = QueueTop(elem); elem; elem = elem->q_forw) {
848         pp = (char **) elem->q_data;
849         p = strsave(pp[2]);
850         FreeInfo(pp);
851         elem->q_data = p;
852     }
853     elem = (struct qelem *) malloc(sizeof(struct qelem));
854     ce = (struct cache_elem *) malloc(sizeof(struct cache_elem));
855     ce->cache_name = strsave(tname);
856     ce->cache_data = QueueTop(oelem);
857     elem->q_data = (char  *)ce;
858     AddQueue(elem, cache);
859     cache = QueueTop(elem);
860     return(ce->cache_data);
861 }
862
863
864 /*      Function Name: GetTypeFromUser
865  *      Description: gets a typed value from the user
866  *      Arguments: prompt string, type name, buffer pointer
867  *      Returns: SUB_ERROR if ^C, SUB_NORMAL otherwise
868  */
869
870 int GetTypeFromUser(prompt, tname, pointer)
871 char *prompt;
872 char *tname;
873 char  **pointer;
874 {
875     char def[BUFSIZ], buffer[BUFSIZ], *p, *argv[3];
876     struct qelem *elem;
877     int stat;
878
879     strcpy(def, *pointer);
880     strcpy(buffer, prompt);
881     strcat(buffer, " (");
882     for (elem = GetTypeValues(tname); elem; elem = elem->q_forw) {
883         strcat(buffer, elem->q_data);
884         if (elem->q_forw)
885             strcat(buffer, ", ");
886     }
887     strcat(buffer, ")");
888     if (strlen(buffer) > 64)
889         sprintf(buffer, "%s (? for help)", prompt);
890     if (GetValueFromUser(buffer, pointer) == SUB_ERROR)
891       return(SUB_ERROR);
892     if (**pointer == '?') {
893         sprintf(buffer, "Type %s is one of:", tname);
894         Put_message(buffer);
895         for (elem = GetTypeValues(tname); elem; elem = elem->q_forw) {
896             Put_message(elem->q_data);
897         }
898         *pointer = strsave(def);
899         return(GetTypeFromUser(prompt, tname, pointer));
900     }
901     for (elem = GetTypeValues(tname); elem; elem = elem->q_forw) {
902         if (!strcasecmp(elem->q_data, *pointer)) {
903             strcpy(*pointer, elem->q_data);
904             return(SUB_NORMAL);
905         }
906     }
907     sprintf(buffer, "\"%s\" is not a legal value for %s.  Use one of:",
908             *pointer, tname);
909     Put_message(buffer);
910     for (elem = GetTypeValues(tname); elem; elem = elem->q_forw) {
911         Put_message(elem->q_data);
912     }
913     sprintf(buffer, "Are you sure you want \"%s\" to be a legal %s",
914             *pointer, tname);
915     if (YesNoQuestion("Do you want this to be a new legal value", 0) == TRUE &&
916         YesNoQuestion(buffer, 0) == TRUE) {
917         argv[0] = tname;
918         argv[1] = "TYPE";
919         argv[2] = *pointer;
920         /* don't uppercase access flags.  Do uppercase everything else */
921         if (strncmp(tname, "fs_access", 9))
922           for (p = argv[2]; *p; p++)
923             if (islower(*p))
924               *p = toupper(*p);
925         if (stat = do_mr_query("add_alias", 3, argv, Scream, NULL)) {
926             com_err(program_name, stat, " in add_alias");
927         } else {
928             elem = (struct qelem *) malloc(sizeof(struct qelem));
929             elem->q_data = strsave(*pointer);
930             AddQueue(elem, GetTypeValues(tname));
931             Put_message("Done.");
932         }
933     }
934     *pointer = strsave(def);
935     return(GetTypeFromUser(prompt, tname, pointer));
936 }
937
938
939 /*      Function Name: GetAddressFromUser
940  *      Description: gets an IP address from the user
941  *      Arguments: prompt string, buffer pointer
942  *              buffer contains default value as long int
943  *      Returns: SUB_ERROR if ^C, SUB_NORMAL otherwise
944  */
945
946 int GetAddressFromUser(prompt, pointer)
947 char *prompt;
948 char  **pointer;
949 {
950     char *value, buf[256];
951     struct in_addr addr;
952     int ret;
953
954     addr.s_addr = htonl(atoi(*pointer));
955     value = strsave(inet_ntoa(addr));
956     ret = GetValueFromUser(prompt, &value);
957     if (ret == SUB_ERROR) return(SUB_ERROR);
958     addr.s_addr = inet_addr(value);
959     free(pointer);
960     sprintf(buf, "%d", ntohl(addr.s_addr));
961     *pointer = strsave(buf);
962     return(SUB_NORMAL);
963 }
964
965
966 do_mr_query(name, argc, argv, proc, hint)
967 char *name;
968 int argc;
969 char **argv;
970 int (*proc)();
971 char *hint;
972 {
973     int status;
974     extern char *whoami, *moira_server;
975
976     refresh_screen();
977     status = mr_query(name, argc, argv, proc, hint);
978     if (status != MR_ABORTED && status != MR_NOT_CONNECTED)
979       return(status);
980     status = mr_connect(moira_server);
981     if (status) {
982         com_err(whoami, status, " while re-connecting to server %s",
983                 moira_server);
984         return(MR_ABORTED);
985     }
986     status = mr_auth(whoami);
987     if (status) {
988         com_err(whoami, status, " while re-authenticating to server %s",
989                 moira_server);
990         mr_disconnect();
991         return(MR_ABORTED);
992     }
993     status = mr_query(name, argc, argv, proc, hint);
994     return(status);
995 }
996
This page took 0.118057 seconds and 5 git commands to generate.