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