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