[comp.sources.misc] v13i083: Patch to menu_mh in volume 11

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-----------------------------