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