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