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