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