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