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