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