source: trunk/third/moira/clients/moira/menu.c @ 23740

Revision 23740, 19.1 KB checked in by broder, 16 years ago (diff)
In moira: * New CVS snapshot (Trac: #195) * Drop patches that have been incorporated upstream. * Update to build without krb4 on systems that no longer have it. This doesn't build yet on squeeze, which lacks a krb4 library, but I'm committing now before I start hacking away at a patch to fix that.
Line 
1/* $Id: menu.c,v 1.59 2000-03-16 22:23:49 zacheiss Exp $
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
37RCSID("$Header: /afs/athena.mit.edu/astaff/project/moiradev/repository/moira/clients/moira/menu.c,v 1.59 2000-03-16 22:23:49 zacheiss Exp $");
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
49extern int interrupt;           /* will be set if ^C is received */
50extern char *whoami;
51
52FILE *log_file = (FILE *) NULL;         /* file stream of log file */
53int more_flg = 1;
54
55/* Structure for holding current displayed menu */
56struct 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
67int COLS;
68#endif
69
70#define NULLMS ((struct menu_screen *) 0)
71
72Menu *top_menu;                 /* Root for command search */
73int parsed_argc;                /* used by extern routines to get additional */
74char **parsed_argv;             /*   comand line input */
75
76int Parse_words(char *buf, char *argv[], int n);
77void refresh_ms(struct menu_screen *ms);
78void Put_line(char *msg);
79void menu_com_err_hook(const char *who, long code,
80                       const char *fmt, va_list ap);
81struct menu_screen *make_ms(int length);
82void destroy_ms(struct menu_screen *ms);
83struct menu_line *find_command_from(char *c, struct menu *m, int d);
84struct menu_line *Find_command(Menu *m, char *command);
85int 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
92void 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 */
126void 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
158void 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 */
172struct 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 */
201void 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 */
212void 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 */
225int 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
458void 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 */
471int 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
596int 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 */
601void 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 */
612void Stop_paging(void)
613{
614  lines_left = -1;
615}
616
617/* Print a message in the input window of cur_ms.  */
618void 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.  */
655void 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 */
716void 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 */
727int 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 */
752struct 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 */
777struct 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
785static 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
802int 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}
Note: See TracBrowser for help on using the repository browser.