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