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