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