[comp.sources.unix] v17i095: E, friendlier front-end to vi, Part01/03

rsalz@uunet.uu.net (Rich Salz) (02/10/89)

Submitted-by: speedboat jones <tcjones@watdragon.waterloo.edu>
Posting-number: Volume 17, Issue 95
Archive-name: e2/part01

Hi. Here is a new version (1.3) of e - the vi front end thing. It has several
new features, including a way around the modeline security problem.

     e is an interface to vi(1) that maintains a history of the
     most recently e'ed files for each directory. Using the his-
     tory, it is both fast and simple to re-edit previously e'ed
     files.

     In addition, e does spelling corrections on its arguments,
     fast lookup and editing of files in other directories, and
     allows for the inheritance of .exrc files in other direc-
     tories. It also closes the modeline security hole, making it
     possible to ensure that no .exrc file that you don't own is
     ever seen by vi.

Terry Jones.

    Department Of Computer Science,  University Of Waterloo
    Waterloo Ontario Canada N2L 3G1. Phone: 1-519-8884674
    UUCP:                    ...!watmath!watdragon!tcjones
    CSNET, Internet, CDNnet: tcjones@dragon.waterloo.{cdn,edu}
    BITNET:                  tcjones@WATER.bitnet
    Canadian domain:         tcjones@dragon.uwaterloo.ca




#! /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 3)."
# Contents:  MANIFEST Makefile README abandon.c check_hist.c
#   dir_check.c dir_find.h e_error.c e_update.sh find_hist.c
#   find_match.c get_temp.c inheritance.c insert_cmd.c io.c new_vi.c
#   normal.c nth_hist.c reconstruct.c signal.c sp_dist.c tags
# Wrapped by tcjones@watdragon on Thu Feb  9 10:01:02 1989
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'\" \(1020 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X
XE version 1.3 comes with the following files...
X
MODS.....................2757
Makefile.................1792
README...................2385
abandon.c................917
ask_hist.c...............2657
check_hist.c.............385
dir_check.c..............987
dir_find.c...............3846
dir_find.h...............379
do_vi.c..................4970
e.1......................9576
e.c......................5750
e.h......................4788
e_error.c................722
e_update.sh..............789
find_hist.c..............2299
find_match.c.............1261
get_temp.c...............338
inheritance.c............173
insert_cmd.c.............1153
io.c.....................1161
main.c...................2804
multiple.c...............2638
new_vi.c.................546
normal.c.................1784
nth_hist.c...............516
read_hist.c..............6117
reconstruct.c............2004
signal.c.................495
sp_dist.c................1011
spell_help.c.............3614
terminal.c...............3469
X
And this Manifest.
X
END_OF_FILE
if test 1020 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
chmod +x 'MANIFEST'
# 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'\" \(1792 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
X# E version 1.3, November 1988
X# Terry Jones (tcjones@dragon.waterloo.edu)
X#
X
X
X
X# UNIX *must* be one of BSD, SUN, SYSV, ULTRIX or DYNIX.
UNIX = Bsd
X
X
X# There's probably no need to change anything below this.
X
CFLAGS = -O -D$(UNIX)
HEADERS = e.h
OBJ = \
X	abandon.o \
X	ask_hist.o \
X	check_hist.o \
X	dir_check.o \
X	dir_find.o \
X	do_vi.o \
X	e.o \
X	e_error.o \
X	find_hist.o \
X	find_match.o \
X	get_temp.o \
X	inheritance.o \
X	insert_cmd.o \
X	io.o \
X	main.o \
X	multiple.o \
X	new_vi.o \
X	normal.o \
X	nth_hist.o \
X	read_hist.o \
X	reconstruct.o \
X	signal.o \
X	sp_dist.o \
X	spell_help.o \
X	terminal.o
X
SRC = \
X	abandon.c \
X	ask_hist.c \
X	check_hist.c \
X	dir_check.c \
X	dir_find.c \
X	do_vi.c \
X	e.c \
X	e_error.c \
X	find_hist.c \
X	find_match.c \
X	get_temp.c \
X	inheritance.c \
X	insert_cmd.c \
X	io.c \
X	main.c \
X	multiple.c \
X	new_vi.c \
X	normal.c \
X	nth_hist.c \
X	read_hist.c \
X	reconstruct.c \
X	signal.c \
X	sp_dist.c \
X	spell_help.c \
X	terminal.c
X
e : $(HEADERS) $(OBJ)
X	cc $(CFLAGS) -o e $(OBJ)
X	strip e
X
abandon.o        : e.h
ask_hist         : e.h
check_hist       : e.h
dir_check        : e.h
dir_find.o       : e.h dir_find.h
do_vi.o          : e.h
e.o              : e.h
e_error.o        : e.h
find_hist.o      : e.h
find_match.o     : e.h
get_temp.o       : e.h
inheritance.o    : e.h
insert_cmd.o     : e.h
io.o             : e.h
main.o           : e.h
multiple.o       : e.h
new_vi.o         : e.h
normal.o         : e.h
nth_hist.o       : e.h
read_hist.o      : e.h
reconstruct.o    : e.h
signal.o         : e.h
spell_help.o     : e.h
terminal.o       : e.h
X
lint :
X	lint -D$(UNIX) *.[ch]
X
tags : $(SRC)
X	ctags *.[ch]
X
shar : tags
X	manifest.sh
X	makekit -s30k README e.1 Makefile MANIFEST MODS *.[ch] e_update.sh tags
X
manifest:
X	manifest.sh
X
doc : e.1
X	troff -man -Tdumb e.1 | ddumb > e.cat 
END_OF_FILE
if test 1792 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
chmod +x 'Makefile'
# 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'\" \(2385 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
README - e version 1.3
X
X
Blurb:
X    e is a command line preprocessor to get you into vi with ease.
X    I find it very useful - even given a shell with history. It keeps 
X    a history of the files that have been e'ed most recently in each 
X    directory. Thus it is nice to be able to do
X
X    cd somewhere
X    e
X
X    and get straight into the file you were last working on in the 
X    directory "somewhere". It also allows fast cross-directory editing,
X    does spelling corrections and solves the nasty modeline security
X	problem by allowing you to ensure that you never inherit someone
X	else's .exrc file.
X
X
Documentation:
X    Documentation and examples can be found in the man page in e.1. 
X    This is in troff -man format.
X
X
Installing e:
X    Change the UNIX line at the start of the Makefile. This *must* be 
X    one of Bsd, Sun, Sysv, Ultrix or Dynix. 
X
X    [If you are on a sequent (dynix), change the e dependency
X     line in the Makefile to "e :& $(HEADERS) $(OBJS)" to get parallel make]
X
X    Then make.
X
X    If you use a previous version of e, you will want to update your old 
X    .e files as the new version uses a single .e file in your home 
X    directory. The format is slightly different. The shell script in 
X    e_update.sh will make the changes for you.
X
X
Portability:
X    This is known to work on BSD4.[23], Ultrix 2.0, Dynix (BSD4.2 universe),
X    and SUN 3.0. I put quite alot of time into trying to get it to go on
X    a SVR2 NCR tower here, but it was so *incredibly* slow that I ran out
X    of patience - but it is *very* close (it compiles, but the terminal gets
X    screwed up sometimes). Please let me know if you make it work.
X
X	It passes through lint without comment - except for the screwy stuff
X	in <sys/ioctl.h> on BSD.
X
X
Thanks:
X    To Phil Oldiges, Simon Brown and John Sellens.
X    Also to Doug Gwyn for his directory routines and answering questions
X    about them.
X
X
X-------------------------------------------------------------------------------
Terry Jones, Department Of Computer Science, University Of Waterloo
X             Waterloo Ontario Canada N2L 3G1
X{ihnp4,allegra,decvax,utzoo,utcsri,clyde}!watmath!watdragon!tcjones
tcjones@dragon.waterloo.{cdn,edu} tcjones@WATER.bitnet
tcjones%watdragon@waterloo.csnet [from oz, tcjones@dragon.waterloo.cdn@munnari]
X-------------------------------------------------------------------------------
END_OF_FILE
if test 2385 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
chmod +x 'README'
# end of 'README'
fi
if test -f 'abandon.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'abandon.c'\"
else
echo shar: Extracting \"'abandon.c'\" \(917 characters\)
sed "s/^X//" >'abandon.c' <<'END_OF_FILE'
X#include "e.h"
X
X/*
X * abandon()
X *
X * Close the old history and the new history files, then unlink the
X * new history. This is called when we wish to leave the program but are
X * not going to call reconstruct() to finish the building of the new history
X * for us. Typically we discover one way or another that the new history wasn't
X * needed (e.g. the user quits or the file requested was the most recently
X * used and so we don't have to update the LRU list.)
X *
X */
void
abandon()
X{
X    if (hist_fp && fclose(hist_fp) == EOF){
X        (void)fprintf(stderr, "%s: Could not fclose '%s'\n", myname, ehist);
X    }
X
X    if (tmp_fp && fclose(tmp_fp) == EOF){
X        (void)fprintf(stderr, "%s: Could not fclose '%s'\n", myname, tmp_file);
X    }
X
X    if (tmp_fp && unlink(tmp_file) == -1){
X        (void)fprintf(stderr, "%s: Could not unlink '%s'\n", myname, tmp_file);
X    }
X
X    hist_fp = tmp_fp = NULL;
X    return;
X}
X
END_OF_FILE
if test 917 -ne `wc -c <'abandon.c'`; then
    echo shar: \"'abandon.c'\" unpacked with wrong size!
fi
# end of 'abandon.c'
fi
if test -f 'check_hist.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'check_hist.c'\"
else
echo shar: Extracting \"'check_hist.c'\" \(385 characters\)
sed "s/^X//" >'check_hist.c' <<'END_OF_FILE'
X#include "e.h"
X
X/*
X * check_hist()
X *
X * Make sure the history ok. This is called by things which are intending
X * toperform some history-relatd stuff after calling read_hist().
X *
X */
void
check_hist()
X{
X    if (hist_count == -1){
X        e_error("Couldn't find %s history '%s'.", myname, ehist);
X    }
X
X    if (hist_count == 0){
X        e_error("No history for '%s'.", cwd);
X    }
X}
END_OF_FILE
if test 385 -ne `wc -c <'check_hist.c'`; then
    echo shar: \"'check_hist.c'\" unpacked with wrong size!
fi
# end of 'check_hist.c'
fi
if test -f 'dir_check.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dir_check.c'\"
else
echo shar: Extracting \"'dir_check.c'\" \(987 characters\)
sed "s/^X//" >'dir_check.c' <<'END_OF_FILE'
X#include "e.h"
X
X/*
X * dir_check()
X *
X * Checks to see if the name 'target' can be found in the directory 'dir'.
X * Make sure you are able to read it and that it is in fact a regular file.
X * Return 1 if it can, 0 if not.
X * 
X */
int 
dir_check(target, dir)
char *target;
char *dir;
X{
X    char filename[MAXPATHLEN];
X    struct stat sbuf;
X
X    ok_sprintf(filename, "%s/%s", dir, target);
X    if (stat(filename, &sbuf) == -1){
X        return 0;
X    }
X    /* 
X     *  If it is not a directory and EITHER you own it and can
X     *  read it OR you don't own it and it is readable by others, 
X     *  OR you are in the group of the owner and it's group readable
X     *      - then this is it.
X     */
X
X    if (((sbuf.st_mode & S_IFMT) == S_IFREG)  &&  
X        ((sbuf.st_uid == (short)uid && sbuf.st_mode & S_IREAD) ||
X        (sbuf.st_gid == (short)getgid() && sbuf.st_mode & G_READ) ||
X        (sbuf.st_uid != (short)uid && sbuf.st_mode & O_READ))){
X
X        return 1;
X    }
X
X    return 0;
X}
END_OF_FILE
if test 987 -ne `wc -c <'dir_check.c'`; then
    echo shar: \"'dir_check.c'\" unpacked with wrong size!
fi
# end of 'dir_check.c'
fi
if test -f 'dir_find.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dir_find.h'\"
else
echo shar: Extracting \"'dir_find.h'\" \(379 characters\)
sed "s/^X//" >'dir_find.h' <<'END_OF_FILE'
X/* 
X * Directory delimiters for the VIPATH environment variable. 
X *
X */
X#define is_delim(c) ((*c)==' '||(*c)==':'||(*c)=='\t'||(*c)=='\n')
X
X/*
X * Walk over delimiters using the above macro.
X *
X */
X#define skip_delim(c) while (is_delim((c))) (c)++;
X
X/*
X * Walk over non-delimiters using the above macro.
X *
X */
X#define skip_to_next_delim(c) while (*(c) && !is_delim((c))) (c)++;
END_OF_FILE
if test 379 -ne `wc -c <'dir_find.h'`; then
    echo shar: \"'dir_find.h'\" unpacked with wrong size!
fi
# end of 'dir_find.h'
fi
if test -f 'e_error.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'e_error.c'\"
else
echo shar: Extracting \"'e_error.c'\" \(722 characters\)
sed "s/^X//" >'e_error.c' <<'END_OF_FILE'
X#include "e.h"
X
X/*
X * e_error()
X *
X * Error message printer. The argument a should be a format string that
X * can be printed using fprintf(). We make sure the terminal is in a sane
X * condition. Then the message is printed preceded by the
X * name we were invoked with and succeeded by a newline.
X * Then open files are closed and we get out as quickly as we can.
X *
X */
X/* VARARGS1 */
void
e_error(u, v, w, x, y, z)
char *u;
X{
X    terminal(TERM_RESET);
X    ok_fprintf(stderr, "%s: ", myname);
X    ok_fprintf(stderr, u, v, w, x, y, z);
X    if (fputc('\n', stderr) == EOF){
X        perror("fputc");
X        exit(EX_IOERR);
X    }
X    abandon();
X    if (fflush(stderr) == EOF){
X        perror("fflush");
X    }
X    _exit(1);
X}
END_OF_FILE
if test 722 -ne `wc -c <'e_error.c'`; then
    echo shar: \"'e_error.c'\" unpacked with wrong size!
fi
# end of 'e_error.c'
fi
if test -f 'e_update.sh' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'e_update.sh'\"
else
echo shar: Extracting \"'e_update.sh'\" \(789 characters\)
sed "s/^X//" >'e_update.sh' <<'END_OF_FILE'
X#!/bin/sh
X
X#
X# e_update.sh - Walk your directory tree, finding all the old .e files and
X#               turning the contents into a single file ~/.e
X#
X# To be used when changing from old versions of e to version 1.3.
X#
X# DON'T expand(1) this file - there's a TAB in the second sed command.
X# This assumes you don't have .e files hanging around that weren't put
X# there by e.
X#
X
tmp=/tmp/dotty.$$
X
if [ -f $tmp ]
then
X    echo $tmp exists! Try again.
X    exit
fi
X
cd
HOME=`pwd`
cd /
for i in `find $HOME -name .e -print`
do
X    #
X    # remove "/.e" from the end.
X    #
X    echo $i | sed -e 's/\/\.e$//'         
X
X    #
X    # insert a TAB at the front of each name
X    #
X    cat $i | tail -8 | sed -e 's/^/	/'
X
X    #
X    # remove the old file.
X    #
X    rm $i
X
done > $tmp
X
mv $tmp $HOME/.e
END_OF_FILE
if test 789 -ne `wc -c <'e_update.sh'`; then
    echo shar: \"'e_update.sh'\" unpacked with wrong size!
fi
chmod +x 'e_update.sh'
# end of 'e_update.sh'
fi
if test -f 'find_hist.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'find_hist.c'\"
else
echo shar: Extracting \"'find_hist.c'\" \(2299 characters\)
sed "s/^X//" >'find_hist.c' <<'END_OF_FILE'
X#include "e.h"
X
X/*
X * find_hist()
X *
X * Find out where the history file is hiding. If E_HIST (currently this is
X * "VIHIST") is defined, then use that. Otherwise use a default ($HOME/.e
X * at the moment.)
X *
X * If E_HIST starts with a '/' then take it as an absolute path, otherwise
X * take it relative to the home directory.
X *
X * Set up the name of the temporary file to be in the same directory as the
X * history. This ensures 1) that we can write there and 2) that we can use
X * rename(2) when we want to make it the new history. (I'd just use /tmp but 
X * that stops me from using rename).
X *
X */
void
find_hist()
X{
X    char *efile;
X    struct passwd *pwd;
X
X    uid = (int)getuid();
X    pwd = getpwuid(uid);
X
X    if (!pwd){
X        e_error("Could not get password file entry for uid %d.", uid);
X    }
X
X    home = pwd->pw_dir;
X    efile = getenv(E_HIST);
X
X    if (!efile){
X        /*
X         * E_HIST is not set.
X         * Use the default location and name for the history file (that
X         * is name = DEFAULT_HIST in the home directory.)
X         *
X         */
X        ok_sprintf(ehist, "%s/%s", home, DEFAULT_HIST);
X        ok_sprintf(tmp_file, "%s/.e_tempXXXXXX", home);
X    }
X    else{
X        /*
X         * It was set.
X         *
X         */
X        if (*efile == '/'){
X            /*
X             * It's an absolute pathname. Copy it into ehist and tmp_file.
X             * Zero the last '/' in tmp_file it to get the basename, then
X             * strcat the .e_tempXXXXXX stuff. The call to rindex() cannot 
X             * fail to find a '/' since by this time we know that the first 
X             * character of efile (and hence ehist and tmp_file) is '/'.
X             *
X             */
X            strcpy(ehist, efile);
X            strcpy(tmp_file, efile);
X            *rindex(tmp_file, '/') = '\0';
X            strcat(tmp_file, "/.e_tempXXXXXX");
X        }
X        else{
X            /*
X             * Take it as being relative to the home directory.
X             *
X             */
X            ok_sprintf(ehist, "%s/%s", home, efile);
X            ok_sprintf(tmp_file, "%s/.e_tempXXXXXX", home);
X        }
X    }
X
X#ifdef Sysv
X    if (!getcwd(cwd, sizeof(cwd))){
X#else
X    if (getwd(cwd) == (char *)0){
X#endif
X        e_error("Could not get working directory.");
X    }
X    return;
X}
END_OF_FILE
if test 2299 -ne `wc -c <'find_hist.c'`; then
    echo shar: \"'find_hist.c'\" unpacked with wrong size!
fi
# end of 'find_hist.c'
fi
if test -f 'find_match.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'find_match.c'\"
else
echo shar: Extracting \"'find_match.c'\" \(1261 characters\)
sed "s/^X//" >'find_match.c' <<'END_OF_FILE'
X#include "e.h"
X
X
X/*
X * find_match()
X *
X * Find the name in the history list that contains the 'pattern'.
X * If we find one, put it into the 'arg' variable. Otherwise
X * announce that a match couldn't be found and leave.
X *
X */
void
find_match(pattern)
char *pattern;
X{
X    register i;
X	int match();
X
X    /* 
X     * Try for a match with each file in turn. Note that we are working
X     * from most-recently-used backwards.
X     *
X     */
X
X    for (i = hist_count - 1; i >= 0; i--){
X        if (match(hist[i], pattern)){
X            ok_sprintf(arg, "%s", hist[i]);
X            reconstruct(i);
X            return;
X        }
X    }
X
X    /* 
X     * We couldn't match so get out of here. 
X     *
X     */
X    e_error("Unable to match with '%s'.", pattern);
X}
X
X
X
X/*
X * match()
X *
X * Boneheaded but easy pattern matcher. Just see if the 'pattern'
X * exists anywhere in the 'argument'. Boyer-Moore who?
X * In general our patterns will be so short that it wouldn't be
X * worth the effort to set up a better algorithm.
X *
X */
int
match(argument, pattern)
char *argument;
char *pattern;
X{
X    register length = strlen(pattern);
X
X    while (strlen(argument) >= length){
X        if (!strncmp(argument++, pattern, length)){
X            return 1;
X        }
X    }
X    return 0;
X}
END_OF_FILE
if test 1261 -ne `wc -c <'find_match.c'`; then
    echo shar: \"'find_match.c'\" unpacked with wrong size!
fi
# end of 'find_match.c'
fi
if test -f 'get_temp.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'get_temp.c'\"
else
echo shar: Extracting \"'get_temp.c'\" \(338 characters\)
sed "s/^X//" >'get_temp.c' <<'END_OF_FILE'
X#include "e.h"
X
X/* 
X * get_temp()
X *
X * Get ourselves a temporary file for the new history. 
X *
X */
void
get_temp()
X{
X    if (mktemp(tmp_file) != tmp_file){
X        e_error("Could not mktemp.");
X    }
X
X    if ((tmp_fp = fopen(tmp_file, "w")) == NULL){
X        e_error("Could not open temporary file '%s'.", tmp_file);
X    }
X    return;
X}
END_OF_FILE
if test 338 -ne `wc -c <'get_temp.c'`; then
    echo shar: \"'get_temp.c'\" unpacked with wrong size!
fi
# end of 'get_temp.c'
fi
if test -f 'inheritance.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'inheritance.c'\"
else
echo shar: Extracting \"'inheritance.c'\" \(173 characters\)
sed "s/^X//" >'inheritance.c' <<'END_OF_FILE'
X#include "e.h"
X
void
inheritance()
X{
X    if (getenv(E_INHERIT)){
X        inherit = 1;
X    }
X
X    if (getenv(E_SAFE_INHERIT)){
X        safe_inherit = 1;
X    }
X
X    return;
X}
END_OF_FILE
if test 173 -ne `wc -c <'inheritance.c'`; then
    echo shar: \"'inheritance.c'\" unpacked with wrong size!
fi
# end of 'inheritance.c'
fi
if test -f 'insert_cmd.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'insert_cmd.c'\"
else
echo shar: Extracting \"'insert_cmd.c'\" \(1153 characters\)
sed "s/^X//" >'insert_cmd.c' <<'END_OF_FILE'
X#include "e.h"
X
X/*
X * insert_cmd()
X *
X * They want the last file in the history but want to preceed it
X * this time with a command - no problems here.
X *
X */
void
insert_cmd(command)
char *command;
X{
X    char *place;
X
X    /* 
X     * If there was already a command there (indicated by a '+'), then we
X     * want to get rid of it. If there is a '+' but no ' ' (somewhere) after 
X     * it, then the history file is in disarray and we do not try to recover.
X     *
X     */
X
X    if (*hist[hist_count - 1] == '+'){
X        if ((place = index(hist[hist_count - 1], ' ')) == NULL){
X            e_error("History '%s' corrupted, + but no following space", ehist);
X        }
X        skip_white(place);
X    }
X    else{
X        place = hist[hist_count - 1];
X    }
X
X    /* 
X     * Put the new command and the filename into 'arg' 
X     *
X     */
X    ok_sprintf(arg, "%s %s", command, place);
X
X    /* 
X     * Reconstruct, leaving out the oldest name if needed.
X     * reconstruct(-1) will exclude nothing - the history is not full.
X     *
X     */
X    if (hist_count == HIST_LINES){
X        reconstruct(0);
X    }
X    else{
X        reconstruct(-1);
X    }
X    return;
X}
END_OF_FILE
if test 1153 -ne `wc -c <'insert_cmd.c'`; then
    echo shar: \"'insert_cmd.c'\" unpacked with wrong size!
fi
# end of 'insert_cmd.c'
fi
if test -f 'io.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'io.c'\"
else
echo shar: Extracting \"'io.c'\" \(1161 characters\)
sed "s/^X//" >'io.c' <<'END_OF_FILE'
X#include "e.h"
X
X/*
X * char_in()
X *
X * Display the string in 'prompt', go into cbreak and get a single character
X * and then reset the terminal. Return the character.
X *
X */
int
char_in(prompt)
char *prompt;
X{
X    int c;
X
X    ok_fprintf(stderr, "%s", prompt);
X    terminal(TERM_SET);
X    c = getc(stdin);
X    terminal(TERM_RESET);
X    return c;
X}
X
X/*
X * ok_printf()
X *
X * Call fprintf and check the return status. I did this to satisfy lint.
X * It makes things slower with the extra function call overhead though.
X * Sigh.
X *
X */
X/* VARARGS2 */
void
ok_fprintf(stream, format, u, v, w, x, y, z)
XFILE *stream;
char *format;
X{
X    if (fprintf(stream, format, u, v, w, x, y, z) == EOF){
X        perror("fprintf");
X        exit(EX_IOERR);
X    }
X}
X
X
X#ifndef Sysv
X/*
X * ok_srintf()
X *
X * Call sprintf and check the return status. I did this to satisfy lint.
X * It makes things slower with the extra function call overhead though.
X * Sigh.
X *
X */
X/* VARARGS2 */
void
ok_sprintf(dest, format, u, v, w, x, y, z)
char *dest;
char *format;
X{
X    if (sprintf(dest, format, u, v, w, x, y, z) == (char *)EOF){
X        perror("sprintf");
X        exit(EX_IOERR);
X    }
X}
X#endif
END_OF_FILE
if test 1161 -ne `wc -c <'io.c'`; then
    echo shar: \"'io.c'\" unpacked with wrong size!
fi
# end of 'io.c'
fi
if test -f 'new_vi.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'new_vi.c'\"
else
echo shar: Extracting \"'new_vi.c'\" \(546 characters\)
sed "s/^X//" >'new_vi.c' <<'END_OF_FILE'
X#include "e.h"
X
X/* 
X * Attempt to make a new history file.
X *
X */
void
new_vi()
X{
X    FILE *vh;
X
X    /* 
X     * If we can't make it, get out. 
X     *
X     */
X    if ((vh = fopen(ehist, "w")) == NULL){
X        e_error("Could not open new history.");
X    }
X
X    /* 
X     * Put in the directory and 'arg' that we will be vi'ing in a second. 
X     *
X     */
X    ok_fprintf(vh, "%s\n\t%s\n", cwd, arg);
X
X    /* 
X     * Close the history. 
X     *
X     */
X    if (fclose(vh) == EOF){
X        e_error("Could not close '%s'.", ehist);
X    }
X    return;
X}
END_OF_FILE
if test 546 -ne `wc -c <'new_vi.c'`; then
    echo shar: \"'new_vi.c'\" unpacked with wrong size!
fi
# end of 'new_vi.c'
fi
if test -f 'normal.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'normal.c'\"
else
echo shar: Extracting \"'normal.c'\" \(1784 characters\)
sed "s/^X//" >'normal.c' <<'END_OF_FILE'
X#include "e.h"
X
X/* 
X * normal()
X *
X * A normal filename was found, put it into arg. First of all if there
X * is a history and this file is already in it (which means they could
X * have gotten to this file in other ways), then reconstruct the history
X * as though they had. Also offer spelling help.
X *
X */
X
void
normal(string)
char *string;
X{
X    ok_sprintf(arg, "%s", string);
X
X    if (hist_count != -1){
X
X        register int i;
X
X        /* 
X         * If it is in the history then reconstruct and return. 
X         *
X         */
X        for (i = 0; i < hist_count; i++){
X            if (!strcmp(hist[i], arg)){
X                reconstruct(i);
X                return;
X            }
X        }
X
X        /* 
X         * It's not in the history, help with spelling then reconstruct. 
X         *
X         */
X        if (!spell_help(0)){
X            dir_find();
X        }
X
X        /* 
X         * If it is in the history then reconstruct and return. 
X         * (It may now be in the history even if it wasn't before - this
X         * is because dir_find() or spell_help() may have done something to 
X         * arg.)
X         *
X         */
X        for (i = 0; i < hist_count; i++){
X            if (!strcmp(hist[i], arg)){
X                reconstruct(i);
X                return;
X            }
X        }
X
X        /*
X         * Reconstruct and leave out the oldest if needed.
X         *
X         */
X        if (hist_count == HIST_LINES){
X            reconstruct(0);
X        }
X        else{
X            reconstruct(-1);
X        }
X    }
X    else{
X
X        /* 
X         * There is no history around so help with spelling and set up a 
X         * history for next time.
X         *
X         */
X
X        if (!spell_help(0)){
X            dir_find();
X        }
X        new_vi();
X    }
X    return;
X}
X
END_OF_FILE
if test 1784 -ne `wc -c <'normal.c'`; then
    echo shar: \"'normal.c'\" unpacked with wrong size!
fi
# end of 'normal.c'
fi
if test -f 'nth_hist.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nth_hist.c'\"
else
echo shar: Extracting \"'nth_hist.c'\" \(516 characters\)
sed "s/^X//" >'nth_hist.c' <<'END_OF_FILE'
X#include "e.h"
X
X/*
X * Get the nth last filename from hlist. Then rebuild the history for
X * the directory, putting the requested filename last (most recently used).
X *
X */
void
nth_hist(n)
int n;
X{
X    if (n >= hist_count){
X        if (hist_count > 1){
X            e_error("Only %d history items exist.", hist_count);
X        }
X        else{
X            e_error("Only one history item exists.");
X        }
X    }
X    ok_sprintf(arg, "%s", hist[hist_count - n - 1]);
X    reconstruct(hist_count - n - 1);
X    return;
X}
END_OF_FILE
if test 516 -ne `wc -c <'nth_hist.c'`; then
    echo shar: \"'nth_hist.c'\" unpacked with wrong size!
fi
# end of 'nth_hist.c'
fi
if test -f 'reconstruct.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'reconstruct.c'\"
else
echo shar: Extracting \"'reconstruct.c'\" \(2004 characters\)
sed "s/^X//" >'reconstruct.c' <<'END_OF_FILE'
X#include "e.h"
X
X
X/* 
X * reconstruct()
X *
X * Finish off the building of the new history file. Emit the directory name
X * then the history, except for hist[except] which is the new most recently 
X * used entry and so we do it last.
X *
X * After this, emit the saved line if there was one and then the rest of
X * the original history.
X *
X * Then close the two files and rename the old history to be the new one.
X * Make sure they new .e file has the same perms as the old.
X *
X */
void
reconstruct(except)
int except;
X{
X
X    register int i;
X    register int c;
X
X    /* The name of the directory goes first. */
X    ok_fprintf(tmp_fp, "%s\n", cwd);
X
X    /* Put in the lines we still want. i.e. those excluding 'except'. */
X    for (i = 0; i < hist_count; i++){
X        if (i != except){
X            ok_fprintf(tmp_fp, "\t%s\n", hist[i]);
X        }
X    }
X
X    /* Put in the new entry. */
X    ok_fprintf(tmp_fp, "\t%s\n", arg);
X
X    /* The saved line, if there was one. */
X    if (saved_line){
X        ok_fprintf(tmp_fp, "%s\n", saved_line);
X    }
X
X    /* The rest of the old history file. */
X    while ((c = getc(hist_fp)) != EOF){
X        if (putc(c, tmp_fp) == EOF){
X            perror("putc");
X            exit(EX_IOERR);
X        }
X    }
X
X    /* Clean up etc. */
X    if (fclose(hist_fp) == EOF){
X        e_error("Could not close '%s'.", ehist);
X    }
X    if (fclose(tmp_fp) == EOF){
X        e_error("Could not close '%s'.", tmp_file);
X    }
X#ifdef Sysv
X    if (unlink(ehist) == -1){
X        e_error("Could not unlink '%s'\nNew history in '%s'.", ehist, tmp_file);
X    }
X
X    if (link(tmp_file, ehist) == -1){
X        e_error("Could not link '%s' to '%s'.\n", tmp_file, ehist);
X    }
X
X    if (unlink(tmp_file) == -1){
X        e_error("Could not unlink '%s'.\n", tmp_file);
X    }
X#else
X    if (rename(tmp_file, ehist) == -1){
X        e_error("Could not rename '%s' to '%s'.", tmp_file, ehist);
X    }
X#endif
X    if (chmod(ehist, emode) == -1){
X        e_error("Could not chmod '%s'", ehist);
X    }
X    return;
X}
END_OF_FILE
if test 2004 -ne `wc -c <'reconstruct.c'`; then
    echo shar: \"'reconstruct.c'\" unpacked with wrong size!
fi
# end of 'reconstruct.c'
fi
if test -f 'signal.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'signal.c'\"
else
echo shar: Extracting \"'signal.c'\" \(495 characters\)
sed "s/^X//" >'signal.c' <<'END_OF_FILE'
X#include "e.h"
X
X/*
X * clean_up()
X *
X * This is where we come when we get a SIGINT.
X *
X */
int
clean_up()
X{
X    /*
X     * Just get out after making sure things are tidy.
X     *
X     */
X    e_error("\nInterrupt.");
X}
X
X
X/*
X * catch_signals()
X *
X * Arrange for SIGINT to be dealt with by clean_up().
X *
X */
void
catch_signals()
X{
X    if (signal(SIGINT, SIG_IGN) != SIG_IGN){
X        if (signal(SIGINT, clean_up) == (int (*)())-1){
X            e_error("Signal fails!");
X        }
X    }
X    return;
X}
END_OF_FILE
if test 495 -ne `wc -c <'signal.c'`; then
    echo shar: \"'signal.c'\" unpacked with wrong size!
fi
# end of 'signal.c'
fi
if test -f 'sp_dist.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sp_dist.c'\"
else
echo shar: Extracting \"'sp_dist.c'\" \(1011 characters\)
sed "s/^X//" >'sp_dist.c' <<'END_OF_FILE'
X/*
X * Stolen from "The UNIX Programming Environment" by Kernighan and Pike.
X *
X * Work out the distance between the strings 's' and 't' according
X * to the rough metric that
X *
X *     Identical = 0
X *     Interchanged characters = 1
X *     Wrong character/extra character/missing character = 2
X *     Forget it = 3
X *
X */
int
sp_dist(s, t)
char *s;
char *t;
X{
X
X    while (*s++ == *t){
X        if (*t++ == '\0'){
X            /* identical */
X            return 0;
X        }
X    }
X
X    if (*--s){
X        if (*t){
X            if (s[1]&&t[1]&&*s == t[1]&&*t == s[1]&&!strcmp(s+2, t+2)){
X                /* Interchanged chars. */
X                return 1;
X            }
X            if (!strcmp(s+1, t+1)){
X                /* Wrong char. */
X                return 2;
X            }
X        }
X        if (!strcmp(s+1, t)){
X            /* Extra char in 't'. */
X            return 2;
X        }
X    }
X    if (!strcmp(s, t+1)){
X        /* Extra char in 's'. */
X        return 2;
X    }
X
X    /* Forget it. */
X    return 3;
X}
END_OF_FILE
if test 1011 -ne `wc -c <'sp_dist.c'`; then
    echo shar: \"'sp_dist.c'\" unpacked with wrong size!
fi
# end of 'sp_dist.c'
fi
if test -f 'tags' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tags'\"
else
echo shar: Extracting \"'tags'\" \(1646 characters\)
sed "s/^X//" >'tags' <<'END_OF_FILE'
Mmain	main.c	/^main(argc, argv)$/
abandon	abandon.c	/^abandon()$/
ask_hist	ask_hist.c	/^ask_hist()$/
catch_signals	signal.c	/^catch_signals()$/
char_in	io.c	/^char_in(prompt)$/
check_hist	check_hist.c	/^check_hist()$/
clean_up	signal.c	/^clean_up()$/
dir_check	dir_check.c	/^int $/
dir_find	dir_find.c	/^dir_find()$/
do_vi	do_vi.c	/^do_vi(thing)$/
e	e.c	/^e(c, v)$/
e_error	e_error.c	/^e_error(u, v, w, x, y, z)$/
find_hist	find_hist.c	/^find_hist()$/
find_match	find_match.c	/^find_match(pattern)$/
get_temp	get_temp.c	/^get_temp()$/
inheritance	inheritance.c	/^inheritance()$/
insert_cmd	insert_cmd.c	/^insert_cmd(command)$/
is_delim	dir_find.h	/^#define is_delim(c) ((*c)==' '||(*c)==':'||(*c)=='/
match	find_match.c	/^match(argument, pattern)$/
multiple	multiple.c	/^multiple(number, args, size)$/
new_vi	new_vi.c	/^new_vi()$/
normal	normal.c	/^normal(string)$/
nth_hist	nth_hist.c	/^nth_hist(n)$/
ok_fprintf	io.c	/^ok_fprintf(stream, format, u, v, w, x, y, z)$/
ok_sprintf	io.c	/^ok_sprintf(dest, format, u, v, w, x, y, z)$/
read_hist	read_hist.c	/^read_hist()$/
reconstruct	reconstruct.c	/^reconstruct(except)$/
safety_first	do_vi.c	/^safety_first(s)$/
skip_delim	dir_find.h	/^#define skip_delim(c) while (is_delim((c))) (c)++;/
skip_to_next_delim	dir_find.h	/^#define skip_to_next_delim(c) while (*(c) && !is_d/
skip_to_white	e.h	/^#define skip_to_white(c) while (*(c) && *(c) != ' /
skip_white	e.h	/^#define skip_white(c) while (*(c) == ' ' || *(c) =/
sp_dist	sp_dist.c	/^sp_dist(s, t)$/
spell_help	spell_help.c	/^spell_help(flag)$/
terminal	terminal.c	/^terminal(what)$/
zap_nl	e.h	/^#define zap_nl(c) while (*(c) && *(c) != '\\n') (c)/
END_OF_FILE
if test 1646 -ne `wc -c <'tags'`; then
    echo shar: \"'tags'\" unpacked with wrong size!
fi
chmod +x 'tags'
# end of 'tags'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 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

-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.