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