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