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