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