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