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