]>
Commit | Line | Data |
---|---|---|
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 | 46 | static 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 | 65 | static 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 | 78 | char **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 | 99 | void 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 | 112 | void 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 | |
128 | struct 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 | 143 | static 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 | 162 | void 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 | 180 | int 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 | 204 | int 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 | 237 | int 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 | 257 | int 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 | 276 | int 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 | 308 | Bool 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 | 341 | Bool 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 | 374 | Bool 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 | 385 | Bool 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 | 404 | int 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 | 422 | int 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 | 437 | void 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 | 456 | int 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 | 489 | int 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 | 529 | static 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 | 552 | int 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 | 589 | char *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 | 602 | char *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 | 621 | int 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 | 644 | int 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 | 660 | int 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 | 678 | void 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 | 715 | void 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 | 755 | char *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 | 767 | struct 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 | 819 | int 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 | 900 | int 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 | ||
919 | int 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 |