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