]> andersk Git - moira.git/blame - clients/moira/menu.c
eliminate use of the `register' keyword: let the compiler decide
[moira.git] / clients / moira / menu.c
CommitLineData
07c56447 1/*
2aaf83c2 2 * Copyright 1987 by the Massachusetts Institute of Technology.
3 * For copying and distribution information, see the file
4 * "mit-copyright.h".
5 *
6 * $Source$
7 * $Author$
8 * $Header$
2aaf83c2 9 *
07c56447 10 * Generic menu system module.
11 *
12 * Basically, we define an enormous tree structure which represents the
13 * menu. Some extra pieces (ml_command, ma_doc) get thrown in so we can
14 * also use the structure for a command-based system.
15 *
16 * By making the menu descriptions so general, we can ease porting to just
17 * about anything.
18 */
19
2aaf83c2 20#ifndef lint
21static char rcsid_menu_c[] = "$Header$";
7798ebc3 22#endif
2aaf83c2 23
babbc197 24#include <mit-copyright.h>
34f47457 25#include <sys/types.h>
07c56447 26#include <stdio.h>
7798ebc3 27#include <stdlib.h>
cde7e985 28#include <string.h>
967b7c08 29#include <signal.h>
07c56447 30#include <curses.h>
cde7e985 31#include <unistd.h>
68ec9052 32#include <termios.h>
7798ebc3 33#include <stdarg.h>
2aaf83c2 34#include <ctype.h>
6298c97d 35#include <com_err.h>
cde7e985 36#include <moira.h>
07c56447 37#include "menu.h"
38
5eaef520 39#define MAX(A, B) ((A) > (B) ? (A) : (B))
40#define MIN(A, B) ((A) < (B) ? (A) : (B))
967b7c08 41#define CTL(ch) ((ch) & 037)
07c56447 42
43#define MIN_INPUT 2 /* Minimum number of lines for input window */
44
facd6784 45extern int interrupt; /* will be set if ^C is received */
859891c0 46extern char *whoami;
47
48FILE *log_file = (FILE *) NULL; /* file stream of log file */
e9db439c 49int more_flg = 1;
2aaf83c2 50
07c56447 51/* Structure for holding current displayed menu */
52struct menu_screen {
5eaef520 53 WINDOW *ms_screen; /* Window for this menu */
54 WINDOW *ms_title; /* Title subwindow */
55 WINDOW *ms_menu; /* Menu subwindow */
56 WINDOW *ms_input; /* Input subwindow */
57 int ms_input_y; /* Input subwindow reference coordinate */
58} *cur_ms;
07c56447 59
2aaf83c2 60#define NULLMS ((struct menu_screen *) 0)
61
62Menu *top_menu; /* Root for command search */
11317e48 63int parsed_argc; /* used by extern routines to get additional */
64char **parsed_argv; /* comand line input */
2aaf83c2 65
6298c97d 66/*
67 * Hook function to cause error messages to be printed through
22da5e41 68 * curses instead of around it. Takes at most 5 args to the
69 * printf string (crock...)
6298c97d 70 */
71
5eaef520 72void menu_com_err_hook(const char *who, long code, const char *fmt,
73 caddr_t arg1, caddr_t arg2, caddr_t arg3,
74 caddr_t arg4, caddr_t arg5)
6298c97d 75{
5eaef520 76 char buf[BUFSIZ], *cp;
77
78 strcpy(buf, who);
79 for (cp = buf; *cp; cp++)
80 ;
81 *cp++ = ':';
82 *cp++ = ' ';
83 if (code)
84 {
85 strcpy(cp, error_message(code));
86 while (*cp)
87 cp++;
6298c97d 88 }
5eaef520 89 sprintf(cp, fmt, arg1, arg2, arg3, arg4, arg5);
90 Put_message(buf);
6298c97d 91}
92
07c56447 93/*
94 * Start_menu takes a menu as an argument. It initializes curses u.s.w.,
95 * and a quit in any submenu should unwind back to here. (it might not,
96 * if user functions which run their own menus don't cooperate.)
97 * Start_menu should only be called once, at the start of the program.
98 */
5eaef520 99int Start_menu(Menu *m)
07c56447 100{
5eaef520 101 struct menu_screen *make_ms();
44d12d58 102 void (*old_hook)(const char *, long, const char *, va_list) =
5eaef520 103 set_com_err_hook((void (*) (const char *, long, const char *, va_list))menu_com_err_hook);
104
105 if (initscr() == (WINDOW *)ERR)
106 {
107 fputs("Can't initialize curses!\n", stderr);
108 Start_no_menu(m);
07c56447 109 }
5eaef520 110 else
111 {
112 raw(); /* We parse & print everything ourselves */
113 noecho();
114 cur_ms = make_ms(0); /* So we always have some current */
115 /* menu_screen */
116 /* Run the menu */
117 Do_menu(m, -1, NULL);
118 }
119 set_com_err_hook(old_hook);
120 Cleanup_menu();
967b7c08 121}
122
5eaef520 123int Cleanup_menu(void)
967b7c08 124{
5eaef520 125 if (cur_ms)
126 {
127 wclear(cur_ms->ms_screen);
128 wrefresh(cur_ms->ms_screen);
967b7c08 129 }
5eaef520 130 endwin();
07c56447 131}
5eaef520 132
07c56447 133
2aaf83c2 134/* Like Start_menu, except it doesn't print menus and doesn't use curses */
5eaef520 135int Start_no_menu(Menu *m)
2aaf83c2 136{
5eaef520 137 cur_ms = NULLMS;
138 COLS = 80;
139 /* Run the menu */
140 Do_menu(m, -1, NULL);
2aaf83c2 141}
142
07c56447 143/*
144 * Create a new menu screen template with the specified menu length
145 * and return it.
146 */
5eaef520 147struct menu_screen *make_ms(int length)
07c56447 148{
5eaef520 149 struct menu_screen *ms;
07c56447 150
5eaef520 151 if (MAX_TITLE + length + MIN_INPUT > LINES)
152 {
153 fputs("Menu too big!\n", stderr);
154 exit(2);
07c56447 155 }
156
5eaef520 157 ms = malloc(sizeof(struct menu_screen));
07c56447 158
5eaef520 159 ms->ms_screen = newwin(0, 0, 0, 0);
160 ms->ms_title = subwin(ms->ms_screen, MAX_TITLE, 0, 0, 0);
161 ms->ms_menu = subwin(ms->ms_screen, length, 0, MAX_TITLE, 0);
162 ms->ms_input = subwin(ms->ms_screen, 0, 0,
163 ms->ms_input_y = MAX_TITLE + length,
164 0);
07c56447 165
5eaef520 166 scrollok(ms->ms_input, TRUE);
167 wmove(ms->ms_input, 0, 0);
168 wclear(ms->ms_screen);
07c56447 169
5eaef520 170 return ms;
07c56447 171}
172
173/*
174 * This routine destroys a menu_screen.
175 */
5eaef520 176int destroy_ms(struct menu_screen *ms)
07c56447 177{
5eaef520 178 delwin(ms->ms_title);
179 delwin(ms->ms_menu);
180 delwin(ms->ms_input);
181 delwin(ms->ms_screen);
182 free(ms);
07c56447 183}
184
185/*
186 * This guy actually puts up the menu
967b7c08 187 * Note: if margc < 0, no 'r' option will be displayed (i.e., on the
188 * top level menu)
07c56447 189 */
5eaef520 190int Do_menu(Menu *m, int margc, char *margv[])
07c56447 191{
5eaef520 192 struct menu_screen *my_ms = NULLMS, *old_cur_ms = NULLMS;
193 char argvals[MAX_ARGC][MAX_ARGLEN]; /* This is where args are stored */
194 char buf[MAX_ARGC * MAX_ARGLEN];
195 char *argv[MAX_ARGC];
196 int line;
197 int i;
198 struct menu_line *command, *Find_command();
199 int argc;
200 int quitflag, is_topmenu = (margc < 0);
201 int toggle_logging();
202
203 /* Entry function gets called with old menu_screen still current */
204 if (m->m_entry != NULLFUNC)
205 {
206 if (m->m_entry(m, margc, margv) == DM_QUIT)
207 return DM_NORMAL;
208 if (parsed_argc > 0)
209 {
210 margc = parsed_argc + 1;
211 margv = --parsed_argv;
212 }
213 else
214 {
215 margc--;
216 margv++;
11317e48 217 }
218 }
219
5eaef520 220 parsed_argc = 0;
221
222 /* The following get run only in curses mode */
223 if (cur_ms != NULLMS)
224 {
225 /* Get a menu_screen */
226 old_cur_ms = cur_ms;
227 /* 2 is for the 2 obligatory lines; quit and toggle */
228 cur_ms = my_ms = make_ms(m->m_length + 2 + (is_topmenu ? 0 : 1));
229
230 /* Now print the title and the menu */
231 wclear(my_ms->ms_screen);
232 wrefresh(my_ms->ms_screen);
233 wmove(my_ms->ms_title, 0, MAX(0, (COLS - strlen(m->m_title)) >> 1));
234 wstandout(my_ms->ms_title);
235 waddstr(my_ms->ms_title, m->m_title);
236 wstandend(my_ms->ms_title);
237
238 for (line = 0; line < m->m_length; line++)
239 {
240 int len = strlen(m->m_lines[line].ml_command);
241 if (len > 12)
242 len = 12;
243
244 wmove(my_ms->ms_menu, line, 0);
245
246 wprintw(my_ms->ms_menu, "%2d. (%s)%*s %s.", line + 1,
247 m->m_lines[line].ml_command, 12 - len, "",
248 m->m_lines[line].ml_doc);
2aaf83c2 249 }
5eaef520 250 wmove(my_ms->ms_menu, line++, 0);
251 if (!is_topmenu)
252 {
253 waddstr(my_ms->ms_menu,
254 " r. (return) Return to previous menu.");
255 wmove(my_ms->ms_menu, line++, 0);
967b7c08 256 }
5eaef520 257 waddstr(my_ms->ms_menu, " t. (toggle) Toggle logging on and off.");
258 wmove(my_ms->ms_menu, line, 0);
259 waddstr(my_ms->ms_menu, " q. (quit) Quit.");
260 }
261 else
262 {
263 Put_message(m->m_title);
264 for (line = 0; line < m->m_length; line++)
265 {
266 sprintf(buf, "%2d. (%s)%*s %s.", line + 1,
267 m->m_lines[line].ml_command,
268 12 - strlen(m->m_lines[line].ml_command), "",
269 m->m_lines[line].ml_doc);
270 Put_message(buf);
33a56ee9 271 }
5eaef520 272 if (!is_topmenu)
273 Put_message(" r. (return) Return to previous menu.");
274 Put_message(" t. (toggle) Toggle logging on and off.");
275 Put_message(" q. (quit) Quit.");
276 Put_message(" ?. Print this information.");
07c56447 277 }
07c56447 278
5eaef520 279 for (;;)
280 {
281 /* This will be set by a return val from func or submenu */
282 quitflag = DM_NORMAL;
283 /* This is here because we may be coming from another menu */
284 if (cur_ms != NULL)
285 {
286 touchwin(my_ms->ms_screen);
287 wrefresh(my_ms->ms_screen);
c3e65787 288 }
5eaef520 289 if (margc > 1)
290 {
291 /* Initialize argv */
292 for (argc = 0; argc < MAX_ARGC; argc++)
293 argv[argc] = argvals[argc];
294 argc = margc - 1;
295 for (i = 1; i < margc; i++)
296 strcpy(argvals[i - 1], margv[i]);
297 margc = 0;
e85f474d 298 }
5eaef520 299 else
300 {
301 /* Get a command */
302 if (!Prompt_input("Command: ", buf, sizeof(buf)))
303 {
304 if (cur_ms == NULLMS && feof(stdin))
305 sprintf(buf, "quit");
306 else
307 continue;
308 }
309 /* Parse it into the argument list */
310 /* If there's nothing there, try again */
311 /* Initialize argv */
312 for (argc = 0; argc < MAX_ARGC; argc++)
313 argv[argc] = argvals[argc];
314
315 if ((argc = Parse_words(buf, argv, MAX_ARGLEN)) == 0)
316 continue;
e9db439c 317 }
5eaef520 318 if ((line = atoi(argv[0])) > 0 && line <= m->m_length)
319 command = &m->m_lines[line - 1];
320 else if ((!is_topmenu &&
321 (!strcmp(argv[0], "r") || !strcmp(argv[0], "return"))) ||
322 !strcmp(argv[0], "q") || !strcmp(argv[0], "quit"))
323 {
324 /* here if it's either return or quit */
325 if (cur_ms != NULLMS)
326 {
327 cur_ms = old_cur_ms;
328 destroy_ms(my_ms);
2aaf83c2 329 }
5eaef520 330 if (m->m_exit != NULLFUNC)
331 m->m_exit(m);
332 return *argv[0] == 'r' ? DM_NORMAL : DM_QUIT;
e9db439c 333 }
5eaef520 334 else if (argv[0][0] == '?')
335 {
336 for (line = 0; line < m->m_length; line++)
337 {
338 sprintf(buf, "%2d. (%s)%*s %s.", line + 1,
339 m->m_lines[line].ml_command,
340 12 - strlen(m->m_lines[line].ml_command), "",
341 m->m_lines[line].ml_doc);
342 Put_message(buf);
33a56ee9 343 }
5eaef520 344 if (!is_topmenu)
345 Put_message(" r. (return) Return to previous menu.");
346 Put_message(" t. (toggle) Toggle logging on and off.");
347 Put_message(" q. (quit) Quit.");
348 continue;
33a56ee9 349 }
5eaef520 350 else if (!strcmp(argv[0], "t") || !strcmp(argv[0], "toggle"))
351 {
352 toggle_logging(argc, argv);
353 continue;
e9db439c 354 }
5eaef520 355 /* finally, try to find it using Find_command */
356 else if (!(command = Find_command(m, argvals[0])))
357 {
358 sprintf(buf, "Command not recognized: %s\n", argvals[0]);
359 Put_message(buf);
360 continue;
2aaf83c2 361 }
5eaef520 362 /* If we got to here, command is a valid menu_line */
363 /* Send the offical command name into the argv */
364 strcpy(argvals[0], command->ml_command);
365 /* Show that we're working on it */
366 Put_message(command->ml_doc);
367 /* Print args that we've already got */
368 for (i = 1; i < argc; i++)
369 {
370 if (!command->ml_args[i].ma_prompt)
371 break;
372 sprintf(buf, "%s%s", command->ml_args[i].ma_prompt, argv[i]);
373 Put_message(buf);
2aaf83c2 374 }
5eaef520 375 /* Get remaining arguments, if any */
376 for (; argc < command->ml_argc; argc++)
377 {
378 if (!Prompt_input(command->ml_args[argc].ma_prompt,
379 argvals[argc], sizeof(argvals[argc])))
380 goto punt_command;
e9db439c 381 }
5eaef520 382 parsed_argc = argc - command->ml_argc;
383 parsed_argv = &(argv[command->ml_argc]);
384 if (command->ml_function != NULLFUNC)
385 {
386 /* If it's got a function, call it */
387 quitflag = command->ml_function(argc, argv);
e9db439c 388 }
5eaef520 389 else if (command->ml_submenu != NULLMENU)
390 {
391 /* Else see if it is a submenu */
392 quitflag = Do_menu(command->ml_submenu, argc, argv);
07c56447 393 }
5eaef520 394 else
395 {
396 /* If it's got neither, something is wrong */
397 Put_message("*INTERNAL ERROR: NO FUNCTION OR MENU FOR LINE*");
398 }
399 if (quitflag == DM_QUIT)
400 {
401 if (cur_ms != NULLMS)
402 {
403 cur_ms = old_cur_ms;
404 destroy_ms(my_ms);
2aaf83c2 405 }
5eaef520 406 if (m->m_exit != NULLFUNC)
407 m->m_exit(m);
408 parsed_argc = 0;
409 return DM_QUIT;
07c56447 410 }
967b7c08 411 punt_command:
5eaef520 412 parsed_argc = 0;
07c56447 413 }
414}
415
5eaef520 416int refresh_screen(void)
142e9b37 417{
5eaef520 418 if (cur_ms != NULLMS)
419 {
420 touchwin(cur_ms->ms_screen);
421 refresh_ms(cur_ms);
142e9b37 422 }
423}
424
425
07c56447 426/* Prompt the user for input in the input window of cur_ms */
5eaef520 427int Prompt_input(char *prompt, char *buf, int buflen)
07c56447 428{
5eaef520 429 int c;
430 char *p;
431 int y, x, oldx, oldy;
432
433 if (cur_ms != NULLMS)
434 {
435 more_flg = 1;
436 getyx(cur_ms->ms_input, y, x);
437 wmove(cur_ms->ms_input, y, 0);
438
439 refresh_screen();
440 waddstr(cur_ms->ms_input, prompt);
441 getyx(cur_ms->ms_input, y, x);
442
443 oldx = x;
444 oldy = y;
445 p = buf;
446 while (1)
447 {
448 wmove(cur_ms->ms_input, y, x);
449 touchwin(cur_ms->ms_screen);
450 wclrtoeol(cur_ms->ms_input);
451 wrefresh(cur_ms->ms_input);
452 c = getchar() & 0x7f;
453 switch (c)
454 {
967b7c08 455 case CTL('C'):
5eaef520 456 *p = '\0';
457 return 0;
967b7c08 458 case CTL('Z'):
5eaef520 459 kill(getpid(), SIGTSTP);
460 touchwin(cur_ms->ms_screen);
461 break;
967b7c08 462 case CTL('L'):
5eaef520 463 wclear(cur_ms->ms_input);
464 wmove(cur_ms->ms_input, 0, 0);
465 waddstr(cur_ms->ms_input, prompt);
466 touchwin(cur_ms->ms_input);
467 wrefresh(cur_ms->ms_screen);
468 getyx(cur_ms->ms_input, y, x);
469 oldy = y;
470 oldx = x;
471 p = buf;
472 break;
6298c97d 473
e9db439c 474 case '\n':
475 case '\r':
5eaef520 476 goto end_input;
477 /* these should be obtained by doing ioctl() on tty */
2aaf83c2 478 case '\b':
479 case '\177':
5eaef520 480 if (p > buf)
481 {
482 p--;
483 x--;
484 if (x < 0)
485 {
486 wmove(cur_ms->ms_input, y, 0);
487 wclrtoeol(cur_ms->ms_input);
488 y--;
7798ebc3 489#ifdef __NetBSD__
5eaef520 490 x = cur_ms->ms_input->maxx - 1;
7798ebc3 491#else
5eaef520 492 x = cur_ms->ms_input->_maxx - 1;
7798ebc3 493#endif
c13d1215 494 }
2aaf83c2 495 }
5eaef520 496 break;
967b7c08 497 case CTL('U'):
498 case CTL('G'):
499 case CTL('['):
5eaef520 500 x = oldx;
501 y = oldy;
502 p = buf;
503 break;
2aaf83c2 504 default:
5eaef520 505 /* (buflen - 1) leaves room for the \0 */
506 if (isprint(c) && (p - buf < buflen - 1))
507 {
508 waddch(cur_ms->ms_input, c);
509 *p++ = c;
510 x++;
7798ebc3 511#ifdef __NetBSD__
5eaef520 512 if (x >= cur_ms->ms_input->maxx)
7798ebc3 513#else
5eaef520 514 if (x >= cur_ms->ms_input->_maxx)
7798ebc3 515#endif
5eaef520 516 {
517 x = 0;
518 y++;
c13d1215 519 }
5eaef520 520 }
521 else
522 putchar(CTL('G'));
523 break;
07c56447 524 }
07c56447 525 }
f659480d 526 end_input:
5eaef520 527 waddch(cur_ms->ms_input, '\n');
528
529 wclrtoeol(cur_ms->ms_input);
530 refresh_ms(cur_ms);
531 *p = '\0';
532 Start_paging();
533 goto gotit;
534 }
535 else
536 {
537 printf("%s", prompt);
538 if (!fgets(buf, buflen, stdin))
539 return 0;
540 if (interrupt)
541 {
542 interrupt = 0;
543 return 0;
facd6784 544 }
5eaef520 545 Start_paging();
546 goto gotit;
07c56447 547 }
6298c97d 548gotit:
5eaef520 549 strcpy(buf, strtrim(buf));
550 return 1;
07c56447 551}
552
2aaf83c2 553int lines_left;
554
555/* Start paging */
556/* This routine will cause the most recently put message to be the
557 one at the top of the screen when a ---More--- prompt is displayed */
5eaef520 558int Start_paging(void)
2aaf83c2 559{
5eaef520 560 if (cur_ms != NULLMS)
561 lines_left = LINES - cur_ms->ms_input_y - 1;
562 else
563 lines_left = 23;
2aaf83c2 564}
565
566/* Turn off paging */
5eaef520 567int Stop_paging(void)
2aaf83c2 568{
5eaef520 569 lines_left = -1;
2aaf83c2 570}
571
f659480d 572/* Print a message in the input window of cur_ms. */
5eaef520 573int Put_message(char *msg)
f659480d 574{
5eaef520 575 char *copy, *line, *s;
576
577 copy = malloc(COLS);
578 s = line = msg;
579 if (log_file)
580 {
581 /* if we're doing logging; we assume that the file has already
582 been opened. */
583 fprintf(log_file, "%s\n", msg);
584 fflush(log_file);
f659480d 585 }
5eaef520 586
587 while (*s++)
588 {
589 if (s - line >= COLS - 1)
590 {
591 strncpy(copy, line, COLS - 1);
592 copy[COLS - 1] = '\0';
593 line += COLS - 1;
594 }
595 else if (*s == '\n')
596 {
597 *s = '\0';
598 strcpy(copy, line);
599 line = ++s;
600 }
601 else
602 continue;
603 Put_line(copy);
604 }
605 Put_line(line);
606 free(copy);
f659480d 607}
608
609/* Will be truncated to COLS characters. */
5eaef520 610int Put_line(char *msg)
07c56447 611{
5eaef520 612 int y, x, i;
613 char *msg1, chr;
614
615 if (!more_flg)
616 return;
617
618 if (lines_left >= 0)
619 {
620 if (--lines_left == 0)
621 {
622 /* Give the user a more prompt */
623 if (cur_ms != NULLMS)
624 {
625 wstandout(cur_ms->ms_input);
626 wprintw(cur_ms->ms_input, "---More---");
627 wstandend(cur_ms->ms_input);
628 refresh_ms(cur_ms);
629 chr = getchar() & 0x7f;/* We do care what it is */
630 if (chr == 'q' || chr == 'Q' || chr == 3 /* ^C */)
631 {
632 more_flg = 0;
633 return;
e9db439c 634 }
5eaef520 635 getyx(cur_ms->ms_input, y, x);
636 /* x is a bitbucket; avoid lint problems */
637 x = x;
638 wmove(cur_ms->ms_input, y, 0);
639 wclrtoeol(cur_ms->ms_input);
e9db439c 640 }
5eaef520 641 else
642 {
643 printf("---More (hit return)---");
644 getchar();
2aaf83c2 645 }
5eaef520 646 Start_paging(); /* Reset lines_left */
2aaf83c2 647 }
648 }
e9db439c 649
5eaef520 650 if (cur_ms != NULLMS)
651 {
652 msg1 = calloc(COLS, 1);
653 strncpy(msg1, msg, COLS - 1);
654 for (i = strlen(msg1); i < COLS - 1; i++)
655 msg1[i] = ' ';
656 wprintw(cur_ms->ms_input, "%s\n", msg1);
2aaf83c2 657 }
5eaef520 658 else
659 puts(msg);
07c56447 660}
661
662/* Refresh a menu_screen onto the real screen */
5eaef520 663int refresh_ms(struct menu_screen *ms)
07c56447 664{
5eaef520 665 wrefresh(ms->ms_title);
666 wrefresh(ms->ms_menu);
667 wrefresh(ms->ms_input);
2aaf83c2 668}
669
670/* Parse buf into a list of words, which will be placed in strings specified by
671 argv. Space for these strings must have already been allocated.
672 Only the first n characters of each word will be copied */
5eaef520 673int Parse_words(char *buf, char *argv[], int n)
2aaf83c2 674{
5eaef520 675 char *start, *end; /* For sausage machine */
676 int argc;
677
678 start = buf;
679 for (argc = 0; argc < MAX_ARGC; argc++)
680 {
681 while (isspace(*start))
682 start++; /* Kill whitespace */
683 if (*start == '\0')
684 break; /* Nothing left */
685 /* Now find the end of the word */
686 for (end = start; *end != '\0' && !isspace(*end); end++)
687 ;
688 strncpy(argv[argc], start, MIN(end - start, n)); /* Copy it */
689 argv[argc][MIN(end - start, n - 1)] = '\0'; /* Terminate */
690 start = end;
2aaf83c2 691 }
5eaef520 692 return argc;
2aaf83c2 693}
694
695/* This is the internal form of Find_command, which recursively searches
696 for a menu_line with command command in the specified menu */
697/* It will search to a maximum depth of d */
5eaef520 698struct menu_line *find_command_from(char *c, struct menu *m, int d)
2aaf83c2 699{
5eaef520 700 int line;
701 struct menu_line *maybe;
702
703 if (d < 0)
704 return NULL; /* Too deep! */
705 for (line = 0; line < m->m_length; line++)
706 {
707 if (!strcmp(c, m->m_lines[line].ml_command))
708 return &m->m_lines[line];
73b2adba 709 }
5eaef520 710 for (line = 0; line < m->m_length; line++)
711 {
712 if (m->m_lines[line].ml_submenu != NULLMENU &&
713 (maybe = find_command_from(c, m->m_lines[line].ml_submenu, d - 1)))
714 return maybe;
2aaf83c2 715 }
5eaef520 716 /* If we got to here, nothing works */
717 return NULL;
07c56447 718}
2aaf83c2 719
720/* Find_command searches down the current menu tree */
721/* And returns a pointer to a menu_line with the specified command name */
722/* It returns (struct menu_line *) 0 if none is found */
5eaef520 723struct menu_line *Find_command(Menu *m, char *command)
2aaf83c2 724{
5eaef520 725 if (m == NULLMENU)
726 return NULL;
727 else
728 return find_command_from(command, m, MAX_MENU_DEPTH);
2aaf83c2 729}
22705d2b 730
5eaef520 731int toggle_logging(int argc, char *argv[])
859891c0 732{
5eaef520 733 int pid;
734 char buf[BUFSIZ];
735
736 if (!log_file)
737 {
738 pid = getpid();
739 if (!whoami)
740 {
741 Put_message("I've lost my SENSE of DIRECTION! I have no IDEA who I AM!");
742 Put_message("My God... You've turned him into a DEMOCRAT!!");
743 Put_message(" -- Doonesbury");
744 Put_message("");
745 Put_message("translation: your log file can be found in \"/usr/tmp/a.out.pid\".");
746 whoami = "a.out";
747 sprintf(buf, "/usr/tmp/%s-log.%d", whoami, pid);
859891c0 748 }
5eaef520 749 else
750 sprintf(buf, "/usr/tmp/%s-log.%d", whoami, pid);
751
752 /* open the file */
753 log_file = fopen(buf, "a");
754
755 if (!log_file)
756 Put_message("Open of log file failed. Logging is not on.");
757 else
758 Put_message("Log file successfully opened.");
859891c0 759 }
5eaef520 760 else
761 { /* log_file is a valid pointer; turn off logging. */
762 fflush(log_file);
763 fclose(log_file);
764 log_file = NULL;
765 Put_message("Logging off.");
766 }
767 return DM_NORMAL;
768}
This page took 0.212641 seconds and 5 git commands to generate.