simple_menu program - part1/2
Mike Howard
how at milhow1.UU.NET
Tue Mar 26 07:49:52 AEST 1991
Submitted-by: Mike Howard <how%milhow1 at uunet.uu.net>
Archive-name: simple_menu/part01
I'm looking for suckers to test this - please reply by e-mail to
how%milhow1 at uunet.uu.net
Currently compiles and appears to work on Sun SparcStation 4.1.1,
SCO Xenix 2.3.3 and SCO UNIX 3.2. This is the third version I've
done so I have some expectation that it should not foul up too badly.
simple_menu - executes a simple menus
This is a new version of my 'simple/dumb' menu program. The goal of
this project is to write a simple menu shell which handles the user
response loop and simplifies writing and maintaining user menus. Only
rudimentary pick-one-of-N menus are supported with optional parameters.
For those people (if there are any) who have actually mucked with
my two previous attempts: the changes in this version are:
o menu-environment variables to allow dynamic customization of menus
on the basis of users and system administration changes
o assignable command processor path and variable assignment format
o some bug fixes - in particular, hitting return at the menu prompt
does not cause the program to exit.
o restructuring the code so that display and user interaction is more
modular. This is in anticipation of creating an X version of this
thing. Currently, only character based terminals which can be
controlled by termcap or terminfo character control are supported.
Menu actions are either to call a sub-menu or to run a shell script.
Shell scripts are run by writing variable definitions to a temp file
followed by copying a supplied shell script and then feeding this to
a command interpreter. The command interpreter and assignment format
default to Bourne shell - but can be changed on either the command line
(dumb) or in the menu itself [what do you think? should I chuck the
command line option? - does it have *any* real use or is it dangerous?].
Some dynamic customization of menus is supported by 'menu-environment'
variables. These are variables which take their values from either the
user's environment [from-env type] or from a specified file [from-file type].
In both cases, default values can be supplied in the menu. Also, in both
cases, all menu-environment variables are defined in the shell script
fed to the command interpreter.
Take a look at 'menu.def' to see an example of a menu definition.
The Makefile should be pretty straightforward to modify. In general,
you will not need more than one entry in MENUPATH - but it does take colon
separated path names.
After building, try './simple_menu -M .' in the build-directory in
order to test it. That will fire it up using the sample menu.def file.
This exercises all the options I normally (and some I don't) use. If you
find some cases which make it die, please document and mail them to me
for update.
Mike Howard
how at milhow1.uunet.uu.net
--------------------------------cut here--------------------------------------
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 1 (of 2)."
# Contents: MANIFEST Makefile README directory ev-values grammar.y
# login.menu menu.def patchlevel.h prototypes.h scanner.c
# simple_menu.h sub.menu tty_display.c
# Wrapped by mike at milhow4 on Mon Mar 25 16:45:32 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MANIFEST' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(610 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X File Name Archive # Description
X-----------------------------------------------------------
X MANIFEST 1 This shipping list
X Makefile 1
X README 1
X directory 1
X ev-values 1
X grammar.y 1
X login.menu 1
X menu.def 1
X patchlevel.h 1
X prototypes.h 1
X scanner.c 1
X simple_menu.1 2
X simple_menu.c 2
X simple_menu.h 1
X sub.menu 1
X tty_display.c 1
END_OF_FILE
if test 610 -ne `wc -c <'MANIFEST'`; then
echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(3176 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# installation info
XBINDIR = /usr/local/bin
XMENUPATH = /usr/local/lib/simple_menu:/usr/local/lib/dumb_menu
XLIBDIR = /usr/local/lib/simple_menu
XMANDIR = /usr/local/man/man1
XMANEXT = 1
XINSTALL = install
XINSTALL_BIN_OPT = -c -m 755
XINSTALL_MAN_OPT = -c -m 644
X# INSTALL = cp
X# INSTALL_BIN_OPT =
X# INSTALL_MAN_OPT =
X
X# pick one which works
XVOID_FLAG = -DVOID=void
X# VOID_FLAG = -DVOID=void -DPROTOTYPES_OK
X# VOID_FLAG = -DVOID=int
X# VOID_FLAG = -DVOID=int -DPROTOTYPES_OK
X
X# os independant compiler flag(s)
XCIND_FLAGS = -g $(VOID_FLAG) -DDEFAULT_MENU_PATH=\"$(MENUPATH)\"
X# CIND_FLAGS = -O $(VOID_FLAG) -DDEFAULT_MENU_PATH=\"$(MENUPATH)\"
X
X# sun4 sys V compatability
XCC = /usr/5bin/cc
X# CC = cc
X
X# SYS V
XCFLAGS = $(CIND_FLAGS) -DTERMINFO
XLDFLAGS = -lcurses
X
X# BSD with termcap & BSD style tty inteface
X# CFLAGS = $(CIND_FLAGS) -DBSDTTY -DTERMCAP
X# LDFLAGS = -ltermcap
X
X# BSD or SCO Xenix with termcap & termio style tty inteface
X# CFLAGS = $(CIND_FLAGS) -DTERMIO -DTERMCAP
X# LDFLAGS = -ltermcap
X
X# SCO Xenix small model with termcap & termio style tty inteface
X# CFLAGS = $(CIND_FLAGS) -DTERMIO -DTERMCAP -M0s
X# LDFLAGS = -ltermcap
X
X# shouldn't have to change below here
X
X# C source files
X# Yacc source files
XYSRC = grammar.y
XYCCC = grammar.c
XYOBJ = grammar.o
XOBJS = simple_menu.o disp.o $(YOBJ) scanner.o
XDISP_OBJ = tty_display.o
X
XHDRS = patchlevel.h simple_menu.h prototypes.h
XSRC = simple_menu.c $(YSRC) scanner.c $(HDRS)
XCSRC = simple_menu.c $(YCCC) scanner.c tty_display.c
X
XMISC_SRC = simple_menu.1 menu.def sub.menu login.menu \
X directory README ev-values
XDISP_SRC = tty_display.c
X
Xsimple_menu : $(OBJS)
X $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o simple_menu
X
X$(YCCC) : $(YSRC)
X $(YACC) -d $(YSRC)
X mv y.tab.c $(YCCC)
X
Xscanner.o : scanner.c y.tab.h $(HDRS)
X$(YOBJ) : $(YCCC) $(HDRS)
Xdisp.o : $(DISP_OBJ)
X cp $(DISP_OBJ) disp.o
X$(DISP_OBJ) simple_menu.o scanner.o : $(HDRS)
X
Xprt : $(SRC) $(DISP_SRC)
X for x in $? ; do \
X /usr/5bin/pr -f -l60 -e8 -o2 $$x | rsh milhow1 -l how 'lp -dlaser' ;\
X done
X touch prt
X
X# uses an automatic prototype generator
Xprototypes.h :
X echo "#ifdef PROTOTYPES_OK" >p-tmp.h
X cproto $(CFLAGS) -p2 $(CSRC) >>p-tmp.h
X echo "" >>p-tmp.h
X echo "#else /* PROTOTYPES_OK */" >>p-tmp.h
X cproto $(CFLAGS) -p1 $(CSRC) >>p-tmp.h
X echo "#endif /* PROTOTYPES_OK */" >>p-tmp.h
X mv p-tmp.h prototypes.h
X
Xtar :
X format /dev/rfd096ds9
X tar cvf /dev/fd096ds9 $(SRC) $(DISP_SRC) \
X Makefile $(MISC_SRC) \
X simple_menu simple_menu.0s
X
Xtar.kit :
X rm -f tar.file.z
X tar cvf tar.file $(SRC) $(DISP_SRC) \
X Makefile \
X $(MISC_SRC) \
X simple_menu simple_menu.0s
X pack tar.file
X
Xclean :
X rm -f $(OBJS) $(YCCC) y.tab.h
X
Xvery.clean :
X make clean
X rm -f simple_menu
X
Xinstall : simple_menu simple_menu.1
X $(INSTALL) $(INSTALL_BIN_OPT) simple_menu $(BINDIR)
X $(INSTALL) $(INSTALL_MAN_OPT) simple_menu.1 \
X $(MANDIR)/simple_menu.$(MANEXT)
X [ ! -s $(LIBDIR) ] || mkdir $(LIBDIR)
X
Xkit : $(SRC) $(DISP_SRC) Makefile $(MISC_SRC)
X makekit -m $(SRC) $(DISP_SRC) Makefile $(MISC_SRC)
X touch kit
X
Xmake-patches :
X rm -f patches
X for x in MANIFEST \
X $(SRC) $(DISP_SRC) Makefile \
X $(MISC_SRC) ; do \
X echo "\nIndex: $$x" >>patches ;\
X cdiff RLSDIR/$$x ./$$x >>patches ;\
X done
END_OF_FILE
if test 3176 -ne `wc -c <'Makefile'`; then
echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(2514 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X simple_menu - executes a simple menus
X
X This is a new version of my 'simple/dumb' menu program. The goal of
Xthis project is to write a simple menu shell which handles the user
Xresponse loop and simplifies writing and maintaining user menus. Only
Xrudimentary pick-one-of-N menus are supported with optional parameters.
X
X For those people (if there are any) who have actually mucked with
Xmy two previous attempts: the changes in this version are:
X o menu-environment variables to allow dynamic customization of menus
X on the basis of users and system administration changes
X o assignable command processor path and variable assignment format
X o some bug fixes - in particular, hitting return at the menu prompt
X does not cause the program to exit.
X o restructuring the code so that display and user interaction is more
X modular. This is in anticipation of creating an X version of this
X thing. Currently, only character based terminals which can be
X controlled by termcap or terminfo character control are supported.
X
X Menu actions are either to call a sub-menu or to run a shell script.
X
X Shell scripts are run by writing variable definitions to a temp file
Xfollowed by copying a supplied shell script and then feeding this to
Xa command interpreter. The command interpreter and assignment format
Xdefault to Bourne shell - but can be changed on either the command line
X(dumb) or in the menu itself [what do you think? should I chuck the
Xcommand line option? - does it have *any* real use or is it dangerous?].
X
X Some dynamic customization of menus is supported by 'menu-environment'
Xvariables. These are variables which take their values from either the
Xuser's environment [from-env type] or from a specified file [from-file type].
XIn both cases, default values can be supplied in the menu. Also, in both
Xcases, all menu-environment variables are defined in the shell script
Xfed to the command interpreter.
X
X Take a look at 'menu.def' to see an example of a menu definition.
X
X The Makefile should be pretty straightforward to modify. In general,
Xyou will not need more than one entry in MENUPATH - but it does take colon
Xseparated path names.
X
X After building, try './simple_menu -M .' in the build-directory in
Xorder to test it. That will fire it up using the sample menu.def file.
XThis exercises all the options I normally (and some I don't) use. If you
Xfind some cases which make it die, please document and mail them to me
Xfor update.
X
XMike Howard
Xhow at milhow1.uunet.uu.net
END_OF_FILE
if test 2514 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'directory' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'directory'\"
else
echo shar: Extracting \"'directory'\" \(227 characters\)
sed "s/^X//" >'directory' <<'END_OF_FILE'
Xsimple_menu.1:The Manual Page
Xscanner.c:The Lexical Analyzer
Xsimple_menu.c:Main Program
Xgrammary.y:The Parser
Xtty_display.c:A tty display handler
Xsimple_menu.h:Function definition header file
Xprototypes.h:Prototype definitions
END_OF_FILE
if test 227 -ne `wc -c <'directory'`; then
echo shar: \"'directory'\" unpacked with wrong size!
fi
# end of 'directory'
fi
if test -f 'ev-values' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'ev-values'\"
else
echo shar: Extracting \"'ev-values'\" \(111 characters\)
sed "s/^X//" >'ev-values' <<'END_OF_FILE'
X# environment file definitions
X
XEV_FROMFILE_NO_INIT = a new value
X
XEV_FROMFILE_DEFINED = the non-default value
END_OF_FILE
if test 111 -ne `wc -c <'ev-values'`; then
echo shar: \"'ev-values'\" unpacked with wrong size!
fi
# end of 'ev-values'
fi
if test -f 'grammar.y' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'grammar.y'\"
else
echo shar: Extracting \"'grammar.y'\" \(9787 characters\)
sed "s/^X//" >'grammar.y' <<'END_OF_FILE'
X%{
X/* %W% %D% */
X
Xstatic char *cpy_str =
X "Copyright (c), Mike Howard, 1990,1991 all rights reserved";
X
X/* Conditions of use:
X
X This software is not for sale and is not to be sold by or
X to anyone.
X
X You may use this software and may distribute it to anyone
X you wish to provided you distribute the entire distribution
X package w/o any deletions (i.e. include all the source code).
X
X I do not warrent this software to do anything at all and
X am not responsible for anything which happens as a result of
X its use.
X*/
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <string.h>
X#include <signal.h>
X#include <ctype.h>
X#include "simple_menu.h"
X#include "patchlevel.h"
X
X
X/* Menu definition files begin with an optional environment definition
X section followed by a manditory menu definition section.
X
X The environment definition section consists of one or more environment
X variable declarations of the forms:
X
X shell-path = 'path' ;
X
X asg-fmt = 'format' ; # default is asg-fmt = '"%s=\"%s\"\n"' ;
X
X from-env "NAME" ;
X
X from-env "NAME" = 'default value' ;
X
X from-file 'file-path' "NAME" ;
X
X from-file 'file-path' "NAME" = 'default value' ;
X
X from-env variables are initialized from the environment. from-file
X variables are initialized from the first value in the file named
X file-path which is of the form:
X
X NAME = string
X
X In either case, default values of the Null string or a specified string
X can be defined.
X
X Environment variables are evalutated after the menu file is parsed and
X before the top level menu is displayed.
X
X Environment variables are defined in the environment shell items
X execute in. Their definition precedes local parameter definitions,
X so local parameters can be used to over-ride their value.
X
X
X Menu definitions begin with a main menu definition, optionally
X followed by submenu definitions. The main menu is automatically
X given the name MAIN, so it may begin with a title directive.
X
X title 'text for the title'
X
X This is followed by zero or more of the following parameters, which
X do the `obvious' things:
X
X bold clear always-show once wait alpha
X
X This is followed by one or more menu-item definitions of the form:
X
X prelude 'prompt' %( shell command %)
X parm "name" 'prompt'
X parm "name" = 'initializer' 'prompt'
X parm "name" = "name" 'prompt'
X ;
X
X epilogue 'prompt' %( shell command %)
X parm "name" 'prompt'
X parm "name" = 'initializer' 'prompt'
X parm "name" = "name" 'prompt'
X ;
X
X SHELL 'prompt' %( shell command %)
X parm "name" 'prompt'
X parm "name" = 'initializer' 'prompt'
X parm "name" = "name" 'prompt'
X ;
X
X do-menu "menu-name" 'prompt'
X ;
X
X skip ;
X
X Only one prelude and epilogue are allowed per menu.
X
X Parameters default values may be set in one of three ways:
X parm "name" 'prompt' - default is ""
X parm "name" = 'string' 'prompt' - default is "string"
X parm "name" = "ev-name" 'prompt' - default is the value of the
X environment variable ev-name
X
X Shell scripts are run by creating a command file and feeding it to
X a shell. The sequence is:
X 1. user interactively fills in values for local parameters
X 2. copy all global variables definition strings to temp file
X 3. copy all local parameter definitions to temp file
X 4. copy shell script to temp file
X 5. fork a shell and feed it the temp file - wait for completion
X 6. delete the temp file.
X
X text can be written in one of three ways:
X 1. bound by curly braces { & }
X in which case } and \ are written as by escaping with a backslash
X character
X 2. bound by %( & %), in which case %( and and %) are written
X by doubling (trippling, ...) the percent sign.
X 3. bound by single quote marks ', in which case a single quote
X mark is written by doubling - 'foo''s dog' -> foo's dog
X
X The text in between the double quotes may ONLY contain letters, digits,
X and underscores;
X
X Sub-menus begin with the sequence:
X
X menu "menu-name"
X
X followed by definitions as for the main menu.
X
X comments are delimited on the left by a '#' sign and on the
X right by the end of line. In-line comments are allowed.
X
X Sub-menus can also be formed by running simple_menu as the shell process,
X pointed to an appropriate sub-menu definition file.
X
X There is no provision for menus which require more than one screen
X to display.
X */
X
X%}
X
X%union {
X int ival;
X char *txt;
X char chr;
X double dbl;
X struct item *itm;
X struct parm *prm;
X struct ev_var *ev;
X struct menu *mnu;
X}
X
X%token <ival> NUMBER
X%token <dbl> FLOAT
X%token <txt> TEXT NAME
X%token MENU
X%token SHELL_PATH ASG_FMT
X%token FROM_ENV FROM_FILE
X%token PARM SHELL TITLE ERROR SKIP DO_MENU PRELUDE EPILOGUE
X%token CLEAR BOLD ALWAYS_SHOW ONCE ALPHA WAIT
X
X%type <ival> menu_flags menu_flag
X%type <itm> item
X%type <prm> parm
X%type <ev> ev_list ev_var
X%type <mnu> menu title
X
X%%
X
Xmenu_def_file : ev_list menu_list
X | menu_list
X ;
X
Xev_list : ev_var
X | ev_list ev_var
X ;
X
Xev_var : SHELL_PATH '=' TEXT ';'
X {
X cmd_path = $3;
X }
X | ASG_FMT '=' TEXT ';'
X {
X asg_fmt = $3;
X }
X | FROM_ENV NAME ';'
X {
X $$ = make_new_ev_var(EV_FROM_ENV, $2, (char *)0, (char *)0);
X $$->next = environment_list;
X environment_list = $$;
X DEBUG1("env variable %s from environment - no default\n", $2);
X }
X | FROM_ENV NAME '=' TEXT ';'
X {
X $$ = make_new_ev_var(EV_FROM_ENV, $2, $4, (char *)0);
X $$->next = environment_list;
X environment_list = $$;
X DEBUG2("env variable %s from environment - defaults to %s\n", $2, $4);
X }
X | FROM_FILE TEXT NAME ';'
X {
X $$ = make_new_ev_var(EV_FROM_FILE, $3, (char *)0, $2);
X $$->next = environment_list;
X environment_list = $$;
X DEBUG2("env variable %s from file %s - no default\n", $3, $2);
X }
X | FROM_FILE TEXT NAME '=' TEXT ';'
X {
X $$ = make_new_ev_var(EV_FROM_FILE, $3, $5, $2);
X $$->next = environment_list;
X environment_list = $$;
X DEBUG3("env variable %s from file %s - default: %s\n", $3, $2, $5);
X }
X ;
X
Xmenu_list : menu
X {
X menu_list_head =
X menu_list_tail = $1;
X }
X | menu_list menu
X {
X menu_list_tail->next = $2;
X menu_list_tail = menu_list_tail->next;
X }
X ;
X
Xmenu : title menu_flags item
X {
X $1->flags = $2;
X switch ($3->action) {
X case ITEM_PRELUDE:
X $1->prelude = $3;
X break;
X case ITEM_EPILOGUE:
X $1->epilogue = $3;
X break;
X default:
X $1->item_head =
X $1->item_tail = $3;
X break;
X }
X }
X | menu item
X {
X switch ($2->action) {
X case ITEM_PRELUDE:
X if ($1->prelude) {
X yacc_errors++;
X fprintf(stderr, "multiple prelude detected -line %d\n",
X line_number);
X }
X else
X $1->prelude = $2;
X break;
X case ITEM_EPILOGUE:
X if ($1->epilogue) {
X yacc_errors++;
X fprintf(stderr, "multiple epilogue detected -line %d\n",
X line_number);
X }
X else
X $1->epilogue = $2;
X break;
X default:
X if ($1->item_head) {
X $1->item_tail->next = $2;
X $1->item_tail = $2;
X }
X else
X $1->item_head =
X $1->item_tail = $2;
X break;
X }
X }
X ;
X
Xtitle : TITLE TEXT
X {
X struct menu *menu_ptr;
X
X menu_ptr = make_new_menu();
X menu_ptr->menu_title = $2;
X if (menu_list_head) {
X fprintf(stderr, "untitled sub menu detected near line %d\n",
X line_number);
X yacc_errors++;
X menu_ptr->menu_name = "NOT NAMED";
X }
X DEBUG2("\nMenu %s Title '%s'\n", menu_ptr->menu_name, $2);
X $$ = menu_ptr;
X }
X | MENU NAME TITLE TEXT
X {
X struct menu *menu_ptr;
X
X menu_ptr = make_new_menu();
X menu_ptr->menu_name = $2;
X menu_ptr->menu_title = $4;
X DEBUG2("\nMenu %s Title '%s'\n", $2, $4);
X $$ = menu_ptr;
X }
X ;
X
Xmenu_flags :
X {
X $$ = 0;
X }
X | menu_flags menu_flag
X {
X $$ = $1 | $2;
X }
X ;
X
Xmenu_flag : CLEAR
X {
X $$ = CLEAR_FLAG;
X }
X | BOLD
X {
X $$ = BOLD_FLAG;
X }
X | ALWAYS_SHOW
X {
X $$ = ALWAYS_DISPLAY_FLAG;
X }
X | ONCE
X {
X $$ = ONCE_FLAG;
X }
X | ALPHA
X {
X $$ = ALPHA_FLAG;
X }
X | WAIT
X {
X $$ = WAIT_FLAG;
X }
X ;
X
Xitem : SHELL TEXT TEXT parms ';'
X {
X $$ = make_new_item($2, $3, parm_list, ITEM_SHELL);
X parm_list = (struct parm *)0;
X DEBUG3("shell item: line %d '%s'\n%%(\n%s\n%%)\n",
X line_number, $2, $3);
X }
X | PRELUDE TEXT TEXT parms ';'
X {
X $$ = make_new_item($2, $3, parm_list, ITEM_PRELUDE);
X parm_list = (struct parm *)0;
X DEBUG3("prelude item: line %d '%s'\n%%(\n%s\n%%)\n",
X line_number, $2, $3);
X }
X | EPILOGUE TEXT TEXT parms ';'
X {
X $$ = make_new_item($2, $3, parm_list, ITEM_EPILOGUE);
X parm_list = (struct parm *)0;
X DEBUG3("epilogue item: line %d '%s 'n%%(\n%s\n%%)\n",
X line_number, $2, $3);
X }
X | DO_MENU NAME TEXT ';'
X {
X $$ = make_new_item($3, $2, (struct parm *)0, ITEM_MENU);
X DEBUG3("menu item: line %d \"%s\"\n'%s'\n",
X line_number, $2, $3);
X }
X | SKIP ';'
X {
X $$ = make_new_item("SKIP", (char *)0, (struct parm *)0,
X ITEM_SKIP);
X DEBUG1("skip item: line %d\n", line_number);
X }
X ;
X
Xparms : /* empty */
X | parms parm
X ;
X
Xparm : PARM NAME TEXT
X {
X $$ = make_new_parm(PARM_NO_DEFAULT, $2, $3, (char *)0);
X $$->next = parm_list;
X parm_list = $$;
X DEBUG2("parm: %s\n'%s'\n", $2, $3);
X }
X | PARM NAME '=' TEXT TEXT
X {
X $$ = make_new_parm(PARM_STATIC_DEFAULT, $2, $5, $4);
X $$->next = parm_list;
X parm_list = $$;
X DEBUG3("parm: %s = %s\n'%s'\n", $2, $4, $5);
X }
X ;
X | PARM NAME '=' NAME TEXT
X {
X $$ = make_new_parm(PARM_ENV_DEFAULT, $2, $5, $4);
X $$->next = parm_list;
X parm_list = $$;
X DEBUG3("parm: %s = \"%s\"\n'%s'\n", $2, $4, $5);
X if (!find_ev_var_by_name($4)) {
X yacc_errors++;
X fprintf(stderr, "parm initialized to non-existant environmental variable - line %s\n",
X line_number);
X }
X }
X ;
X
X%%
END_OF_FILE
if test 9787 -ne `wc -c <'grammar.y'`; then
echo shar: \"'grammar.y'\" unpacked with wrong size!
fi
# end of 'grammar.y'
fi
if test -f 'login.menu' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'login.menu'\"
else
echo shar: Extracting \"'login.menu'\" \(495 characters\)
sed "s/^X//" >'login.menu' <<'END_OF_FILE'
X# a sample login menu
X
Xfrom-env "EDITOR" = 'vi' ;
Xfrom-env "PAGER" = 'more' ;
X
Xtitle 'Login Menu'
X
Xclear always-show
X
Xprelude 'checking for mail ...'
X%( mail %)
X;
X
Xepilogue 'checking for mail'
X%( mail %)
X;
X
Xshell 'Edit a File'
X%( ${EDITOR} $FILE %)
Xparm "FILE"='work.doc' 'Name of File to Edit'
X;
X
Xshell 'Browse a File'
X%( ${PAGER} $FILE %)
Xparm "FILE"='work.doc' 'Name of File to View'
X;
X
Xshell 'Mail to a User'
X%( mail -s "$SUBJECT" $TO_WHOM %)
Xparm "SUBJECT" 'Subject'
Xparm "TO_WHOM" 'To'
X;
END_OF_FILE
if test 495 -ne `wc -c <'login.menu'`; then
echo shar: \"'login.menu'\" unpacked with wrong size!
fi
# end of 'login.menu'
fi
if test -f 'menu.def' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'menu.def'\"
else
echo shar: Extracting \"'menu.def'\" \(2442 characters\)
sed "s/^X//" >'menu.def' <<'END_OF_FILE'
X# environment definitions
X
Xfrom-file './ev-values' "EV_FROMFILE_NO_INIT" ;
X
Xfrom-file './ev-values' "EV_FROMFILE_DEFINED" = 'value of file value' ;
X
Xfrom-file './ev-values' "EV_FROMEFILE_NOT_THERE" ;
X
Xfrom-env "EV_DEFINED" = 'value of EV_DEFINED' ;
X
Xfrom-env "EV_UNDEFINED" ;
X
X
X#This is the beginning of the main menu
X# since it is not named, the name will default to MAIN
X
Xtitle 'Test Menu'
X
X# clear will cause the screen to be cleared prior to each
X# redisplay.
X# bold will cause the text 'Test Menu' to be displayed in
X# standout mode - if the terminal type is defined and supports
X# it
X# always-show will cause the choices to always displayed
X
Xclear bold always-show
X
X# this is a simple example
X
Xshell 'First Item'
X%( echo $PARM1 %) # this is the shell script which will be executed
Xparm "PARM1" 'Input Parm 1' # this paramter is set by the user
X;
X
Xshell 'Second Item'
X%( echo "This is $PARM and $FOO and $BARF" %)
Xparm "PARM" 'input value for PARM'
Xparm "FOO"='foo value' 'input value for FOO'
Xparm "BARF" = "EV_DEFINED" 'environment variable EV_DEFINED default'
X;
X
Xshell 'Display all Menu-Environment Variables and values'
X%(
X echo "EV_FROMFILE_NO_INIT: $EV_FROMFILE_NO_INIT"
X echo "EV_FROMFILE_DEFINED: $EV_FROMFILE_DEFINED"
X echo "EV_FROMEFILE_NOT_THERE: $EV_FROMEFILE_NOT_THERE"
X echo "EV_DEFINED: $EV_DEFINED"
X echo "EV_UNDEFINED: $EV_UNDEFINED"
X%)
X;
X
X# this will cause a line to be skipped so as to block the first
X# two items together
X
Xskip ;
X
Xshell 'Execute a Command'
X%(
X $CMD
X%)
Xparm "CMD" 'Command Line'
X;
X
Xskip ;
X
X# three types of sub-menus folow. The first is an internal
X# sub menu defined later in this file
X
Xdo-menu "SUB_MENU" 'An Internal Submenu'
X;
X
X# this is a sub menu defined in a second file
X
Xshell 'Another Submenu in a Separate File'
X%( ./simple_menu ./sub.menu %)
X;
X
X# this sub menu is constructed dynamically by building a
X# menu and feeding it to simple_menu
X
Xshell 'A Dynamically constructed Submenu'
X%( awk -F: '
XBEGIN {
X print "title %( A dynamically constructed submenu %%)"
X print "clear bold"
X}
X{
X print "shell %( Browse " $2 " %%) %( " pager " " $1 " %%) ;"
X}
X' pager=$PAGER directory | ./simple_menu -
X%)
Xparm "PAGER" = 'more' 'name of your pager'
X;
X
X# ============================================================
X
X# sub menu definition
X
Xmenu "SUB_MENU"
X
Xtitle 'a sub menu'
X
Xbold alpha once
X
Xshell 'spawn a shell'
X%( /bin/sh -i %)
X;
X
Xshell 'do nothing'
X%( echo "did nothing" %)
X;
END_OF_FILE
if test 2442 -ne `wc -c <'menu.def'`; then
echo shar: \"'menu.def'\" unpacked with wrong size!
fi
# end of 'menu.def'
fi
if test -f 'patchlevel.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'patchlevel.h'\"
else
echo shar: Extracting \"'patchlevel.h'\" \(21 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X#define PATCHLEVEL 3
END_OF_FILE
if test 21 -ne `wc -c <'patchlevel.h'`; then
echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
# end of 'patchlevel.h'
fi
if test -f 'prototypes.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'prototypes.h'\"
else
echo shar: Extracting \"'prototypes.h'\" \(4212 characters\)
sed "s/^X//" >'prototypes.h' <<'END_OF_FILE'
X#ifdef PROTOTYPES_OK
X
X/* simple_menu.c */
X
Xint main(int /*argc*/, char ** /*argv*/);
Xvoid display_parsed_menus(void);
Xvoid init(int /*argc*/, char ** /*argv*/);
Xstruct parm *make_new_parm(int /*flag*/, char * /*identifier*/, char * /*prompt*/, char * /*def_or_evname*/);
Xstruct ev_var *make_new_ev_var(int /*flag*/, char * /*identifier*/, char * /*deflt*/, char * /*fname*/);
Xstruct item *make_new_item(char * /*prompt*/, char * /*command*/, struct parm * /*parms*/, int /*action*/);
Xstruct menu *make_new_menu(void);
Xvoid init_environment(void);
Xstruct ev_var *find_ev_var_by_name(char * /*name*/);
Xvoid init_parm_defaults(void);
Xvoid init_item_parm_defaults(struct item * /*i_ptr*/);
Xvoid push_menu(struct menu * /*menu_ptr*/);
Xint pop_menu(void);
Xstruct menu *find_menu(char * /*name*/);
Xint check_menu(void);
Xvoid do_menu(void);
Xvoid do_shell_script(struct item * /*selected_item*/);
Xvoid do_prelude(void);
Xvoid do_epilogue(void);
Xvoid fatal(char * /*s*/);
Xvoid trapoid(int /*sig*/);
Xvoid do_longjmp(int /*sig*/);
Xvoid wait_for_child(int /*pid*/);
Xvoid set_signals(int /*flag*/);
Xvoid reset_signals(void);
Xint open_menu_file(void);
Xint search_menu_path(char * /*path*/, char * /*fname*/);
Xchar *Malloc(unsigned /*size*/);
Xchar *Realloc(char * /*ptr*/, unsigned /*size*/);
Xvoid yyerror(char * /*s*/);
Xvoid prt_item(struct item * /*item_ptr*/);
Xvoid simple_menu_exit(int /*code*/);
X
X/* grammar.c */
X
Xint yyparse(void);
X
X/* scanner.c */
X
Xint match_token(char * /*s*/);
Xint make_lower(char /*c*/);
Xint yylex(void);
Xint scan_in_token_state(void);
Xint scan_in_name_state(void);
Xint scan_in_string_state(void);
Xint scan_in_text_state(void);
Xint scan_in_old_text_state(void);
Xvoid unget_char(char /*c*/);
Xint next_char(int /*fd*/);
Xvoid flush_char_input(void);
Xvoid add_char(char /*c*/);
Xvoid strip_white_space(void);
Xchar *take_saved_text(void);
X
X/* tty_display.c */
X
Xint outc(int /*c*/);
Xvoid init_terminal(void);
Xvoid close_terminal(void);
Xvoid display_menu(void);
Xchar *get_variable_value(char * /*prompt*/, char * /*deflt*/);
Xint get_user_rsp(void);
Xvoid do_pause(int /*flag*/);
X
X#else /* PROTOTYPES_OK */
X
X/* simple_menu.c */
X
Xint main(/*int argc, char **argv*/);
Xvoid display_parsed_menus(/*void*/);
Xvoid init(/*int argc, char **argv*/);
Xstruct parm *make_new_parm(/*int flag, char *identifier, char *prompt, char *def_or_evname*/);
Xstruct ev_var *make_new_ev_var(/*int flag, char *identifier, char *deflt, char *fname*/);
Xstruct item *make_new_item(/*char *prompt, char *command, struct parm *parms, int action*/);
Xstruct menu *make_new_menu(/*void*/);
Xvoid init_environment(/*void*/);
Xstruct ev_var *find_ev_var_by_name(/*char *name*/);
Xvoid init_parm_defaults(/*void*/);
Xvoid init_item_parm_defaults(/*struct item *i_ptr*/);
Xvoid push_menu(/*struct menu *menu_ptr*/);
Xint pop_menu(/*void*/);
Xstruct menu *find_menu(/*char *name*/);
Xint check_menu(/*void*/);
Xvoid do_menu(/*void*/);
Xvoid do_shell_script(/*struct item *selected_item*/);
Xvoid do_prelude(/*void*/);
Xvoid do_epilogue(/*void*/);
Xvoid fatal(/*char *s*/);
Xvoid trapoid(/*int sig*/);
Xvoid do_longjmp(/*int sig*/);
Xvoid wait_for_child(/*int pid*/);
Xvoid set_signals(/*int flag*/);
Xvoid reset_signals(/*void*/);
Xint open_menu_file(/*void*/);
Xint search_menu_path(/*char *path, char *fname*/);
Xchar *Malloc(/*unsigned size*/);
Xchar *Realloc(/*char *ptr, unsigned size*/);
Xvoid yyerror(/*char *s*/);
Xvoid prt_item(/*struct item *item_ptr*/);
Xvoid simple_menu_exit(/*int code*/);
X
X/* grammar.c */
X
Xint yyparse(/*void*/);
X
X/* scanner.c */
X
Xint match_token(/*char *s*/);
Xint make_lower(/*char c*/);
Xint yylex(/*void*/);
Xint scan_in_token_state(/*void*/);
Xint scan_in_name_state(/*void*/);
Xint scan_in_string_state(/*void*/);
Xint scan_in_text_state(/*void*/);
Xint scan_in_old_text_state(/*void*/);
Xvoid unget_char(/*char c*/);
Xint next_char(/*int fd*/);
Xvoid flush_char_input(/*void*/);
Xvoid add_char(/*char c*/);
Xvoid strip_white_space(/*void*/);
Xchar *take_saved_text(/*void*/);
X
X/* tty_display.c */
X
Xint outc(/*int c*/);
Xvoid init_terminal(/*void*/);
Xvoid close_terminal(/*void*/);
Xvoid display_menu(/*void*/);
Xchar *get_variable_value(/*char *prompt, char *deflt*/);
Xint get_user_rsp(/*void*/);
Xvoid do_pause(/*int flag*/);
X#endif /* PROTOTYPES_OK */
END_OF_FILE
if test 4212 -ne `wc -c <'prototypes.h'`; then
echo shar: \"'prototypes.h'\" unpacked with wrong size!
fi
# end of 'prototypes.h'
fi
if test -f 'scanner.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'scanner.c'\"
else
echo shar: Extracting \"'scanner.c'\" \(6770 characters\)
sed "s/^X//" >'scanner.c' <<'END_OF_FILE'
X/* %W% %D% */
X/* copyrite (c) Mike Howard, 1990, 1991 */
X
X#include <stdio.h>
X#include <ctype.h>
X#include "y.tab.h"
X#include "simple_menu.h"
X
Xextern int debug_mode;
Xextern int lex_errors;
Xextern int line_number;
X
Xchar *saved_text;
Xchar *Malloc();
Xchar *Realloc();
X
Xstruct word_cell {
X char *name;
X int value;
X};
X
Xstruct word_cell word_list[] = {
X"ERROR", ERROR,
X"item", SHELL, /* left over dinosaur */
X"shell", SHELL,
X"parm", PARM,
X"title", TITLE,
X"clear", CLEAR,
X"bold", BOLD,
X"always-show", ALWAYS_SHOW,
X"once", ONCE,
X"prelude", PRELUDE,
X"epilogue", EPILOGUE,
X"menu", MENU,
X"do-menu", DO_MENU,
X"skip", SKIP,
X"alpha", ALPHA,
X"wait", WAIT,
X"shell-path", SHELL_PATH,
X"asg-fmt", ASG_FMT,
X"from-env", FROM_ENV,
X"from-file", FROM_FILE,
X(char *)0, -1 };
X
Xint
Xmatch_token(s)
X char *s;
X{
X int i;
X
X for (i=1;word_list[i].name;i++) {
X if (*s == word_list[i].name[0] && !strcmp(s, word_list[i].name))
X return i;
X }
X
X lex_errors++;
X return 0;
X}
X
Xint
Xmake_lower(c)
X char c;
X{
X return isupper(c) ? tolower(c) : c;
X}
X
X/* this thing is a state machine - of sorts. */
X
Xint
Xyylex()
X{
X char c;
X
X while (1) {
X while (isspace(c = next_char(0)))
X ;
X switch (c) {
X case '"':
X return scan_in_name_state();
X case '{':
X return scan_in_old_text_state();
X case '\0':
X return 0;
X case '%':
X if ((c = next_char(0)) == '(')
X return scan_in_text_state();
X unget_char(c);
X unget_char('%');
X return scan_in_token_state();
X case '\'':
X return scan_in_string_state();
X case '#':
X while (c && c != '\n')
X c = next_char(0);
X break;
X case ';':
X case '=':
X VDEBUG2("scanner: line %d - returning %c\n", line_number, c);
X return c;
X default:
X unget_char(c);
X return scan_in_token_state();
X }
X }
X}
X
Xint
Xscan_in_token_state()
X{
X char c;
X int ret;
X
X while (isalpha(c = make_lower(next_char(0))) || c == '-')
X add_char(c);
X
X unget_char(c);
X ret = match_token(saved_text);
X VDEBUG3("scanner: line %d: token: %s matches %s\n", line_number,
X saved_text, word_list[ret].name);
X free(saved_text);
X saved_text = (char *)0;
X
X return word_list[ret].value;
X}
X
Xint
Xscan_in_name_state()
X{
X char c;
X
X while (1) {
X c = next_char(0);
X if (isalnum(c) || c == '_')
X add_char(c);
X else if (c == '"') {
X strip_white_space();
X yylval.txt = take_saved_text();
X VDEBUG2("scanner: line %d - found Name: \"%s\"\n", line_number,
X yylval.txt);
X return NAME;
X }
X else {
X printf("error in line %d - bad character (%c) in name\n",
X line_number, c);
X while (c && !isspace(c))
X c = next_char(0);
X unget_char(c);
X lex_errors++;
X return ERROR;
X }
X }
X}
X
X/* scans for ' delimited plain text - translates '' into ' */
X
Xint scan_in_string_state()
X{
X char c;
X
X while (1) {
X switch (c = next_char(0)) {
X case 0:
X printf("error in line %d - premature end of text\n", line_number);
X lex_errors++;
X return ERROR;
X case '\'':
X if ((c = next_char(0)) != '\'') {
X strip_white_space();
X yylval.txt = take_saved_text();
X VDEBUG2("scanner: line %d - found Text-String\n'%s'\n",
X line_number, yylval.txt);
X return TEXT;
X }
X add_char('\'');
X break;
X default:
X add_char(c);
X break;
X }
X }
X}
X
X/* scans for %( %) delimited text - a %) may be embedded if written %%) */
X
Xint scan_in_text_state()
X{
X char c;
X
X while (1) {
X switch (c = next_char(0)) {
X case 0:
X printf("error in line %d - premature end of text\n", line_number);
X lex_errors++;
X return ERROR;
X case '%':
X if ((c = next_char(0)) == ')') {
X strip_white_space();
X yylval.txt = take_saved_text();
X VDEBUG2("scanner: line %d - found Text-String\n%(\n%s\n%)\n",
X line_number, yylval.txt);
X return TEXT;
X }
X if (c == '%') {
X if ((c = next_char(0)) == ')' || c == '(') {
X add_char('%');
X add_char(c);
X break;
X }
X /* back up two characters and restart */
X unget_char(c);
X c = '%';
X break;
X }
X unget_char(c);
X add_char('%');
X break;
X default:
X add_char(c);
X break;
X }
X }
X}
X
Xint
Xscan_in_old_text_state()
X{
X char c;
X
X while (1) {
X switch (c = next_char(0)) {
X case 0:
X printf("error in line %d - premature end of text\n", line_number);
X lex_errors++;
X return ERROR;
X case '\\':
X switch(c = next_char(0)) {
X case '\\':
X case '}':
X add_char(c);
X break;
X default:
X add_char('\\');
X add_char(c);
X break;
X }
X break;
X case '}':
X strip_white_space();
X yylval.txt = take_saved_text();
X VDEBUG2("scanner: line %d - found old style Text-String\n{\n%s\n}\n",
X line_number, yylval.txt);
X return TEXT;
X default:
X add_char(c);
X break;
X }
X }
X}
X
X#define CHAR_BUFSIZE 1024
Xunsigned char char_buf[CHAR_BUFSIZE];
Xint chars_left;
Xunsigned char *nxt_char;
X#define UNGET_BUFSIZE 128
Xchar unget_buf[UNGET_BUFSIZE];
Xint unget_len;
X
XVOID
Xunget_char(c)
X char c;
X{
X if ((unget_buf[unget_len++] = c) == '\n')
X line_number--;
X}
X
Xint
Xnext_char(fd)
Xint fd;
X{
X int c;
X
X if (unget_len > 0) {
X c = unget_buf[--unget_len];
X }
X else {
X if (chars_left <= 0) {
X if ((chars_left = read(fd, char_buf, CHAR_BUFSIZE)) <= 0)
X return 0;
X nxt_char = char_buf;
X }
X
X c = *nxt_char++;
X chars_left--;
X }
X
X if (c == '\n')
X line_number++;
X
X return c;
X}
X
XVOID flush_char_input()
X{
X chars_left =
X unget_len = 0;
X}
X
X#define INIT_SIZE 256
X#define INC_SIZE 64
X
X
XVOID
Xadd_char(c)
X char c;
X{
X static int saved_length;
X static int room_left;
X static int saved_size;
X
X if (!saved_text) {
X memset(saved_text = Malloc(INIT_SIZE), '\0', INIT_SIZE);
X room_left = INIT_SIZE;
X saved_size = INIT_SIZE;
X saved_length = 0;
X }
X
X if (room_left < 2) {
X saved_text = Realloc(saved_text, saved_size += INC_SIZE);
X room_left += INC_SIZE;
X }
X
X saved_text[saved_length++] = c;
X saved_text[saved_length] = '\0';
X room_left--;
X}
X
X
XVOID
Xstrip_white_space()
X{
X char *cp;
X char *sp;
X
X if (!saved_text)
X return;
X
X for (cp = saved_text + strlen(saved_text) - 1;cp > saved_text;cp--) {
X if (!isspace(*cp))
X break;
X }
X *++cp = '\0';
X
X for (cp=saved_text;*cp && isspace(*cp);cp++)
X ;
X
X /* is it all white? */
X if (!*cp && cp > saved_text) {
X saved_text = Realloc(saved_text, 1);
X *saved_text = '\0';
X return;
X }
X
X /* is there any leading white space? */
X if (cp > saved_text) {
X char *tmp;
X int len;
X
X tmp = Malloc(len = strlen(cp) + 1);
X memcpy(tmp, cp, len);
X free(saved_text);
X saved_text = tmp;
X
X return;
X }
X
X saved_text = Realloc(saved_text, strlen(saved_text) + 1);
X}
X
Xchar *
Xtake_saved_text()
X{
X char *cp = saved_text;
X
X saved_text = (char *)0;
X
X return cp;
X}
END_OF_FILE
if test 6770 -ne `wc -c <'scanner.c'`; then
echo shar: \"'scanner.c'\" unpacked with wrong size!
fi
# end of 'scanner.c'
fi
if test -f 'simple_menu.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'simple_menu.h'\"
else
echo shar: Extracting \"'simple_menu.h'\" \(3804 characters\)
sed "s/^X//" >'simple_menu.h' <<'END_OF_FILE'
X/* %W% %D% */
X/* copyrite (c) Mike Howard, 1990, 1991 */
X
X/* #define VOID void or int is expected to occur in the compilation line */
X#ifndef VOID
X# define VOID void
X#endif
X
X/* include some common stuff */
X#ifndef FILE
X# include <stdio.h>
X#endif
X#include <setjmp.h>
X
X#define EV_FROM_FILE 1
X#define EV_FROM_ENV 2
X
Xstruct ev_var {
X struct ev_var *next;
X char *identifier;
X char *value;
X char *deflt;
X char *file_name;
X int flag;
X};
X
X#define PARM_NO_DEFAULT 0
X#define PARM_STATIC_DEFAULT 1
X#define PARM_ENV_DEFAULT 2
X
Xstruct parm {
X struct parm *next;
X char *prompt;
X char *identifier;
X char *value;
X char *def_or_evname;
X int flag;
X};
X
X#define ITEM_SHELL 1
X#define ITEM_MENU 2
X#define ITEM_SKIP 3
X#define ITEM_PRELUDE 4
X#define ITEM_EPILOGUE 5
X
X
Xstruct item {
X struct item *next;
X int action;
X int item_idx;
X char *prompt;
X char *command;
X struct parm *parms;
X};
X
X#define CLEAR_FLAG 1
X#define BOLD_FLAG 2
X#define ALWAYS_DISPLAY_FLAG 4
X#define ONCE_FLAG 8
X#define ALPHA_FLAG 16
X#define WAIT_FLAG 32
X#define Clear_Flag (clear_flag&&(active_menu->flags&CLEAR_FLAG))
X#define Bold_Flag (bold_flag&&(active_menu->flags&BOLD_FLAG))
X#define Always_Display_Flag (active_menu->flags&ALWAYS_DISPLAY_FLAG)
X#define Once_Flag (active_menu->flags&ONCE_FLAG)
X#define Alpha_Flag (active_menu->flags&ALPHA_FLAG)
X#define Wait_Flag (active_menu->flags&WAIT_FLAG)
X
Xstruct menu {
X struct menu *next;
X struct menu *menu_stack_ptr;
X struct item *item_head;
X struct item *item_tail;
X struct item *prelude;
X struct item *epilogue;
X char *menu_name;
X char *menu_title;
X char *short_title;
X int max_item;
X int flags;
X};
X
X#define DEBUG0(fmt) if(debug_mode>1)printf(fmt);
X#define DEBUG1(fmt,aa) if(debug_mode>1)printf(fmt,aa);
X#define DEBUG2(fmt,aa,bb) if(debug_mode>1)printf(fmt,aa,bb);
X#define DEBUG3(fmt,aa,bb,cc) if(debug_mode>1)printf(fmt,aa,bb,cc);
X
X#define VDEBUG0(fmt) if(debug_mode>2)printf(fmt);
X#define VDEBUG1(fmt,aa) if(debug_mode>2)printf(fmt,aa);
X#define VDEBUG2(fmt,aa,bb) if(debug_mode>2)printf(fmt,aa,bb);
X#define VDEBUG3(fmt,aa,bb,cc) if(debug_mode>2)printf(fmt,aa,bb,cc);
X
X/* data declarations and initializations */
X#ifdef MAIN
X# define EXTERN
X#else
X# define EXTERN extern
X#endif
X
X/* capability flags - set by init_terminal */
XEXTERN int clear_flag;
XEXTERN int bold_flag;
X
XEXTERN struct menu *menu_list_head;
XEXTERN struct menu *menu_list_tail;
XEXTERN struct menu *active_menu;
X
XEXTERN struct parm *parm_list;
XEXTERN struct ev_var *environment_list;
X
XEXTERN char *user_rsp;
XEXTERN int default_timeout;
X
XEXTERN int lex_errors;
XEXTERN int yacc_errors;
XEXTERN int line_number;
X
X
X
Xextern char *optarg;
Xextern int optind, opterr;
XEXTERN int tty_in;
XEXTERN char *tty_fname;
XEXTERN char *ttyname();
XEXTERN int argcc;
XEXTERN char **argvv;
XEXTERN char *progname;
XEXTERN char *in_fname;
XEXTERN char *menu_fname;
X#define MENU_FNAME "menu.def"
XEXTERN char *menu_path;
X#ifndef DEFAULT_MENU_PATH
X# define DEFAULT_MENU_PATH \
X "/usr/local/lib/simple_menu:/usr/local/lib/dumb_menu"
X#endif /* DEFAULT_MENU_PATH */
XEXTERN char *cmd_path;
XEXTERN char *asg_fmt;
XEXTERN char *cmd_name;
X
XEXTERN struct item *selected_item;
XEXTERN struct parm *selected_parms;
XEXTERN FILE *tmp_file;
XEXTERN char *tmp_fname;
X
X/* flags */
XEXTERN int verbose;
XEXTERN int debug_mode;
X
XEXTERN int display_menu_flag;
XEXTERN jmp_buf env;
X#define SIGS_FOR_JMP 1
X#define SIGS_FOR_CHILD 2
X
X#ifdef MAIN
X
Xchar *use_msg = "usage: %s (patchlevel %d) [-h | option(s)] [menu-file | -]\n";
Xchar *item_types[] = {
X"none",
X"Shell Item",
X"Menu Item",
X"Skip Item",
X"Prelude Item",
X"Epilogue Item",
X(char *)0 };
X#else
Xextern char *use_msg;
Xextern char *item_types[];
X#endif
X
X#include "prototypes.h"
END_OF_FILE
if test 3804 -ne `wc -c <'simple_menu.h'`; then
echo shar: \"'simple_menu.h'\" unpacked with wrong size!
fi
# end of 'simple_menu.h'
fi
if test -f 'sub.menu' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sub.menu'\"
else
echo shar: Extracting \"'sub.menu'\" \(226 characters\)
sed "s/^X//" >'sub.menu' <<'END_OF_FILE'
X
Xtitle 'A non-descript submenu
XWith a multi-line
X title'
X
Xclear wait
X
Xshell 'Sub-Item 1
X long prompt'
X%( echo "Sub-Item 1" %)
X;
X
Xshell 'Sub-Item 2'
X%( echo "Sub-Item 2" %)
X;
X
Xshell 'Sub-Item 3'
X%( echo "Sub-Item 3" %)
X;
END_OF_FILE
if test 226 -ne `wc -c <'sub.menu'`; then
echo shar: \"'sub.menu'\" unpacked with wrong size!
fi
# end of 'sub.menu'
fi
if test -f 'tty_display.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tty_display.c'\"
else
echo shar: Extracting \"'tty_display.c'\" \(8253 characters\)
sed "s/^X//" >'tty_display.c' <<'END_OF_FILE'
X/* %W% %D% */
X
Xstatic char *cpy_str =
X "Copyright (c), Mike Howard, 1990,1991 all rights reserved";
X
X/* Conditions of use:
X
X This software is not for sale and is not to be sold by or
X to anyone.
X
X You may use this software and may distribute it to anyone
X you wish to provided you distribute the entire distribution
X package w/o any deletions (i.e. include all the source code).
X
X I do not warrent this software to do anything at all and
X am not responsible for anything which happens as a result of
X its use.
X*/
X
X/* this is the display dependant part which knows how to talk to character
X terminals
X
X must define 4 functions:
X init_terminal() - initializes the display - a tty for tty based stuff
X display_menu() - draws the menu on the display
X prepare_for_subshell() - this and the companion routine do whatever
X return_from_subshell() - is required to the display to run a subshell
X close_terminal() - does whatever closedown is required for terminal
X get_user_rsp() - returns single character user choice.
X get_variable_value(prompt, def) - returns Malloc'ed value of parameter
X after talking to user
X do_pause(flag) - implements a timed pause. It should return after a user
X action or default_timeout seconds have passed. The
X flag is 0 for an illegal menu choice and 1 if exiting
X a menu
X*/
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <string.h>
X#include <signal.h>
X#include <ctype.h>
X
X#include "simple_menu.h"
X#include "patchlevel.h"
X
X#ifdef TERMCAP
Xchar tty_bp[1024];
Xchar tty_caps[1024];
Xchar *term_cm;
Xchar *term_so;
Xchar *term_se;
Xint term_sg;
Xchar *term_cl;
Xint term_lines;
Xchar PC;
Xchar *BC;
Xchar *UP;
Xshort ospeed;
X
Xint
Xoutc(c)
X int c;
X{
X putc(c, stdout);
X}
X
XVOID
Xinit_terminal()
X{
X char *getenv();
X char *tty_type = getenv("TERM");
X char *cp = tty_caps;
X char *tgetstr();
X
X /* assumes fd's 0, 1, & 2 are closed */
X tty_fname = ttyname(1);
X if (!isatty(1) || (tty_in = open(tty_fname, O_RDWR)) < 0)
X fatal("cannot open tty - must be run interactively");
X close(0);
X close(1);
X close(2);
X dup(tty_in);
X dup(tty_in);
X close(tty_in);
X
X if (!tty_type || tgetent(tty_bp, tty_type) <= 0) {
X clear_flag =
X bold_flag = 0;
X return;
X }
X
X PC = (BC = tgetstr("pc", &cp)) ? *BC : '\0';
X BC = tgetstr("bc", &cp);
X UP = tgetstr("up", &cp);
X#ifdef TERMIO
X {
X#include <termio.h>
X
X struct termio termio;
X
X ioctl(0, TCGETA, &termio);
X ospeed = termio.c_cflag & CBAUD;
X }
X#undef ECHO /* conflicts with lex code */
X#endif /* TERMIO */
X#ifdef BSDTTY
X {
X#include <sgtty.h>
X struct sgttyb sgttyb;
X
X ioctl(0, TIOCGETP, &sgttyb);
X ospeed = sgttyb.sg_ospeed;
X }
X#endif /* BSDTTY */
X
X term_cm = tgetstr("cm", &cp);
X term_so = tgetstr("so", &cp);
X term_se = tgetstr("se", &cp);
X term_sg = tgetnum("sg");
X bold_flag = term_so ? 1 : 0;
X
X term_cl = tgetstr("cl", &cp);
X term_lines = tgetnum("li");
X clear_flag = term_cl ? 1 : 0;
X
X flush_char_input();
X}
X
XVOID
Xclose_terminal()
X{
X}
X
XVOID
Xprepare_for_subshell()
X{
X}
X
XVOID
Xreturn_from_subshell()
X{
X}
X
XVOID
Xdisplay_menu()
X{
X struct item *ptr;
X int i;
X
X /* if we clear the screen, then do it, otherwise skip a line */
X if (Clear_Flag)
X tputs(term_cl, term_lines, outc);
X else
X putc('\n', stdout);
X
X /* this is not correct for magic cookie tubes - solving that problem
X requires counting lines in menu_title, maintaining line counts in the
X case we don't clear-screen-before-displaying, cursor positioning
X sequences, ... AND having a known tube environment - i.e. no one
X has reprogrammed something for their own purposes. So, if you
X have any such tube, it will probably flash if you set the
X bold flag */
X if (Bold_Flag) {
X tputs(term_so, 1, outc);
X printf("%s", active_menu->menu_title);
X tputs(term_se, 1, outc);
X putc('\n', stdout);
X }
X else
X printf("%s\n", active_menu->menu_title);
X
X if (display_menu_flag) {
X for (ptr=active_menu->item_head;ptr;ptr = ptr->next) {
X switch (ptr->action) {
X case ITEM_SKIP:
X putchar('\n');
X break;
X default:
X if (Alpha_Flag)
X printf("%c. %s\n", 'A' + ptr->item_idx - 1, ptr->prompt);
X else
X printf("%2d. %s\n", ptr->item_idx, ptr->prompt);
X break;
X }
X }
X }
X
X if (Once_Flag)
X printf("Choice? ");
X else if (Always_Display_Flag)
X printf("Q) to End - choice? ");
X else
X printf("Q) to End, ?) for Menu - choice? ");
X fflush(stdout);
X
X display_menu_flag = Always_Display_Flag;
X}
X#endif /* TERMCAP */
X
X#ifdef TERMINFO
X
Xint havecalled_setupterm;
X#include <curses.h>
X#include <term.h>
X
XVOID
Xinit_terminal()
X{
X
X /* assumes fd's 0, 1, & 2 are closed */
X tty_fname = ttyname(1);
X if (!isatty(1) || (tty_in = open(tty_fname, O_RDWR)) < 0)
X fatal("cannot open tty - must be run interactively");
X close(0);
X close(1);
X close(2);
X dup(tty_in);
X dup(tty_in);
X close(tty_in);
X
X
X setupterm((char *)0, 1, &havecalled_setupterm);
X if (havecalled_setupterm != 1) {
X clear_flag =
X bold_flag = 0;
X return;
X }
X
X if (clear_screen)
X clear_flag++;
X if (enter_standout_mode)
X bold_flag++;
X
X flush_char_input();
X}
X
XVOID
Xclose_terminal()
X{
X if (havecalled_setupterm)
X resetterm();
X}
X
XVOID
Xprepare_for_subshell()
X{
X if (havecalled_setupterm)
X resetterm();
X}
X
XVOID
Xreturn_from_subshell()
X{
X if (havecalled_setupterm)
X fixterm();
X}
X
XVOID
Xdisplay_menu()
X{
X struct item *ptr;
X int i;
X
X /* if we clear the screen, then do it, otherwise skip a line */
X if (Clear_Flag)
X putp(clear_screen);
X else
X putc('\n', stdout);
X
X /* this is not correct for magic cookie tubes - solving that problem
X requires counting lines in menu_title, maintaining line counts in the
X case we don't clear-screen-before-displaying, cursor positioning
X sequences, ... AND having a known tube environment - i.e. no one
X has reprogrammed something for their own purposes. So, if you
X have any such tube, it will probably flash if you set the
X bold flag */
X if (Bold_Flag) {
X putp(enter_standout_mode);
X printf("%s", active_menu->menu_title);
X putp(exit_standout_mode);
X putc('\n', stdout);
X }
X else
X printf("%s\n", active_menu->menu_title);
X
X if (display_menu_flag) {
X for (ptr=active_menu->item_head;ptr;ptr = ptr->next) {
X switch (ptr->action) {
X case ITEM_SKIP:
X putchar('\n');
X break;
X default:
X if (Alpha_Flag)
X printf("%c. %s\n", 'A' + ptr->item_idx - 1, ptr->prompt);
X else
X printf("%2d. %s\n", ptr->item_idx, ptr->prompt);
X break;
X }
X }
X }
X
X if (Once_Flag)
X printf("Choice? ");
X else if (Always_Display_Flag)
X printf("Q) to End - choice? ");
X else
X printf("Q) to End, ?) for Menu - choice? ");
X fflush(stdout);
X
X display_menu_flag = Always_Display_Flag;
X}
X#endif /* TERMINFO */
X
Xchar *
Xget_variable_value(prompt, deflt)
Xchar *prompt;
Xchar *deflt;
X{
X char *cp;
X int c;
X
X printf("%s[%s]: ", prompt, deflt);
X fflush(stdout);
X while ((c = next_char(0)) && c != '\n')
X add_char(c);
X
X if ((cp = take_saved_text()) && strlen(cp)) {
X return cp;
X }
X else if (deflt) {
X strcpy(cp = Malloc(strlen(deflt) + 1), deflt);
X }
X else {
X cp = Malloc(1);
X cp[0] = '\0';
X }
X
X return cp;
X}
X
X
Xint
Xget_user_rsp()
X{
X char c;
X
X while ((c = next_char(0)) && c != '\n')
X add_char(c);
X strip_white_space();
X
X if (user_rsp)
X free(user_rsp);
X if (!(user_rsp = take_saved_text()))
X return c == '\n' ? '\n' : 0;
X
X switch (user_rsp[0]) {
X case 'q':
X case 'Q':
X return 'q';
X case '?':
X return '?';
X case '\0':
X return c == '\n' ? '\n' : 0;
X default:
X if (Alpha_Flag) {
X if (isalpha(user_rsp[0]))
X return toupper(user_rsp[0]) - 'A' + 1;
X return 0;
X }
X else
X return atoi(user_rsp);
X }
X}
X
Xstatic VOID
Xalarm_trap()
X{
X return;
X}
X
XVOID
Xdo_pause(flag)
X int flag;
X{
X char c;
X
X if (Clear_Flag) {
X if (flag)
X printf("Returning to '%s' [Press Return to Continue]",
X active_menu->short_title);
X else
X printf("[Press Return to Continue]");
X fflush(stdout);
X if (!Wait_Flag) {
X alarm(default_timeout);
X signal(SIGALRM, alarm_trap);
X }
X while ((c = next_char(0)) && c != '\n')
X ;
X alarm(0);
X signal(SIGALRM, SIG_IGN);
X }
X}
END_OF_FILE
if test 8253 -ne `wc -c <'tty_display.c'`; then
echo shar: \"'tty_display.c'\" unpacked with wrong size!
fi
# end of 'tty_display.c'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked both archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--------------------------------cut here--------------------------------------
--
Mike Howard
uunet!milhow1!how or how%milhow1 at uunet.uu.net
More information about the Alt.sources
mailing list