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