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