]> andersk Git - moira.git/blame - clients/moira/menu.c
client support for get_host_by_owner
[moira.git] / clients / moira / menu.c
CommitLineData
c441a31a 1/* $Id$
2aaf83c2 2 *
07c56447 3 * Generic menu system module.
4 *
7ac48069 5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology.
6 * For copying and distribution information, see the file
7 * <mit-copyright.h>.
07c56447 8 */
9
babbc197 10#include <mit-copyright.h>
7ac48069 11#include <moira.h>
12#include "menu.h"
13
14#include <ctype.h>
ea0caf4a 15#ifdef HAVE_CURSES
7ac48069 16#include <curses.h>
ea0caf4a 17#endif
7ac48069 18#include <signal.h>
07c56447 19#include <stdio.h>
7798ebc3 20#include <stdlib.h>
cde7e985 21#include <string.h>
533bacb3 22#ifdef HAVE_UNISTD_H
cde7e985 23#include <unistd.h>
533bacb3 24#endif
25
26#ifdef _WIN32
27#include <windows.h>
28#include <conio.h>
e9a6aa9a 29#include <process.h>
533bacb3 30#ifdef getchar
31#undef getchar
32#endif
33#define getchar() _getch()
34#define getpid _getpid
35#endif /* _WIN32 */
7ac48069 36
37RCSID("$Header$");
07c56447 38
4ea05fb6 39#ifdef MAX
40#undef MAX
41#undef MIN
42#endif
5eaef520 43#define MAX(A, B) ((A) > (B) ? (A) : (B))
44#define MIN(A, B) ((A) < (B) ? (A) : (B))
967b7c08 45#define CTL(ch) ((ch) & 037)
07c56447 46
47#define MIN_INPUT 2 /* Minimum number of lines for input window */
48
facd6784 49extern int interrupt; /* will be set if ^C is received */
859891c0 50extern char *whoami;
51
52FILE *log_file = (FILE *) NULL; /* file stream of log file */
e9db439c 53int more_flg = 1;
2aaf83c2 54
07c56447 55/* Structure for holding current displayed menu */
56struct menu_screen {
ea0caf4a 57#ifdef HAVE_CURSES
5eaef520 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 */
ea0caf4a 62#endif /* HAVE_CURSES */
5eaef520 63 int ms_input_y; /* Input subwindow reference coordinate */
64} *cur_ms;
07c56447 65
ea0caf4a 66#ifndef HAVE_CURSES
67int COLS;
68#endif
69
2aaf83c2 70#define NULLMS ((struct menu_screen *) 0)
71
72Menu *top_menu; /* Root for command search */
11317e48 73int parsed_argc; /* used by extern routines to get additional */
74char **parsed_argv; /* comand line input */
2aaf83c2 75
7ac48069 76int Parse_words(char *buf, char *argv[], int n);
77void refresh_ms(struct menu_screen *ms);
78void Put_line(char *msg);
5652b7a9 79void menu_com_err_hook(const char *who, long code,
80 const char *fmt, va_list ap);
7ac48069 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
6298c97d 87/*
88 * Hook function to cause error messages to be printed through
5652b7a9 89 * curses instead of around it.
6298c97d 90 */
91
5652b7a9 92void menu_com_err_hook(const char *who, long code, const char *fmt, va_list ap)
6298c97d 93{
5eaef520 94 char buf[BUFSIZ], *cp;
95
1bf73297 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 }
5eaef520 109 if (code)
110 {
111 strcpy(cp, error_message(code));
112 while (*cp)
113 cp++;
6298c97d 114 }
7ac48069 115 vsprintf(cp, fmt, ap);
5eaef520 116 Put_message(buf);
6298c97d 117}
118
ea0caf4a 119#ifdef HAVE_CURSES
07c56447 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 */
7ac48069 126void Start_menu(Menu *m)
07c56447 127{
44d12d58 128 void (*old_hook)(const char *, long, const char *, va_list) =
5652b7a9 129 set_com_err_hook(menu_com_err_hook);
d7cef8a3 130#ifdef CURSES_HAS_NEWTERM
131 SCREEN *scrn = newterm(NULL, stdout, stdin);
132#else
133 WINDOW *scrn = initscr();
134#endif
135 if (!scrn)
5eaef520 136 {
d7cef8a3 137 fputs("Can't initialize curses!\nReverting to -nomenu mode\n\n", stderr);
5eaef520 138 Start_no_menu(m);
07c56447 139 }
5eaef520 140 else
141 {
d7cef8a3 142#ifdef CURSES_HAS_NEWTERM
143 set_term(scrn);
2e09ee40 144 endwin();
145 initscr();
d7cef8a3 146#endif
5eaef520 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);
d7cef8a3 153 Cleanup_menu();
5eaef520 154 }
155 set_com_err_hook(old_hook);
967b7c08 156}
157
7ac48069 158void Cleanup_menu(void)
967b7c08 159{
5eaef520 160 if (cur_ms)
161 {
162 wclear(cur_ms->ms_screen);
163 wrefresh(cur_ms->ms_screen);
d7cef8a3 164 endwin();
967b7c08 165 }
07c56447 166}
5eaef520 167
07c56447 168/*
169 * Create a new menu screen template with the specified menu length
170 * and return it.
171 */
5eaef520 172struct menu_screen *make_ms(int length)
07c56447 173{
5eaef520 174 struct menu_screen *ms;
07c56447 175
5eaef520 176 if (MAX_TITLE + length + MIN_INPUT > LINES)
177 {
178 fputs("Menu too big!\n", stderr);
179 exit(2);
07c56447 180 }
181
5eaef520 182 ms = malloc(sizeof(struct menu_screen));
07c56447 183
5eaef520 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);
07c56447 190
5eaef520 191 scrollok(ms->ms_input, TRUE);
192 wmove(ms->ms_input, 0, 0);
193 wclear(ms->ms_screen);
07c56447 194
5eaef520 195 return ms;
07c56447 196}
197
198/*
199 * This routine destroys a menu_screen.
200 */
7ac48069 201void destroy_ms(struct menu_screen *ms)
07c56447 202{
5eaef520 203 delwin(ms->ms_title);
204 delwin(ms->ms_menu);
205 delwin(ms->ms_input);
206 delwin(ms->ms_screen);
207 free(ms);
07c56447 208}
ea0caf4a 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}
07c56447 219
220/*
221 * This guy actually puts up the menu
967b7c08 222 * Note: if margc < 0, no 'r' option will be displayed (i.e., on the
223 * top level menu)
07c56447 224 */
5eaef520 225int Do_menu(Menu *m, int margc, char *margv[])
07c56447 226{
5eaef520 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;
7ac48069 233 struct menu_line *command;
5eaef520 234 int argc;
235 int quitflag, is_topmenu = (margc < 0);
5eaef520 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++;
11317e48 251 }
252 }
253
5eaef520 254 parsed_argc = 0;
255
ea0caf4a 256#ifdef HAVE_CURSES
5eaef520 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);
2349681b 268 wmove(my_ms->ms_title, 0, MAX(0, (COLS - (int)strlen(m->m_title)) >> 1));
5eaef520 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);
2aaf83c2 284 }
5eaef520 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);
967b7c08 291 }
5eaef520 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
ea0caf4a 297#endif /* HAVE_CURSES */
5eaef520 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);
33a56ee9 307 }
5eaef520 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.");
07c56447 313 }
07c56447 314
5eaef520 315 for (;;)
316 {
317 /* This will be set by a return val from func or submenu */
318 quitflag = DM_NORMAL;
ea0caf4a 319#ifdef HAVE_CURSES
5eaef520 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);
c3e65787 325 }
ea0caf4a 326#endif /* HAVE_CURSES */
5eaef520 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;
e85f474d 336 }
5eaef520 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;
e9db439c 355 }
5eaef520 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 */
ea0caf4a 363#ifdef HAVE_CURSES
5eaef520 364 if (cur_ms != NULLMS)
365 {
366 cur_ms = old_cur_ms;
367 destroy_ms(my_ms);
2aaf83c2 368 }
ea0caf4a 369#endif /* HAVE_CURSES */
5eaef520 370 if (m->m_exit != NULLFUNC)
371 m->m_exit(m);
372 return *argv[0] == 'r' ? DM_NORMAL : DM_QUIT;
e9db439c 373 }
5eaef520 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);
33a56ee9 383 }
5eaef520 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;
33a56ee9 389 }
5eaef520 390 else if (!strcmp(argv[0], "t") || !strcmp(argv[0], "toggle"))
391 {
392 toggle_logging(argc, argv);
393 continue;
e9db439c 394 }
5eaef520 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;
2aaf83c2 401 }
5eaef520 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);
2aaf83c2 414 }
5eaef520 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;
e9db439c 421 }
5eaef520 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);
e9db439c 428 }
5eaef520 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);
07c56447 433 }
5eaef520 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 {
ea0caf4a 441#ifdef HAVE_CURSES
5eaef520 442 if (cur_ms != NULLMS)
443 {
444 cur_ms = old_cur_ms;
445 destroy_ms(my_ms);
2aaf83c2 446 }
ea0caf4a 447#endif /* HAVE_CURSES */
5eaef520 448 if (m->m_exit != NULLFUNC)
449 m->m_exit(m);
450 parsed_argc = 0;
451 return DM_QUIT;
07c56447 452 }
967b7c08 453 punt_command:
5eaef520 454 parsed_argc = 0;
07c56447 455 }
456}
457
7ac48069 458void refresh_screen(void)
142e9b37 459{
ea0caf4a 460#ifdef HAVE_CURSES
5eaef520 461 if (cur_ms != NULLMS)
462 {
463 touchwin(cur_ms->ms_screen);
464 refresh_ms(cur_ms);
142e9b37 465 }
ea0caf4a 466#endif /* HAVE_CURSES */
142e9b37 467}
468
469
07c56447 470/* Prompt the user for input in the input window of cur_ms */
5eaef520 471int Prompt_input(char *prompt, char *buf, int buflen)
07c56447 472{
533bacb3 473#ifdef HAVE_CURSES
5eaef520 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 {
967b7c08 500 case CTL('C'):
5eaef520 501 *p = '\0';
502 return 0;
967b7c08 503 case CTL('Z'):
5eaef520 504 kill(getpid(), SIGTSTP);
505 touchwin(cur_ms->ms_screen);
506 break;
967b7c08 507 case CTL('L'):
5eaef520 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;
6298c97d 518
e9db439c 519 case '\n':
520 case '\r':
5eaef520 521 goto end_input;
522 /* these should be obtained by doing ioctl() on tty */
2aaf83c2 523 case '\b':
524 case '\177':
5eaef520 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--;
ea0caf4a 534 x = getmaxx(cur_ms->ms_input) - 1;
c13d1215 535 }
2aaf83c2 536 }
5eaef520 537 break;
967b7c08 538 case CTL('U'):
539 case CTL('G'):
540 case CTL('['):
5eaef520 541 x = oldx;
542 y = oldy;
543 p = buf;
544 break;
2aaf83c2 545 default:
5eaef520 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++;
ea0caf4a 552 if (x >= getmaxx(cur_ms->ms_input))
5eaef520 553 {
554 x = 0;
555 y++;
c13d1215 556 }
5eaef520 557 }
558 else
559 putchar(CTL('G'));
560 break;
07c56447 561 }
07c56447 562 }
f659480d 563 end_input:
5eaef520 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();
fca49f53 570 strcpy(buf, strtrim(buf));
571 return 1;
5eaef520 572 }
573 else
ea0caf4a 574#endif /* HAVE_CURSES */
5eaef520 575 {
fca49f53 576 char bigbuf[BUFSIZ];
577
5eaef520 578 printf("%s", prompt);
fca49f53 579 if (!fgets(bigbuf, BUFSIZ, stdin))
5eaef520 580 return 0;
581 if (interrupt)
582 {
583 interrupt = 0;
584 return 0;
facd6784 585 }
5eaef520 586 Start_paging();
fca49f53 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;
07c56447 593 }
594}
595
2aaf83c2 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 */
7ac48069 601void Start_paging(void)
2aaf83c2 602{
ea0caf4a 603#ifdef HAVE_CURSES
5eaef520 604 if (cur_ms != NULLMS)
605 lines_left = LINES - cur_ms->ms_input_y - 1;
606 else
ea0caf4a 607#endif /* HAVE_CURSES */
5eaef520 608 lines_left = 23;
2aaf83c2 609}
610
611/* Turn off paging */
7ac48069 612void Stop_paging(void)
2aaf83c2 613{
5eaef520 614 lines_left = -1;
2aaf83c2 615}
616
f659480d 617/* Print a message in the input window of cur_ms. */
7ac48069 618void Put_message(char *msg)
f659480d 619{
5eaef520 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);
f659480d 630 }
5eaef520 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);
f659480d 652}
653
654/* Will be truncated to COLS characters. */
7ac48069 655void Put_line(char *msg)
07c56447 656{
5eaef520 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 */
ea0caf4a 665#ifdef HAVE_CURSES
5eaef520 666 if (cur_ms != NULLMS)
667 {
533bacb3 668 int x, y;
669 char chr;
670
5eaef520 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;
e9db439c 680 }
5eaef520 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);
e9db439c 686 }
5eaef520 687 else
ea0caf4a 688#endif /* HAVE_CURSES */
5eaef520 689 {
690 printf("---More (hit return)---");
691 getchar();
2aaf83c2 692 }
5eaef520 693 Start_paging(); /* Reset lines_left */
2aaf83c2 694 }
695 }
e9db439c 696
ea0caf4a 697#ifdef HAVE_CURSES
5eaef520 698 if (cur_ms != NULLMS)
699 {
533bacb3 700 int i;
701 char *msg1;
702
5eaef520 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);
2aaf83c2 708 }
5eaef520 709 else
ea0caf4a 710#endif /* HAVE_CURSES */
5eaef520 711 puts(msg);
07c56447 712}
713
ea0caf4a 714#ifdef HAVE_CURSES
07c56447 715/* Refresh a menu_screen onto the real screen */
7ac48069 716void refresh_ms(struct menu_screen *ms)
07c56447 717{
5eaef520 718 wrefresh(ms->ms_title);
719 wrefresh(ms->ms_menu);
720 wrefresh(ms->ms_input);
2aaf83c2 721}
ea0caf4a 722#endif /* HAVE_CURSES */
2aaf83c2 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 */
5eaef520 727int Parse_words(char *buf, char *argv[], int n)
2aaf83c2 728{
5eaef520 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;
2aaf83c2 745 }
5eaef520 746 return argc;
2aaf83c2 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 */
5eaef520 752struct menu_line *find_command_from(char *c, struct menu *m, int d)
2aaf83c2 753{
5eaef520 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];
73b2adba 763 }
5eaef520 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;
2aaf83c2 769 }
5eaef520 770 /* If we got to here, nothing works */
771 return NULL;
07c56447 772}
2aaf83c2 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 */
5eaef520 777struct menu_line *Find_command(Menu *m, char *command)
2aaf83c2 778{
5eaef520 779 if (m == NULLMENU)
780 return NULL;
781 else
782 return find_command_from(command, m, MAX_MENU_DEPTH);
2aaf83c2 783}
22705d2b 784
533bacb3 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
5eaef520 802int toggle_logging(int argc, char *argv[])
859891c0 803{
5eaef520 804 char buf[BUFSIZ];
805
806 if (!log_file)
807 {
533bacb3 808 sprintf(buf, "%s/%s-log.%ld", get_tmp_dir(), whoami, (long)getpid());
5eaef520 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.");
859891c0 817 }
5eaef520 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.409753 seconds and 5 git commands to generate.