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