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