[comp.unix.xenix] Menu software... version 1.35 upgrade to "lush" part 1/1

shields@yunccn.UUCP (Paul Shields) (01/09/90)

Note: I haven't compiled lush for MS-DOS in at least a year. You may
have to work on it.

You'll also need a termcap library that will work on MS-DOS.  I ported
the GNU termcap to MS-DOS and posted it to comp.sources.misc some time
ago (last year? I don't recall.) Drop me a note if you can't find it
anywhere, and I'll send it to you. 

#--------------------------------CUT HERE-------------------------------------
#! /bin/sh
#
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#
# -rw-r--r--   1 shields  staff       1941 Jan  8 17:48 Makefile.MS
# -rw-r--r--   1 shields  staff       1185 Jan  8 16:04 config.h
# -rw-r--r--   1 shields  staff       1643 Jan  8 16:47 defs.h
# -rw-r--r--   1 shields  staff       6587 Jan  8 16:37 edit.c
# -rw-r--r--   1 shields  staff       8788 Jan  8 16:51 envinit.c
# -rw-r--r--   1 shields  staff        701 Jan  8 16:41 login.c
# -rw-r--r--   1 shields  staff         66 Jan  8 17:07 version.h
#
echo 'x - Makefile.MS'
if test -f Makefile.MS; then echo 'shar: not overwriting Makefile.MS'; else
sed 's/^X//' << '________This_Is_The_END________' > Makefile.MS
X# Makefile.MS - Generic MS-DOS Makefile for lush
X# This file is untested, so it will probably need work, especially in
X# the link phase. --Note -- Microsoft make won't work on this Makefile. 
X# Use something like NdMake. 
X 
X# You'll probably want to change LIBDIR and BINDIR to something more sane. 
X# Don't forget to change config.h as well.
X
XLIBDIR=\usr\lib\lush
XBINDIR=\usr\local\bin
X
X# compiler definitions you might want to have:
X#
X# -DPROTOTYPE	if your compiler can handle prototype statements
X# -DMULTIUSER	for MSDOS users, if you have getuid(), getpwnam(), ttyname(), getgrpnam()
X
XDEBUG  =
XDEFS   = -DMSDOS
XCFLAGS = $(DEBUG) $(DEFS)
XLDFLAGS=
XLIBS   = -lc -ltermcap
X
XHFILES = mparse.h mlex.h mfile.h menu.h edit.h lush.h defs.h version.h config.h
XCFILES = mparse.c mlex.c mfile.c menu.c edit.c lush.c envinit.c getin.c login.c
XOBJS   = mparse.obj mlex.obj mfile.obj menu.obj edit.obj lush.obj envinit.obj\
X		getin.obj login.obj
X
X# ----------------------------- dependencies --------------------------------
X
Xlush.exe: $(OBJS)
X	$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o lush.exe
X
Xclean:
X	-del lush.exe
X	-del errs
X	-del *.obj
X	-del *.map
X
Xinstall: lush.exe lushrc menu
X	-mkdir $(BINDIR)
X	-mkdir $(LIBDIR)
X	copy lush.exe $(BINDIR)
X	copy lushrc $(LIBDIR)
X	copy menu $(LIBDIR)
X
Xmparse.obj: mparse.c mparse.h mlex.h mfile.h menu.h lush.h defs.h config.h
X	$(CC) $(CFLAGS) mparse.c -c 
X
Xmlex.obj: mlex.c mlex.h mfile.h lush.h defs.h
X	$(CC) $(CFLAGS) mlex.c -c 
X
Xmfile.obj: mfile.c mfile.h lush.h defs.h
X	$(CC) $(CFLAGS) mfile.c -c 
X
Xmenu.obj:	menu.c menu.h lush.h defs.h config.h
X	$(CC) $(CFLAGS) menu.c -c
X
Xedit.obj:	edit.c edit.h lush.h defs.h config.h 
X	$(CC) $(CFLAGS) edit.c -c
X
Xenvinit.obj: envinit.c lush.h defs.h config.h
X	$(CC) $(CFLAGS) envinit.c -c
X
Xlogin.obj: login.c defs.h
X	$(CC) $(CFLAGS) login.c -c
X
Xgetin.obj: getin.c defs.h
X	$(CC) $(CFLAGS) getin.c -c
X
Xlush.obj: lush.c lush.h defs.h config.h version.h
X	$(CC) $(CFLAGS) lush.c -c
________This_Is_The_END________
if test `wc -l < Makefile.MS` -ne 71; then
	echo 'shar: Makefile.MS was damaged during transit (should have been 71 lines)'
fi
fi		; : end of overwriting check
echo 'x - config.h'
if test -f config.h; then echo 'shar: not overwriting config.h'; else
sed 's/^X//' << '________This_Is_The_END________' > config.h
X/* config.h - some definitions you might want to change. */
X
X#define GLOBALFILE	"/usr/lib/lush/lushrc" /* global config file */
X#define MENUFILE  	"/usr/lib/lush/menu"  /* menu file */
X#define ROOTMENU  	"MAIN_MENU"          /* the default root menu */
X
X#ifdef MSDOS
X#define LUSHRC		"~/lushrc"        /* user config file */
X/* #define MULTIUSER */        /* if you have the getpwiud() library. */
X#else
X#define LUSHRC    	"~/.lushrc"
X#define MULTIUSER		/* UNIX is always multiuser, right? */
X#endif
X
X#define ILLEGAL   	"|<>;&"      /* disallowed user-input characters */
X#define TERM      	"dumb"      /* terminal type if none in environment */
X
X/* things you probably don't want to change... */
X#define LJ_MAX	20 	/* Max size of setjmp() stack.  This governs how
X			many levels down in the menu hierarchy you can go. */
X
X#define MAX_OPTIONS  20   /*(menu.h) max options per menu */
X#define MAX_RESP     10   /*(menu.h) max number of responses per option */
X#define NAME_SIZE    20   /*(menu.h) Max size of a menu name or option word */
X
X#define MAX_MENUS    50   /*(mparse.c) max number of menus in the system */
X
X#define MAX_TOKENS  200   /*(mlex.c) Max number of lexical tokens. */
________This_Is_The_END________
if test `wc -l < config.h` -ne 28; then
	echo 'shar: config.h was damaged during transit (should have been 28 lines)'
fi
fi		; : end of overwriting check
echo 'x - defs.h'
if test -f defs.h; then echo 'shar: not overwriting defs.h'; else
sed 's/^X//' << '________This_Is_The_END________' > defs.h
X/* File:    defs.h
X   Author:  PAS
X   Date:    Sept 7, 1987
X   Purpose: Contains global definitions for lush and other programs.
X */
X/* -- standard headers -------------------------------------------------- */
X
X#ifdef DEBUG
X#include <stdio.h>
X#endif
X#include <fcntl.h>
X
X/* #ifdef MSDOS
X#include <stdlib.h>
X#include <dos.h>
X#include <float.h>
X#endif */
X
X#include <string.h>
X#include <ctype.h>
X#include <time.h>
X#ifdef MULTIUSER
X#include <pwd.h>
X#include <grp.h>
X#endif
X#include <signal.h>
X#include <setjmp.h>
X#include <errno.h>
X
X#ifndef PROTOTYPE	/* function declarations are not done for us. */
Xextern char *malloc();
Xextern int  getopt();
Xextern char *getenv();
Xextern int  putenv();
X#ifdef MULTIUSER
Xextern char *ttyname();
Xextern char *getlogin();
X#endif
X#endif
X
X/* -- system dependent defs --------------------------------------------- */
X
X#ifdef MSDOS
X#define access  laccess      	/* our own access() function. */
X#define TTY   	"con"		/* default terminal. */
X#else
X#define TTY   	"/dev/null"	/* no default terminal. */
X#endif
X
X#ifdef MULTIUSER		/* have getpwiud() library? */
X#define GROUP 	"/etc/group" 	/* various group access permissions. */
X#define PASSWD	"/etc/passwd"	/* where to find the passwords. */
X#else
X#define USER	"nobody"	/* user name */
X#define HOMEDIR	"/"		/* home directory */
X#endif
X
X/* -- immutable defs ---------------------------------------------------- */
X
X/* function return values... */
X#define OK            0
X#define ERROR	     -1
X#define FALSE         0
X#define TRUE          1
X
X#define MAX_LEN     255         /* maximum line length in a file */
X#define PATH_LEN     64         /* max length of a path. */
________This_Is_The_END________
if test `wc -l < defs.h` -ne 67; then
	echo 'shar: defs.h was damaged during transit (should have been 67 lines)'
fi
fi		; : end of overwriting check
echo 'x - edit.c'
if test -f edit.c; then echo 'shar: not overwriting edit.c'; else
sed 's/^X//' << '________This_Is_The_END________' > edit.c
X/*  File:    edit.c 
X    Author:  Paul Shields
X    Date:    May 15, 1987
X    Purpose: this is where the real work is done.
X */
X
X#include "lush.h"
X#ifndef DEBUG
X#include <stdio.h>
X#endif
X#include "edit.h"
X
X#ifdef PROTOTYPE
Xint	(*funcs[])(char *) =   /* array of pointers to functions taking char* and returning int. */
X#else
Xint	(*funcs[])() =
X#endif
X{	     ChgDir,                /* 00 change directory */
X	     ChkPort,               /* 01 check port access */
X	     ChkTerm,               /* 02 check terminal type */
X	     Pause,                 /* 03 pause with "Press enter: " message */
X	     ChkRdAcc,              /* 04 check read access to a file list */
X	     CallCmd,               /* 05 system() to a command with parameters */
X	     SecurChk,              /* 06 perform a security check */
X	     ChkWrAcc,              /* 07 check write access to a file list */
X	     Expert,                /* 08 toggle novice/expert mode */
X	     P1name,                /* 09 write prompt, get parameter. */
X	     P2name,                /* 10 write prompt, get second parameter. */
X	     ChkAccess,             /* 11 check read/write access to a file list */
X	     SetEnvt,		    /* 12 set environment variable */
X	     SaveStr,		    /* 13 save string in (global) recall-buffer */
X	     P1Recall,		    /* 14 put recall-buffer in parameter 1 */
X	     P2Recall		    /* 15 put recall-buffer in parameter 2 */
X};
X
Xstatic char param1[MAX_LEN];     /* parameter for CallCmd. */
Xstatic char param2[MAX_LEN];    /* parameter for CallCmd. */
Xstatic char recall[MAX_LEN];	/* global recall-buffer. */
X
Xint	ChgDir(dn)                  /* change to a directory. */
Xchar	*dn;
X{
X	char  *buf, pbuf[MAX_LEN];
X
X	sprintf(pbuf, dn, param1, param2);  /* add the parameter(s) to the command. */
X    buf = envsubst(pbuf);               /* substitute environment variables if nec. */
X
X    if(chdir(buf) != 0) {
X        perror(buf);
X        return ERROR;
X    }
X	return OK;
X}
X
Xint lookupfile(nam, str)            /* find a string in a file. */
Xchar *nam, *str;
X{
X    FILE *fp;
X    char line[MAX_LEN+1];
X    int  i = strlen(str);
X
X    line[MAX_LEN] = '\0';
X    if((fp = fopen(nam, "r")) != NULL) {
X        while(fgets(line, MAX_LEN, fp) != NULL)
X            if(strncmp(str, line, i) == 0) {
X                fclose(fp);
X                return OK;
X            }
X        fclose(fp);
X    } else
X    	perror(nam);
X
X    return ERROR;
X}
X
Xint   ChkPort(c)                    /* check for local mode */
Xchar  *c;
X{  
X    if(lookupfile(c, tty) == OK)
X        return OK;
X
X	printf("\nThis command is unavailable from TTY %s\n", tty);
X	return ERROR;
X}
X
Xint   ChkTerm(c)                  /* check for remote mode */
Xchar  *c;
X{  
X    if(lookupfile(c, term) == OK)
X        return OK;
X
X	printf("\nThis command is unavailable on terminals of type %s\n", term);
X    return ERROR;
X}
X
Xint   Pause(c)                      /* wait for user */
Xchar  *c;
X{
X	getin("Press enter: ");
X	return OK;
X}
X
Xint ChkRdAcc(list)              /* 04 */
Xchar    *list;
X{
X	printf("\nFile Access Check failed\n");
X    return ERROR;
X}
X
Xint ChkWrAcc(list)              /* 07 */
Xchar    *list;
X{
X	printf("\nFile Access Check failed\n");
X    return ERROR;
X}
X
Xint ChkAccess(list)             /* 11 */
Xchar    *list;
X{
X	printf("\nFile Access Check failed\n");
X    return ERROR;
X}
X
Xint   P1name(prompt)
Xchar  *prompt;
X{
X	int   i;
X	char  *p;
X
X	p = getin(prompt);
X
X	if(strlen(p) > 0) {
X	   /* none of that funny stuff... */
X	   i = strcspn(p, ILLEGAL);
X	}
X	else i=0;
X
X	strncpy(param1, p, i);
X	param1[i] = '\0';
X
X	return OK;                    /* null is ok. */
X}
X
Xint   P2name(prompt)
Xchar  *prompt;
X{
X	int   i;
X	char  *p;
X
X	p = getin(prompt);
X
X	if(strlen(p) > 0) {
X	   /* none of that funny stuff... */
X	   i = strcspn(p, ILLEGAL);
X	}
X	else i=0;
X
X	strncpy(param2, p, i);
X	param2[i] = '\0';
X
X	return OK;                    /* null is ok. */
X}
X
Xint   CallCmd(cmd)               /* use the system function to execute a command. */
Xchar  *cmd;                      /* name of command to call. */
X{
X	int   ret;
X	char  *buf, pbuf[MAX_LEN];
X
X	sprintf(pbuf, cmd, param1, param2);  /* add the parameter(s) to the command. */
X    buf = envsubst(pbuf);               /* substitute environment variables if nec. */
X
X#ifdef DEBUG
X    if(debuglevel & 1)
X        fprintf(stderr,"CallCmd(%s)= system(\"%s\")\n", cmd, buf);
X#endif
X	if((ret = system(buf)) == 0) 
X        return OK;
X
X#ifdef DEBUG
X	fprintf(stderr,"--returned error %d--\n", errno);
X	perror(buf);
X#endif
X	return ERROR;
X}
X
X/* Return TRUE if user is a member of the group, ow FALSE.
X */
Xstatic int member(gr)
Xchar *gr;
X{
X#ifdef MULTIUSER
X	struct group *grp;
X	char **n;
X	
X	if((grp = getgrnam(gr)) != NULL) {
X	for(n = grp->gr_mem; *n != NULL && strcmp(user, *n) != 0; n++)
X#ifdef DEBUG
X	     if(debuglevel & 1)
X	         fprintf(stderr, "%s ",*n)
X#endif
X	    ;
X	return (*n != NULL);
X	}
X	/* else invalid group. */
X	printf("\nSystem error verifying group %s. Please consult system administrator\n",gr);
X	return FALSE;
X#else
X	/* in single-user system, always return TRUE */
X
X	return TRUE;
X#endif
X}
X
Xint   SecurChk(gr)	/* check to see that the user is a member of the */
Xchar  *gr;		/* permitted groups... */
X{
X#ifdef DEBUG
X	if(debuglevel & 1)
X	   fprintf(stderr,"SecurChk(%s) ",gr);
X#endif     
X#ifdef MULTIUSER
X	if(getuid() == 0)
X        return OK;
X
X	if(*gr == '!') {		/* user must not be member of this group. */
X	   if(!member(++gr)) return OK;
X	} else
X	   if(member(gr)) return OK;
X	   
X	printf("\nYou are not allowed to use this command.\n");
X	return ERROR;
X#else
X	return OK;	/* single-user system, always return TRUE. */
X#endif
X}
X
Xint   Expert(w)                 /* toggle novice/expert mode */
Xchar  *w;
X{
X	novice ^= TRUE;               /* xor */
X	return OK;
X}
X
Xint   SetEnvt(w)	/* set environment variable. allocates memory for it, */
Xchar  *w;		/* and substitutes parameters, etc. */
X{
X	char  *buf, pbuf[MAX_LEN];
X
X	sprintf(pbuf, w, param1, param2);  /* add the parameter(s) to the command. */
X	buf = envsubst(pbuf);           /* substitute environment variables if nec. */
X
X	if((w = malloc(strlen(buf)+1)) == NULL)	/* allocate in static storage */
X	  return ERROR;
X	strcpy(w, buf);
X
X	if(putenv(w) != 0) {
X	  free(w);
X	  return ERROR;
X	} 
X	return OK;
X}
X
Xint   SaveStr(w)	/* save string in global recall buffer. */
Xchar  *w;
X{
X	strncpy(w, recall, MAX_LEN-1);
X	recall[MAX_LEN] = 0;
X	return OK;
X}
X
Xint   P1Recall(w)	/* save string in global recall buffer. */
Xchar  *w;
X{
X	strcpy(recall, param1);
X	return OK;
X}
Xint   P2Recall(w)	/* save string in global recall buffer. */
Xchar  *w;
X{
X	strcpy(recall, param2);
X	return OK;
X}
________This_Is_The_END________
if test `wc -l < edit.c` -ne 283; then
	echo 'shar: edit.c was damaged during transit (should have been 283 lines)'
fi
fi		; : end of overwriting check
echo 'x - envinit.c'
if test -f envinit.c; then echo 'shar: not overwriting envinit.c'; else
sed 's/^X//' << '________This_Is_The_END________' > envinit.c
X/* File:    envinit.c
X   Author:  Paul Shields
X   Date:    May 13, 1987
X   Purpose: sets up variables for the environment.
X */
X
X#include "lush.h"
X#ifndef DEBUG
X#include <stdio.h>
X#endif
X
X/* We logged into the console, a local tty, or a remote tty. Certain things
X  are unavailable from a remote tty, so we'll need to compare the environment
X  variable TTY with a list of permitted devices when the need calls for it.
X */
Xchar *root_menu = NULL,	/* default main menu name. */
X     *menufile = NULL,  /* name of menu file. */
X     *globalrc = NULL,  /* name of global rc file. */
X     *userrc = NULL,    /* name of user rc file. */
X     *user, 		/* name of the user. */
X     *tty,              /* TTY environment variable. */
X     *term = NULL;      /* TERM environment variable. */
X
Xchar *CL, *SO, *SE;     /* termcap Clear-screen, Stand-out, Unstand-out */
Xint  LI, CO;		/* lines, columns */
X
X
Xchar *
Xgethome(u)		/* allocate and return user home dir or null. */
Xchar *u;
X{
X#ifdef MULTIUSER
X	struct passwd *pw;
X	/* if u is null, use default of current user. */
X	if(u == NULL || strlen(u) == 0)
X	  u = user;
X	if((pw = getpwnam(u)) == NULL)
X	    return NULL;
X	if((u = malloc(strlen(pw->pw_dir)+1)) == NULL)
X	    return NULL;
X	strcpy(u,pw->pw_dir);
X	return u;
X#else
X	return HOMEDIR;
X#endif
X}
X
X/* allocate and store an environment variable. */
Xchar *mputenv(var,def)
Xchar *var,*def;
X{
X	char *ut;
X	if((ut = malloc(strlen(var)+1+strlen(def)+1)) == NULL)
X	   return NULL;
X	sprintf(ut, "%s=%s",var,def);
X	putenv(ut);
X	return ut;
X}
X
X#define trim(s)	 {char *tl; while(*s && isspace(*s)) s++; \
X	for(tl=s; *tl; tl++) ; for(tl--; tl > s; tl--) \
X	 { if(isspace(*tl)) *tl = '\0'; else break; } }
X
X/* Process a line in the global rc.
X	Allow environment definitions.
X	Do translation of $VAR and ~user strings. 
X	*** Yet to add: System() out to commands enclosed in ``.
X
X	Side-effects: writes junk into the line. 
X */
Xstatic int proc_global(line)
Xchar *line;
X{
X	char *tl, *var, *def;
X
X#ifdef DEBUG
X	if(debuglevel & 1)
X	   fprintf(stderr,"line: |%s|\n",line);
X#endif
X
X/***/ /* this won't do. need to convert to use the scanner in mparse.c */
X	if((tl = strpbrk(line,"#")) != NULL)	/* strip comments */
X	   *tl = '\0';
X
X	/* look for = and break into two: "A=B" => "A","B" */
X	if((def = strpbrk(line, "=")) != NULL) {
X	   var = strtok(line, "=");
X	   def++;
X	   trim(var);		/* zap leading/trailing white space */
X	   trim(def);
X	   tl = envsubst(def);	/* do $ and ~ substitutions */
X	   mputenv(var, tl);
X	} else {
X	   trim(line);
X	   if(strlen(line) > 0)
X	      return ERROR;
X	}
X	return OK;
X}
X
X/* Process a line in the user rc.
X     Only environment definitions allowed. 
X     Restrict to ones already defined.
X */
Xstatic int proc_user(line)
Xchar *line;
X{
X	return proc_global(line);	/***/ /* for now, do the same. */
X}
X
X/* Get and process the global rc file */
Xstatic int getrc_global(name)
Xchar *name;
X{
X	FILE *fp;
X	char line[MAX_LEN+1];
X	int  ln;
X
X	if((fp=fopen(name, "r")) == NULL) {
X	   perror(name);
X	   return ERROR;
X	}
X	for(ln=1; fgets(line, MAX_LEN, fp) != NULL; ln++)
X	   if(proc_global(line) == ERROR)
X	      fprintf(stderr,"%s: syntax error: line %d\n",name,ln);
X	fclose(fp);
X	return OK;
X}
X
X/* Get and process the user rc file */
Xstatic int getrc_user(name)
Xchar *name;
X{
X	FILE *fp;
X	char line[MAX_LEN+1];
X	int  ln;
X
X	if((fp=fopen(name, "r")) == NULL) {
X	   perror(name);
X	   return ERROR;
X	}
X	for(ln=1; fgets(line, MAX_LEN, fp) != NULL; ln++)
X	   if(proc_user(line) == ERROR)
X	      fprintf(stderr,"%s: syntax error: line %d\n",name,ln);
X	fclose(fp);
X	return OK;
X}
X
Xint envinit(argc,argv)
Xint  argc;
Xchar *argv[];
X{
X	register char *h;
X	char *ut;		/* temporary */
X	int err = 0, c;
X	extern char *optarg;
X
X#ifndef MSDOS
X	if(getenv("SHELL") != argv[0]) 		/* security. */
X	    mputenv("SHELL",argv[0]);
X#endif
X
X	/* find out who we are. */
X#ifdef MULTIUSER
X	if((user = getlogin()) == NULL) {
X	    struct passwd *pw;
X	    if((pw = getpwuid(getuid())) == NULL) {
X		fprintf(stderr,"Can't find your username anywhere.\n");
X		return ERROR;
X	    }
X	    ut = pw->pw_name;
X	    if((user = malloc(strlen(ut)+1)) == NULL)
X		{ perror("envinit()"); return ERROR; }
X	    strcpy(user,ut);
X	}
X#else
X	user=USER;
X#endif
X	mputenv("USER",user);
X#ifdef DEBUG
X    if(debuglevel & 1)
X	fprintf(stderr,"USER=<%s> ",user);
X#endif
X
X	if((ut = getenv("HOME")) == NULL) {
X	  if((ut = gethome(user)) == NULL) {
X	    fprintf(stderr,"No home directory.\n");
X	    return ERROR;
X	  }
X	  mputenv("HOME",ut);
X	}
X#ifdef DEBUG
X    if(debuglevel & 1)
X	fprintf(stderr,"HOME=<%s> ",ut);
X#endif
X
X	/* process the command line options... */
X	while ((c = getopt(argc, argv, "f:R:M:G:U:")) != EOF)
X	  switch((char)c) {
X	    case 'f':
X	    case 'M': 
X		if((menufile=malloc(strlen(optarg)+1)) == NULL)
X		  { perror("envinit()"); return ERROR; }
X		strcpy(menufile,optarg);
X		break;
X	    case 'R':
X		if((root_menu=malloc(strlen(optarg)+1)) == NULL)
X		  { perror("envinit()"); return ERROR; }
X		strcpy(root_menu,optarg);
X		break;
X	    case 'G': 
X		if((globalrc=malloc(strlen(optarg)+1)) == NULL)
X		  { perror("envinit()"); return ERROR; }
X		strcpy(globalrc,optarg);
X		break;
X	    case 'U':
X		if((userrc=malloc(strlen(optarg)+1)) == NULL)
X		  { perror("envinit()"); return ERROR; }
X		strcpy(userrc,optarg);
X		break;
X	    case '?':
X		err = TRUE;
X	  }
X	if(err) {
X	  fprintf(stderr, "Usage:  %s [-G global-config-file] [-M menufile]\n",argv[0]);
X	  fprintf(stderr, "            [-R rootmenu] [-U user-config-file]\n");
X	  return ERROR;
X	}
X
X	if(globalrc == NULL)		/* default global rc file location */
X	  globalrc = GLOBALFILE;
X
X#ifdef DEBUG
X    if(debuglevel & 1)
X	fprintf(stderr,"global rc=<%s>\n",globalrc);
X#endif
X	/* Now process global rc file... must always exist. */
X	getrc_global(globalrc);
X
X	if(menufile == NULL)		/* default menu file location */
X	  if((menufile = getenv("MENUFILE")) == NULL)
X	    menufile = MENUFILE;
X
X	if(root_menu == NULL) 		/* default root menu name */
X	  if((root_menu = getenv("ROOTMENU")) == NULL)
X	    root_menu = ROOTMENU;
X
X	if(userrc == NULL)
X	  if((userrc = getenv("LUSHRC")) == NULL)
X	    userrc = LUSHRC;
X
X#ifdef DEBUG
X    if(debuglevel & 1)
X	printf("userrc: <%s>, menufile: <%s>, root_menu: <%s>\n",
X	    userrc, menufile, root_menu);
X#endif
X	/***/ /* note: may need to subst ~ in userrc here. */
X
X	/* now process the user rc file... */
X	getrc_user(userrc);
X
X	if((tty = getenv("TTY")) == NULL) {     /* default terminal */
X#ifdef MULTIUSER
X	   if((ut = ttyname(fileno(stdin))) == NULL)
X	      tty = TTY;
X	   else {
X		tty = malloc(strlen(ut)+1);
X		strcpy(tty, ut);
X	   }
X#else
X	   tty = TTY;
X#endif
X	   mputenv("TTY",tty);
X	}
X
X	if((term = getenv("TERM")) == NULL) {   /* default to "dumb" terminal */
X	   term = TERM;
X	   mputenv("TERM",term);
X	}
X
X	return OK;
X}
X
X/* Initialize the termcap variables. Some of this code is from MicroEMACS 
X   by Daniel M. Lawrence (and others.) */
Xint
Xtcapinit()                  /* important. call envinit() before this. */
X{
X    char *tgetstr();
X    int  tgetnum();
X    char tcbuf[1024];
X    static char strbuf[128];
X    char *str = strbuf;
X
X    if (term == NULL) {
X        fprintf(stderr,"Environment variable TERM not defined!\n");
X        return ERROR;
X    }
X
X    if ((tgetent(tcbuf, term)) <= 0) {
X        fprintf(stderr, "Unknown terminal type %s!\n", term);
X        return ERROR;
X    }
X
X    LI = tgetnum("li");			/* lines & columns */
X    CO = tgetnum("co");
X
X    if((CL = tgetstr("cl",&str)) == NULL)	/* clear screen */
X	CL = "\n------------------------------------------------------------------------------\n";
X
X    if((SO =  tgetstr("so",&str)) == NULL)	/* stand-out enter */
X	SO = "";
X
X    if((SE = tgetstr("se", &str)) == NULL)	/* stand-out end */
X	SE = "";
X
X    /* caution: we lose access to tcbuf now. don't call any more termcap
X       functions. CL, SO, and SE are in static memory. */
X
X    return OK;
X}
X
Xstatic char retbuf[BUFSIZ];
X#define scanword(s, var)    {char *tmp; \
X	  tmp = ++(s);  while(isalnum(*(s))) (s)++; \
X	  strncpy(var, tmp, (s)-tmp); \
X	  (var)[(s)-tmp] = '\0'; }
X
Xchar *      /* substitute environment values in "$VAR" strings for s. */
Xenvsubst(s) /* returns with static data which is overwritten by the next call. */
Xchar *s;
X{
X    char *r = retbuf, *tmp;
X    static char var[MAX_LEN];
X
X    while(*r = *s) {
X	if(*s == '\\')		/* escape with \$ or \~. */
X	  *++r = *++s;
X	if(*s == '$') {		/* substitute */
X	  scanword(s, var);
X	  if((tmp = getenv(var)) == NULL)     /* look it up.. */
X	    tmp = "";		/* Nothing there */
X	  while(*r = *tmp++)	/* copy */
X	    r++;
X          continue;
X        }
X	if(*s == '~') {		/* look for ~user */
X	  scanword(s, var);
X
X	  if((tmp = gethome(var)) == NULL)
X	    tmp = "";		/* no translation */
X
X	  while(*r = *tmp++)	/* copy */
X	    r++;
X          continue;
X	}
X        s++;
X        r++;
X    }
X
X    return retbuf;
X}
________This_Is_The_END________
if test `wc -l < envinit.c` -ne 362; then
	echo 'shar: envinit.c was damaged during transit (should have been 362 lines)'
fi
fi		; : end of overwriting check
echo 'x - login.c'
if test -f login.c; then echo 'shar: not overwriting login.c'; else
sed 's/^X//' << '________This_Is_The_END________' > login.c
X/*  File:    login.c 
X    Author:  Paul Shields
X    Date:    May 13, 1987
X    Purpose: Miscellaneous esoteric system-dependent functions
X */
X
X#include "defs.h"
X#ifndef NULL
X#define NULL (char *)0
X#endif
X
X/***/ /* the following is a stub. it does nothing. */
Xvoid login(p)		/* log in operator. */
Xchar *p;     		/* oper name */
X{
X#ifdef MULTIUSER
X	struct passwd *pwd = getpwuid(getuid());
X
X    if((char *)pwd != NULL)
X    	strcpy(p,pwd->pw_name);		   /* set operator name */
X#else
X	strcpy(p,USER);
X#endif
X
X	/***/ /* remember login time. */
X}
X
X/***/ /* the following is a stub. it does nothing. */
Xvoid logout(p)			   /* log out operator */
Xchar *p;      			   /* oper name */
X{  /* log system use */
X}
________This_Is_The_END________
if test `wc -l < login.c` -ne 32; then
	echo 'shar: login.c was damaged during transit (should have been 32 lines)'
fi
fi		; : end of overwriting check
echo 'x - version.h'
if test -f version.h; then echo 'shar: not overwriting version.h'; else
sed 's/^X//' << '________This_Is_The_END________' > version.h
X#define VERSION "LUSH version 1.35, Mon Jan  8 17:06:49 EST 1990"
________This_Is_The_END________
if test `wc -l < version.h` -ne 1; then
	echo 'shar: version.h was damaged during transit (should have been 1 lines)'
fi
fi		; : end of overwriting check
exit 0
-- 
Paul Shields, shields@nccn.yorku.ca  (..!uunet!yunccn!shields)

pat@rwing.UUCP (Pat Myrto) (01/14/90)

In article <3890@yunccn.UUCP>, shields@yunccn.UUCP (Paul Shields) writes:
> Note: I haven't compiled lush for MS-DOS in at least a year. You may
> have to work on it.

When the Version 1.35 sources are combined with the rest of the
package posted earlier as Version 1.34, I discovered it wouldn't
compile under Sys V, stopping at edit.c with 'grp' being undefined.

The problem is the order in which lush.h includes defs.h and config.h.
The present order of including defs.h before config.h prevents defs.h
from seeing if MULTIUSER is defined in config.h, preventing the struct
group *grp from being defined.  The fix is to simply reverse the order
of the includes in lush.h from

#include "defs.h"			/* old directives	*/
#include "config.h"

	to

#include "config.h"			/* fixed directives	*/
#include "defs.h"

The package will now compile under Sys V the same as Version 1.34.
Hopefully this will save someone the time of figuring out why the
structure wasn't defined in this version when it was OK in the the
previous one.

-- 
pat@rwing                                       (Pat Myrto),  Seattle, WA
                     ...!uunet!gtenmc!pilchuck!rwing!pat
      ...!uw-beaver!uw-entropy!dataio!/
WISDOM:    "Travelling unarmed is like boating without a life jacket"