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