mike@milhow2.UUCP (Mike Howard) (07/03/90)
Posting-number: Volume 13, Issue 83 Submitted-by: mike@milhow2.UUCP (Mike Howard) Archive-name: menu_mh/patch01 Please post and file in volume-11/menu_mh Thanks Mike Howard how%milhow1@uu.net ---------------------------------------cut there----------------------------- Importance: High These patches implement the following: - dumb_menu goes into an infinite loop if ^D is entered. - a MENU_PATH variable and search for menu is implemented. -m is supported but surpressed. Menu name may either be the default or taken from the command line. - all calls to malloc() and realloc() are tested for success. [this was more to avoid redicule than need - if anyone builds a menu which exceeds memory on any machine, it is probably too big to fit on the screen :-) ] Mike Howard how@milhow1.uunet.uu.net ------------------------cut here---------------------------------- Index: patchlevel.h *** ./version1/patchlevel.h Sat Mar 17 11:50:46 1990 --- ./patchlevel.h Sat Mar 17 11:40:01 1990 *************** *** 0 **** --- 1 ---- + #define PATCHLEVEL 1 Index: MANIFEST *** ./version1/MANIFEST Sat Mar 17 09:49:50 1990 --- ./MANIFEST Sat Mar 17 11:55:40 1990 *************** *** 9,11 **** --- 9,12 ---- dumb_menu.y 1 menu.def 1 sub.menu 1 + patchlevel.h 1 Index: dumb_menu.y *** ./version1/dumb_menu.y Sat Mar 17 09:49:54 1990 --- ./dumb_menu.y Sat Mar 17 10:41:49 1990 *************** *** 1,5 **** %{ ! /* @(#)dumb_menu.y 1.3 90/03/08 */ static char *cpy_str = "Copyright (c), Mike Howard, 1990, all rights reserved"; --- 1,5 ---- %{ ! /* @(#)dumb_menu.y 1.4 90/03/17 */ static char *cpy_str = "Copyright (c), Mike Howard, 1990, all rights reserved"; *************** *** 47,54 **** char *menu_title; ! char *malloc(); ! char *realloc(); int lex_errors; int yacc_errors; --- 47,54 ---- char *menu_title; ! char *Malloc(); ! char *Realloc(); int lex_errors; int yacc_errors; *************** *** 62,67 **** --- 62,72 ---- /* Menus begin with a title definition title { text for the title } + This is followed by zero or more of the following parameters, which + do the `obvious' things: + + bold clear always-show + This is followed by one or more menu-item definitions of the form: item { prompt } { shell command } *************** *** 69,77 **** parm "name" { prompt } ; ! the crud in between braces may contain any character, including escapped braces and back-slash (\). ! The crud in between the double quotes may ONLY contain letters, digits, and underscores; Sub-menus are formed by running dumb_menu as the shell process, pointed --- 74,82 ---- parm "name" { prompt } ; ! the text in between braces may contain any character, including escapped braces and back-slash (\). ! The text in between the double quotes may ONLY contain letters, digits, and underscores; Sub-menus are formed by running dumb_menu as the shell process, pointed *************** *** 174,186 **** extern char *optarg; extern int optind, opterr; int tty_in; - FILE *tty_file; int argcc; char **argvv; char *progname; char *in_fname = "stdin"; ! char *menu_fname = "./menu.def"; char *shell_path = "/bin/sh"; char *cat_path = "/bin/cat"; char *cmd_path; char *cmd_name; --- 179,194 ---- extern char *optarg; extern int optind, opterr; int tty_in; int argcc; char **argvv; char *progname; char *in_fname = "stdin"; ! char *menu_fname; ! #define MENU_FNAME "menu.def" char *shell_path = "/bin/sh"; + char *menu_path; + #define DEFAULT_MENU_PATH_WITH_HOME "%s:/usr/local/lib/dumb_menu" + #define DEFAULT_MENU_PATH_WO_HOME "/usr/local/lib/dumb_menu" char *cat_path = "/bin/cat"; char *cmd_path; char *cmd_name; *************** *** 195,201 **** char *hlp[] = { "Option Function", ! "-m file set menu-definition file name to 'file' (menu.def)", "-s path path to shell to execute scripts", "-c path path to 'cat' for simple debug mode", "-v make command execution verbose (via set -xv)", --- 203,209 ---- char *hlp[] = { "Option Function", ! "-M path menu path", "-s path path to shell to execute scripts", "-c path path to 'cat' for simple debug mode", "-v make command execution verbose (via set -xv)", *************** *** 232,239 **** --- 240,258 ---- printf("%s: '%s'\n", selected_parms->prompt, selected_parms->identifier); } + + init_terminal(); + + display_menu(); + exit(0); } + close(0); + close(1); + dup(tty_in); + dup(tty_in); + close(tty_in); + init_terminal(); do_menu(); *************** *** 248,254 **** extern char *optarg; extern int optind, opterr; ! while ((c = getopt(argc, argv, "hcsm:vD")) != EOF) { switch (c) { case 'h': for (i=0;hlp[i];i++) --- 267,273 ---- extern char *optarg; extern int optind, opterr; ! while ((c = getopt(argc, argv, "hcsm:M:vD")) != EOF) { switch (c) { case 'h': for (i=0;hlp[i];i++) *************** *** 261,268 **** --- 280,294 ---- cat_path = optarg; break; case 'm': + /* this option is for backward compatability. I did not handle + menu file name specification correctly in the original version + and am too lazy to change everything I have done. It will come + out some day. */ menu_fname = optarg; break; + case 'M': + menu_path = optarg; + break; case 'v': verbose++; break; *************** *** 277,296 **** argcc = argc; argvv = argv; progname = argv[0]; ! if (strcmp(menu_fname, "-")) { ! close(0); ! if (open(menu_fname, O_RDONLY) < 0) { ! char buf[80]; ! ! sprintf(buf, "cannot open menu definition: %s", menu_fname); ! fatal(buf); ! } ! } ! ! if ((tty_in = open("/dev/tty", O_RDONLY)) < 0) fatal("cannot open tty - must be run interactively"); - tty_file = fdopen(tty_in, "r"); cmd_path = debug_mode ? cat_path : shell_path; if (cmd_name = strrchr(cmd_path, '/')) --- 303,314 ---- argcc = argc; argvv = argv; progname = argv[0]; ! if (!menu_fname) ! menu_fname = optind == argc ? MENU_FNAME : argv[optind]; ! open_menu_file(); ! if ((tty_in = open("/dev/tty", O_RDWR)) < 0) fatal("cannot open tty - must be run interactively"); cmd_path = debug_mode ? cat_path : shell_path; if (cmd_name = strrchr(cmd_path, '/')) *************** *** 303,313 **** char *identifier; char *prompt; { ! struct parm *parm_ptr = (struct parm *)malloc(sizeof(struct parm)); - if (!parm_ptr) - fatal("malloc() error"); - parm_ptr->next = (struct parm *)0; parm_ptr->prompt = prompt; parm_ptr->identifier = identifier; --- 321,328 ---- char *identifier; char *prompt; { ! struct parm *parm_ptr = (struct parm *)Malloc(sizeof(struct parm)); parm_ptr->next = (struct parm *)0; parm_ptr->prompt = prompt; parm_ptr->identifier = identifier; *************** *** 321,331 **** char *command; struct parm *parms; { ! struct item *item_ptr = (struct item *)malloc(sizeof(struct item)); - if (!item_ptr) - fatal("malloc() error"); - item_ptr->next = (struct item *)0; item_ptr->prompt = prompt; item_ptr->command = command; --- 336,343 ---- char *command; struct parm *parms; { ! struct item *item_ptr = (struct item *)Malloc(sizeof(struct item)); item_ptr->next = (struct item *)0; item_ptr->prompt = prompt; item_ptr->command = command; *************** *** 412,418 **** int rsp; display_menu(); ! fgets(buf, 80, tty_file); if (cp = strchr(buf, '\n')) *cp = '\0'; --- 424,434 ---- int rsp; display_menu(); ! if (!fgets(buf, 80, stdin) && feof(stdin)) { ! putc('\n', stdout); ! exit(0); ! } ! if (cp = strchr(buf, '\n')) *cp = '\0'; *************** *** 449,459 **** printf("%s: ", selected_parms->prompt); fflush(stdout); ! fgets(buf, 255, tty_file); if (cp = strchr(buf, '\n')) *cp = '\0'; ! strcpy(selected_parms->value = malloc(strlen(buf) + 1), buf); selected_parms = selected_parms->next; } --- 465,475 ---- printf("%s: ", selected_parms->prompt); fflush(stdout); ! fgets(buf, 255, stdin); if (cp = strchr(buf, '\n')) *cp = '\0'; ! strcpy(selected_parms->value = Malloc(strlen(buf) + 1), buf); selected_parms = selected_parms->next; } *************** *** 476,485 **** if ( !(pid = fork()) ) { /* reset signals so that DEL,... work correctly */ reset_signals(); ! close(0); ! dup(tty_in); ! close(tty_in); ! fclose(tty_file); execl(cmd_path, cmd_name, tmp_fname, (char *)0); fatal("exec of command failed"); } --- 492,499 ---- if ( !(pid = fork()) ) { /* reset signals so that DEL,... work correctly */ reset_signals(); ! close(2); ! dup(0); execl(cmd_path, cmd_name, tmp_fname, (char *)0); fatal("exec of command failed"); } *************** *** 492,498 **** printf("[Press Return to Continue]"); fflush(stdout); ! fgets(buf, 80, tty_file); } } reset_signals(); --- 506,512 ---- printf("[Press Return to Continue]"); fflush(stdout); ! fgets(buf, 80, stdin); } } reset_signals(); *************** *** 580,586 **** while ((wait_ret = wait(&status)) != pid) { /* test to see if child is still there - if not, then return */ if (kill(pid, 0) < 0) ! return; } } --- 594,600 ---- while ((wait_ret = wait(&status)) != pid) { /* test to see if child is still there - if not, then return */ if (kill(pid, 0) < 0) ! break; } } *************** *** 610,613 **** --- 624,730 ---- signal(SIGQUIT, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGCLD, SIG_DFL); + } + + open_menu_file() + { + int menu_fd; + char *getenv(); + + /* check to see if we are reading from stdin */ + if (!strcmp(menu_fname, "-")) + return; + + /* absolute paths and ./<file-name> paths over-ride path search */ + if (menu_fname[0] == '/' || !strncmp(menu_fname, "./", 2)) { + if ((menu_fd = open(menu_fname, O_RDONLY)) < 0) + fatal("cannot open menu file"); + close(0); + dup(menu_fd); + close(menu_fd); + return; + } + + /* search for named menu along the menu path */ + if (menu_path || (menu_path = getenv("MENU_PATH"))) + return search_menu_path(menu_path, menu_fname); + + /* build a default menu path */ + { + char *home; + char buf[256]; + + home = getenv("HOME"); + sprintf(buf, home ? DEFAULT_MENU_PATH_WITH_HOME : + DEFAULT_MENU_PATH_WO_HOME, home); + return search_menu_path(buf, menu_fname); + } + } + + search_menu_path(path, fname) + char *path; + char *fname; + { + char *cp = path; + int size = 256; + int len; + char *buf = Malloc(256); + int menu_fd; + + while (cp) { + if (cp = strchr(path, ':')) + *cp++ = '\0'; + if (size < (len = strlen(path) + strlen(fname) + 2)) { + buf = Realloc(buf, len); + size = len; + } + + strcpy(buf, path); + len = strlen(buf); + if (buf[len-1] != '/') + buf[len++] = '/'; + strcpy(buf + len, fname); + + if ((menu_fd = open(buf, O_RDONLY)) >= 0) { + free(buf); + close(0); + dup(menu_fd); + close(menu_fd); + return; + } + path = cp; + } + + fatal("cannot open menu definition"); + } + + char *Malloc(size) + unsigned size; + { + char *malloc(); + char *cp = malloc(size); + + if (!cp) + fatal("out of memory in Malloc"); + + return cp; + } + + char *Realloc(ptr, size) + char *ptr; + unsigned size; + { + char *realloc(); + char *cp = realloc(ptr, size); + + if (!cp) + fatal("out of memory in Realloc"); + + return cp; + } + + yyerror(s) + char *s; + { + printf("%s\n", s); } Index: dumb_menu.l *** ./version1/dumb_menu.l Sat Mar 17 09:49:53 1990 --- ./dumb_menu.l Sat Mar 17 10:41:49 1990 *************** *** 1,4 **** ! /* @(#)dumb_menu.l 1.2 90/03/08 */ /* copyrite (c) Miller/Howard Investments, 1990 */ %{ --- 1,4 ---- ! /* @(#)dumb_menu.l 1.3 90/03/17 */ /* copyrite (c) Miller/Howard Investments, 1990 */ %{ *************** *** 8,13 **** --- 8,15 ---- #include <ctype.h> char *saved_text; + char *Malloc(); + char *Realloc(); %} /* global definitions */ *************** *** 76,82 **** static int saved_size; if (!saved_text) { ! memset(saved_text = malloc(INIT_SIZE), '\0', INIT_SIZE); room_left = INIT_SIZE; saved_size = INIT_SIZE; saved_length = 0; --- 78,84 ---- static int saved_size; if (!saved_text) { ! memset(saved_text = Malloc(INIT_SIZE), '\0', INIT_SIZE); room_left = INIT_SIZE; saved_size = INIT_SIZE; saved_length = 0; *************** *** 84,90 **** len++; /* inc len to account for terminating null */ while (len >= room_left) { ! saved_text = realloc(saved_text, saved_size += INC_SIZE); room_left += INC_SIZE; } --- 86,92 ---- len++; /* inc len to account for terminating null */ while (len >= room_left) { ! saved_text = Realloc(saved_text, saved_size += INC_SIZE); room_left += INC_SIZE; } *************** *** 114,120 **** /* is it all white? */ if (!*cp && cp > saved_text) { ! saved_text = realloc(saved_text, 1); *saved_text = '\0'; return; } --- 116,122 ---- /* is it all white? */ if (!*cp && cp > saved_text) { ! saved_text = Realloc(saved_text, 1); *saved_text = '\0'; return; } *************** *** 124,130 **** char *tmp; int len; ! tmp = malloc(len = strlen(cp) + 1); memcpy(tmp, cp, len); free(saved_text); saved_text = tmp; --- 126,132 ---- char *tmp; int len; ! tmp = Malloc(len = strlen(cp) + 1); memcpy(tmp, cp, len); free(saved_text); saved_text = tmp; *************** *** 132,140 **** return; } ! saved_text = realloc(saved_text, strlen(saved_text) + 1); } - - #ifdef yywrap - #undef yywrap - #endif --- 134,138 ---- return; } ! saved_text = Realloc(saved_text, strlen(saved_text) + 1); } Index: dumb_menu.1 *** ./version1/dumb_menu.1 Sat Mar 17 09:49:52 1990 --- ./dumb_menu.1 Sat Mar 17 10:41:49 1990 *************** *** 1,17 **** . \" -*- nroff -*- ! . \" @(#)dumb_menu.1 1.2 90/03/08 .DA March 8, 1990 .TH DUMB_MENU 1 "local" .SH NAME dumb_menu \- executes a simple minded menu .SH SYNOPSIS .B dumb_menu ! [ -h | options ] .SH DESCRIPTION .PP ! .B -m path ! sets the path to the menu definition file. Default is ! .I ./menu.def. .PP .B -s path sets path for the shell which will execute the selected menu command. --- 1,32 ---- . \" -*- nroff -*- ! . \" @(#)dumb_menu.1 1.3 90/03/17 .DA March 8, 1990 .TH DUMB_MENU 1 "local" .SH NAME dumb_menu \- executes a simple minded menu .SH SYNOPSIS .B dumb_menu ! [ -h | options ] [menu defintion file] .SH DESCRIPTION .PP ! .B dumb_menu ! executes the menu defined in the optionally specified menu definition ! file. ! The default value is ! .I menu.def. ! If the menu definition file name begins with a slash (/) or dot-slash (./), ! then that absolute file is used. ! If not, then the menu path is searched for a matching file name. ! The menu path is a colon separated string of absolute directory names ! modelled after the PATH environment variable. ! The default menu path is: $HOME:/usr/local/lib/dumb_menu ! .PP ! .B -M path ! sets the search path for the menu definition file. ! If specified, this path is used. ! If not specified, the environment is checked to see if there is ! a variable named ! .B MENU_PATH. .PP .B -s path sets path for the shell which will execute the selected menu command. Index: Makefile *** Makefile Mon Jun 25 08:59:15 1990 --- Makefile.orig Sat Mar 24 06:20:29 1990 *************** *** 1,27 **** # CFLAGS = -g -DFLEX_DEBUG # CFLAGS = -g # CFLAGS = -g -DYYDEBUG ! # CFLAGS = -O -DTERMIO -DTERMCAP ! CFLAGS = -g -DTERMIO -DTERMCAP ! LDFLAGS = -ltermcap # C source files # Yacc source files YSRC = dumb_menu.y ! YCCC = dumb_menu.c ! YOBJ = dumb_menu.o LSRC = dumb_menu.l LEX = flex LFLAGS = - RLSDIR = ./version1 dumb_menu : $(YCCC) lex.yy.c $(CC) $(CFLAGS) $(YCCC) $(LDFLAGS) -o dumb_menu - # SCO Xenix small model flags for 286 machines dumb_menu.0s : dumb_menu.c lex.yy.c ! $(CC) $(CFLAGS) -M0s -i dumb_menu.c $(LDFLAGS) -o dumb_menu.0s lex.yy.c : dumb_menu.l $(LEX) $(LFLAGS) dumb_menu.l --- 1,24 ---- # CFLAGS = -g -DFLEX_DEBUG # CFLAGS = -g # CFLAGS = -g -DYYDEBUG ! CFLAGS = -O -DTERMIO -DTERMCAP ! LDFLAGS = -ly -ltermcap # C source files # Yacc source files YSRC = dumb_menu.y ! YCCC = $(YSRC:.y=.c) ! YOBJ = $(YSRC:.y=.o) LSRC = dumb_menu.l LEX = flex LFLAGS = dumb_menu : $(YCCC) lex.yy.c $(CC) $(CFLAGS) $(YCCC) $(LDFLAGS) -o dumb_menu dumb_menu.0s : dumb_menu.c lex.yy.c ! $(CC) $(CFLAGS) -M0s dumb_menu.c $(LDFLAGS) -o dumb_menu.0s lex.yy.c : dumb_menu.l $(LEX) $(LFLAGS) dumb_menu.l *************** *** 37,62 **** tar cvf /dev/fd096ds9 $(YSRC) $(LSRC) *.1 Makefile s.* *.doc menu.def \ *.menu dumb_menu dumb_menu.0s - tar.kit : - rm -f tar.file.z - tar cvf tar.file $(YSRC) $(LSRC) dumb_menu.1 Makefile \ - menu.def sub.menu directory README \ - dumb_menu dumb_menu.0s - pack tar.file - clean : rm -f $(OBJS) $(YCCC) lex.yy.c ! kit : $(YSRC) $(LSRC) dumb_menu.1 Makefile menu.def sub.menu directory \ ! README patchlevel.h makekit -m $(YSRC) $(LSRC) dumb_menu.1 Makefile menu.def sub.menu \ directory README touch kit - - make-patches : - rm -f patches - for x in patchlevel.h MANIFEST $(YSRC) $(LSRC) dumb_menu.1 Makefile \ - menu.def sub.menu directory README ; do \ - echo "\nIndex: $$x" >>patches ;\ - cdiff $(RLSDIR)/$$x ./$$x >>patches ;\ - done --- 34,43 ---- tar cvf /dev/fd096ds9 $(YSRC) $(LSRC) *.1 Makefile s.* *.doc menu.def \ *.menu dumb_menu dumb_menu.0s clean : rm -f $(OBJS) $(YCCC) lex.yy.c ! kit : $(YSRC) $(LSRC) dumb_menu.1 Makefile menu.def sub.menu directory makekit -m $(YSRC) $(LSRC) dumb_menu.1 Makefile menu.def sub.menu \ directory README touch kit ---------------------------------------cut there-----------------------------