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