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