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

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

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

#! /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 2 (of 3)."
# Contents:  MODS ask_hist.c dir_find.c e.h main.c multiple.c
#   spell_help.c terminal.c
# Wrapped by tcjones@watdragon on Thu Feb  9 10:01:02 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MODS' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MODS'\"
else
echo shar: Extracting \"'MODS'\" \(2757 characters\)
sed "s/^X//" >'MODS' <<'END_OF_FILE'
e Modification History.
X=======================
X
X
Version 1.1 changes          October 1987.
X==========================================
X 
X- Added "VIPATH" environment variable.
X- Fixed bug with argument lists that exceeded ARG_CHARS chars in multiple().
X- Added #ifdef statements to enable compilation on a SUN.
X- Put #defines etc into e.h as they were getting in the way.
X 
X
X
Version 1.2 changes          December 1987.
X===========================================
X 
X- Made the numbering on "e -" the same as for "e .".
X- System V port (thanks to Simon Brown).
X- Added man page (thanks to Phil Oldiges).
X- Fixed handling of the VIPATH variable so that it doesn't screw up
X    when there is more than one delimiter. Added new delimiters.
X- Cleaned up terminal handling to use ioctl().
X- Cleaned up error handling.
X- Fixed (for sure this time) the bug with long argument lists.
X- Made returns consistent in check().
X- Flagged suspected unsatisfied symbolic link in check().
X- Added #define called E_PATH which contains the name of the environment
X    variable containing the PATH for cross directory stuff. (set to "VIPATH").
X- Added E_MODE #define for the protection mode for .e (set to 0644).
X- Fixed spelling correction to offer all likely targets in a directory, not
X    just the first encountered. Added 'N' option to say "I meant what I said,
X    don't give me more possible corrections."
X- Comments!
X 
X
Version 1.3 changes         December 1988.
X==========================================
X
X- Fixed error message when unable to open E_PATH component directory.
X- Added N option to cross-directory suggestions (==> no more suggestions)
X    should have done this in 1.2.
X- Made centralised .e file in the home directory.
X- Split source into twenty odd files.
X- Rewrote e.h to make it more manageable.
X- Rewrote Makefile.
X- Added E_HIST (set to "VIHIST") getenv to let the user decide where the
X    history should live & what to call it. Defaults to $HOME/.e
X- Added E_INHERIT and E_SAFE_INHERIT (set to "VIINHERIT" and "VISAFEINHERIT")
X    to allow/disable inheritance of .exrc files in other directories. See the
X    man page for details.
X
To be added?
X============
X
X- Allow backspacing on a select line.
X- Spelling corrections across directories.
X- Plenty of fancy things.
X
X
X
X-------------------------------------------------------------------------------
Terry Jones, Department Of Computer Science, University Of Waterloo
X             Waterloo Ontario Canada N2L 3G1
X
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 2757 -ne `wc -c <'MODS'`; then
    echo shar: \"'MODS'\" unpacked with wrong size!
fi
chmod +x 'MODS'
# end of 'MODS'
fi
if test -f 'ask_hist.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ask_hist.c'\"
else
echo shar: Extracting \"'ask_hist.c'\" \(2657 characters\)
sed "s/^X//" >'ask_hist.c' <<'END_OF_FILE'
X#include "e.h"
X
X
X/*
X * Question the user about which file from the history is wanted.
X *
X */
void
ask_hist()
X{
X    register int i;
X    register int option;
X
X    /* Print the history. */
X    for (i = 0; i < hist_count; i++){
X        ok_fprintf(stderr, "\t[%d]: %s\n", hist_count-i-1, hist[i]);
X    }
X
X    option = char_in("select -> ");
X
X    /* 
X     * Process the option and put the appropriate file name into the 
X     * arg variable.
X     *
X     */
X
X    if (option == '\n'){
X        /* 
X         * They want the last file of the list. 
X         * There's no need to reconstruct, the history is already correct.
X         *
X         */
X        ok_fprintf(stderr, "%s\n", hist[hist_count - 1]);
X        ok_sprintf(arg, "%s", hist[hist_count - 1]);
X        abandon();
X        return;
X    }
X    else if (option == (int)erase){
X        /* 
X         * They want to leave. 
X         *
X         */
X        ok_fprintf(stderr, "\n");
X        abandon();
X        exit(1);
X    }
X    else if (option >= '0' && option <= '0' + hist_count - 1){
X        /* 
X         * They have requested a file by its history number. 
X         *
X         */
X        register int want = hist_count - (option - '0') - 1;
X        ok_fprintf(stderr, "%s\n", hist[want]);
X        ok_sprintf(arg, "%s", hist[want]);
X        reconstruct(want);
X        return;
X    }
X    else{
X        /* 
X         * Looks like they want to name a specific file. Echo the 
X         * character back to the screen. Then get the rest of the filename.
X         *
X         */
X        ok_fprintf(stderr, "%c", option);
X        arg[0] = (char)option;
X        i = 1;
X        while ((arg[i] = (char)getc(stdin)) != '\n'){
X            i++;
X        }
X        arg[i] = '\0';
X
X        /* 
X         * Seeing as they typed in the name, try and help with spelling. 
X         * If you can't help with spelling, see if there is a file in a
X         * directory mentioned in the VIPATH list that might have been the
X         * file that was meant.
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         *
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         * Otherwise 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    }
X    return;
X}
END_OF_FILE
if test 2657 -ne `wc -c <'ask_hist.c'`; then
    echo shar: \"'ask_hist.c'\" unpacked with wrong size!
fi
# end of 'ask_hist.c'
fi
if test -f 'dir_find.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dir_find.c'\"
else
echo shar: Extracting \"'dir_find.c'\" \(3846 characters\)
sed "s/^X//" >'dir_find.c' <<'END_OF_FILE'
X#include "e.h"
X#include "dir_find.h"
X
X/*
X * dir_find()
X *
X * This takes the environment variable which is #defined as PATH and 
X * extracts the directory names from it. They may be separated by 
X * arbitrary numbers of delimiter characters (currently "\n", "\t", " " 
X * and ":"). Each directory is then checked to see if it contains the 
X * desired filename (with a call to check). Spelling corrections are 
X * not attempted.
X *
X * This could have been done more simply using strtok() but I didn't know
X * about that then... You'll have to bear with me.
X *
X * 'this_dir' will point at the start of the directory name that is to be
X * processed. 'cp' will be advanced to the next delimiter which will be zeroed
X * and then 'cp' will be again advanced until it reaches a non-delimiter. This
X * marks the start of the next name and at the bottom of the loop 'this_dir'
X * is set to be 'cp' and we begin again.
X *
X * skip_delim() and friends are macros that live in dir_find.h
X *
X */
void
dir_find()
X{
X    char *p;
X    char path[E_PATH_LEN];
X    char *this_dir;
X    char *cp;
X
X    /*
X     * Get the environment variable, check its length and cp it to a safe spot.
X     *
X     */
X    p = getenv(E_PATH);
X    if (!p) return;
X
X    if (strlen(p) >= E_PATH_LEN){
X        e_error("Length of '%s' variable exceeds %d.", E_PATH, MAXPATHLEN);
X    }
X
X    strcpy(path, p);
X
X    /*
X     * Begin at the beginning...
X     *
X     */
X    cp = path;
X    skip_delim(cp);
X
X    if (!*cp){
X        /* 
X         * There was nothing there but delimiters! 
X         *
X         */
X        return;
X    }
X
X    this_dir = cp;
X
X    while (*this_dir){
X
X        /* 
X         * Move "cp" along to the first delimiter. 
X         *
X         */
X        skip_to_next_delim(cp);
X
X        /*
X         * If it's not already '\0' then zero it and move on. Otherwise we
X         * have reached the end of the string.
X         *
X         */
X        if (*cp){
X            *cp = '\0';
X            cp++;
X        }
X
X        /* 
X         * Move "cp" along over delimiters unitl the next directory name. 
X         *
X         */
X        skip_delim(cp);
X
X        /* 
X         * Check the directory "this_dir" for the filename "arg". 
X         * If it's there, offer it to them.
X         *
X         */
X        if (dir_check(arg, this_dir)){
X
X            char prompt[MAXPATHLEN + 128];
X            ok_sprintf(prompt, "%s/%s [y]? ", this_dir, arg);
X
X            /* 
X             * Get and process the reply. 
X             *
X             */
X            switch (char_in(prompt)){
X
X                case 'N':{
X                    /*
X                     * They don't want it and they don't want more help.
X                     *
X                     */
X                    ok_fprintf(stderr, "No!\n");
X                    return;
X                }
X
X                case 'n':{
X                    /*
X                     * They don't want it but continue to search for another.
X                     *
X                     */
X                    ok_fprintf(stderr, "no\n");
X                    break;
X                }
X
X                case 'q':
X                case 'Q':{
X                    /*
X                     * Get out.
X                     *
X                     */
X                    ok_fprintf(stderr, "quit\n");
X                    abandon();
X                    exit(0);
X                }
X
X                default :{
X                    /*
X                     * They want it. Set up the filename in 'arg'.
X                     *
X                     */
X                    char tmp[MAXPATHLEN];
X
X                    ok_fprintf(stderr, "yes\n");
X                    ok_sprintf(tmp, "%s/%s", this_dir, arg);
X                    arg[0] = '\0';
X                    strcat(arg, tmp);
X                    return;
X                }
X            }
X        }
X        this_dir = cp;
X    }
X
X    return;
X}
END_OF_FILE
if test 3846 -ne `wc -c <'dir_find.c'`; then
    echo shar: \"'dir_find.c'\" unpacked with wrong size!
fi
# end of 'dir_find.c'
fi
if test -f 'e.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'e.h'\"
else
echo shar: Extracting \"'e.h'\" \(4788 characters\)
sed "s/^X//" >'e.h' <<'END_OF_FILE'
X/*
X * e.h 
X * version 1.3
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
X * tcjones@dragon.waterloo.{cdn,edu} tcjones@WATER.bitnet
X * tcjones%watdragon@waterloo.csnet 
X *
X */
X
X
X#ifdef Bsd
X#   include <stdio.h>
X#   include <sys/types.h>
X#   include <sys/stat.h>
X#   include <signal.h>
X#   include <sys/param.h>
X#   include <pwd.h>
X#   include <ctype.h>
X#   include <sysexits.h>
X#   include <sys/file.h>
X#   include <sys/dir.h>
X#   include <strings.h>
X#   include <sys/ioctl.h>
X#   define VI "/usr/ucb/vi"
X    uid_t getuid();
X    uid_t getgid();
X#endif /* Bsd */
X
X
X#ifdef Sun
X#   include <stdio.h>
X#   include <sys/types.h>
X#   include <sys/stat.h>
X#   include <signal.h>
X#   include <sys/param.h>
X#   include <pwd.h>
X#   include <ctype.h>
X#   include <sysexits.h>
X#   include <sys/file.h>
X#   include <sys/dir.h>
X#   include <strings.h>
X#   include <sys/time.h>
X#   include <sys/vnode.h>
X#   include <ufs/inode.h>
X#   include <sgtty.h>
X#   define VI "/usr/ucb/vi"
X    extern char *sprintf();
X#endif /* Sun */
X
X
X#ifdef Sysv
X#   include <stdio.h>
X#   include <sys/types.h>
X#   include <sys/stat.h>
X#   include <signal.h>
X#   include <sys/param.h>
X#   include <pwd.h>
X#   include <ctype.h>
X#   include <sys/file.h>
X#   include <termio.h>
X#   include <string.h>
X#   include <fcntl.h>
X#   include <dirent.h>
X#   include <sys/dir.h>
X#   define index strchr
X#   define rindex strrchr
X#   define direct dirent
X#   define MAXPATHLEN MAXNAMLEN
X#   define ok_sprintf sprintf
X#   define VI "/usr/bin/vi"
X    extern struct passwd *getpwuid();
X#endif /* Sysv */
X
X
X#ifdef Ultrix
X#   include <stdio.h>
X#   include <sys/types.h>
X#   include <sys/stat.h>
X#   include <signal.h>
X#   include <sys/param.h>
X#   include <pwd.h>
X#   include <ctype.h>
X#   include <sysexits.h>
X#   include <sys/file.h>
X#   include <sys/dir.h>
X#   include <strings.h>
X#   include <sys/ioctl.h>
X#   define VI "/usr/ucb/vi"
X#endif /* Ultrix */
X
X
X#ifdef Dynix
X#   include <stdio.h>
X#   include <sys/types.h>
X#   include <sys/stat.h>
X#   include <signal.h>
X#   include <sys/param.h>
X#   include <pwd.h>
X#   include <ctype.h>
X#   include <sys/dir.h>
X#   include <sys/ioctl.h>
X#   include <strings.h>
X#   define VI "/usr/ucb/vi"
X#endif /* Dynix */
X
X#ifdef waterloo
X#   include <stdlib.h>
X#endif
X
X/*
X * Other checks...
X *
X */
X
X#ifndef IREAD
X#   define IREAD    0400
X#endif
X
X#ifndef EX_IOERR
X#   define EX_IOERR 1
X#endif
X
X
X/*
X * Things that aren't portability concerns.
X *
X */
X
X#define DEFAULT_HIST    ".e"
X#define HIST_LINES      9
X#define HIST_CHARS      1024
X#define E_PATH          "VIPATH"
X#define E_HIST          "VIHIST"
X#define E_INHERIT       "VIINHERIT"
X#define E_SAFE_INHERIT  "VISAFEINHERIT"
X#define E_PATH_LEN      2048
X#define ARG_CHARS       4096
X#define MAX_ARGS        100
X#define O_READ          00004
X#define G_READ          0004
X#define TERM_RECORD     0
X#define TERM_SET        1
X#define TERM_RESET      2
X#define VERSION         "1.3"
X
X/*
X * STRUCT_ASST should be defined if your cc can handle structural assignments. 
X *
X * This is only used in the function terminal(). Leave STRUCT_ASST
X * defined and if it doesn't break you're ok. If it does, undefine it and
X * you'll definitely be ok (but things will run slower - even though you
X * wont notice it.) Words words words. Ho hum.
X *
X */
X
X#define STRUCT_ASST
X
X
int char_in();
int check();
int clean_up();
int dir_check();
int match();
int read_hist();
int safety_first();
int sp_dist();
int spell_help();
void abandon();
void ask_hist();
void catch_signals();
void check_hist();
void dir_find();
void do_vi();
void e();
void e_error();
void find();
void find_hist();
void find_match();
void get_temp();
void inheritance();
void insert_cmd();
void multiple();
void new_vi();
void normal();
void nth_hist();
void ok_fprintf();
void ok_sprintf();
void reconstruct();
void terminal();
X
X
extern char *getenv();
extern char *mktemp();
extern char *sbrk();
X#ifndef Sysv
X    extern char *getwd();
X    void ok_sprintf();
X#endif
X
extern FILE *hist_fp;
extern FILE *tmp_fp;
extern char *hist[];
extern char *home;
extern char *myname;
extern char *saved_line;
extern char arg[];
extern char cwd[];
extern char ehist[];
extern char erase;
extern char tmp_file[];
extern int emode;
extern int hist_count;
extern int inherit;
extern int safe_inherit;
extern int uid;
X
X
X/* 
X * Walk over white space. 
X *
X */
X#define skip_white(c) while (*(c) == ' ' || *(c) == '\t') (c)++;
X
X/* 
X * Walk over non-white characters. 
X *
X */
X#define skip_to_white(c) while (*(c) && *(c) != ' ' && *(c) != '\t') (c)++;
X
X/* 
X * Run down a string and zap the newline if we find one. 
X *
X */
X#define zap_nl(c) while (*(c) && *(c) != '\n') (c)++; *(c) = '\0';
END_OF_FILE
if test 4788 -ne `wc -c <'e.h'`; then
    echo shar: \"'e.h'\" unpacked with wrong size!
fi
chmod +x 'e.h'
# end of 'e.h'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(2804 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X
X/*******************************************************************************
X#  E - command line preprocessor for vi.  Version 1.3 - November 1988.         #
X#  ===================================================================         #
X#                                                                              #
X#  Terry Jones, Department of Computer Science, University of Waterloo         #
X#  Waterloo, Ontario, Canada. N2L 3G1                                          #
X#                                                                              #
X#  {ihnp4,allegra,decvax,utzoo,utcsri,clyde}!watmath!watdragon!tcjones         #
X#  tcjones@dragon.waterloo.{cdn,edu} tcjones@WATER.bitnet                      #
X#  tcjones%watdragon@waterloo.csnet                                            #
X*******************************************************************************/
X
X
X#include "e.h"
X
XFILE *hist_fp = NULL;        /* The original .e file                        */
XFILE *tmp_fp = NULL;         /* The new .e file                             */
char *hist[HIST_LINES];      /* Pointers to history items.                  */
char *home;                  /* Home directory.                             */
char *myname;                /* argv[0]                                     */
char *saved_line = NULL;     /* In case we read one line too many later on. */
char arg[ARG_CHARS];         /* The arguments that vi will be invoked with. */
char cwd[MAXPATHLEN];        /* The directory from which we're invoked.     */
char ehist[MAXPATHLEN];      /* The name of the original .e file.           */
char erase;                  /* The terminal's erase character.             */
char tmp_file[MAXPATHLEN];   /* The name of the new .e file.                */
int emode;                   /* The protection mode of the original .e.     */
int hist_count;              /* The # of items in the history for this dir. */
int safe_inherit = 0;        /* Never inherit other people's .exrc's        */
int inherit = 0;             /* Inherit .exrc files?                        */
int uid;                     /* The user's uid.                             */
X
X
main(argc, argv)
int argc;
char **argv;
X{
X    /*
X     * Do some preliminary things. Grab the name we were invoked with,
X     * record the status of the terminal so we can restore it later if
X     * we have to alter it for some reason, arrange to catch SIGINT and
X     * read and split up the history for this directory.
X     *
X     * Then call e which handles the arguments and calls other things
X     * to get the job done. e should never return.
X     */
X
X    myname = argv[0];
X    terminal(TERM_RECORD);
X    catch_signals();
X    inheritance();
X    find_hist();
X    hist_count = read_hist();
X    e(argc, argv);
X    return 1;
X}
END_OF_FILE
if test 2804 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
chmod +x 'main.c'
# end of 'main.c'
fi
if test -f 'multiple.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'multiple.c'\"
else
echo shar: Extracting \"'multiple.c'\" \(2638 characters\)
sed "s/^X//" >'multiple.c' <<'END_OF_FILE'
X#include "e.h"
X
X/*
X * There were several names on the command line, so we just strcat them
X * into the 'arg' array. Check to see that the length of all the args
X * will not be greater than "size" or else we will overflow arg.
X *
X * This is actually insane - we put the args into a char array to pass to
X * do_vi, and then it promptly sticks them back into a char ** arrangement.
X * Ugh.
X *
X * The total argument length must be at most size - 1 characters, including
X * spaces. arg needs to have a trailing '\0' so that do_vi() wont break.
X *
X */
X
void
multiple(number, args, size)
int number;
char **args;
int size;
X{
X    register i;
X    register total = 0;
X    char temp_arg[ARG_CHARS];
X
X    temp_arg[0] = '\0';
X    while (--number){
X        if ((total += strlen(*(args + 1))) >= size){
X
X            /*
X             * If you are running e and you find that this condition occurs,
X             * the solution is to simply increase the value of the #define
X             * line for ARG_CHARS in e.h. It shouldn't happen under normal
X             * circumstances.
X             *
X             */
X
X            ok_fprintf(stderr,
X                "\007Argument list too long, truncated after '%s'.\n", *args);
X            sleep(2);   /* Give them some chance to see what happened. */
X            break;
X        }
X
X        arg[0] = '\0';
X        strcat(arg, *++args);
X        (void) spell_help(1);
X        strcat(temp_arg, arg);
X        strcat(temp_arg, " ");
X
X        if (number > 1){
X            strcat(arg, " ");
X
X            /* 
X             * Add one to total for the space. There's no need to check for
X             * overflow here as we know there is another argument since
X             * number > 1 still. Thus if this overflows arg, then it is going
X             * to be caught anyway in the test at the top of the while loop.
X             *
X             */
X
X            total++;                
X        }
X    }
X
X    strcpy(arg, temp_arg);
X
X    /*
X     * Now, if there is a history file and we can find an identical line
X     * then reconstruct with that line at the bottom.
X     *
X     */
X
X    if (hist_count != -1){
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        /* There was no history file so try to give them one for next time. */
X        new_vi();
X    }
X    return;
X}
END_OF_FILE
if test 2638 -ne `wc -c <'multiple.c'`; then
    echo shar: \"'multiple.c'\" unpacked with wrong size!
fi
# end of 'multiple.c'
fi
if test -f 'spell_help.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'spell_help.c'\"
else
echo shar: Extracting \"'spell_help.c'\" \(3614 characters\)
sed "s/^X//" >'spell_help.c' <<'END_OF_FILE'
X#include "e.h"
X
X/*
X * spell_help()
X *
X * Read the directory and if the file they want (in 'arg') does not
X * exist then see if there is one that does which has similar spelling
X * to what they requested. Offer the change and handle the reply.
X *
X * The argument tells us how we should form the prompt if we get a match.
X * 1 = this file was one of several arguments to e and so we should say
X * "correct 'frde' to 'fred'?". If there were only one argument it would
X * be redundant to say that, they know their argument was 'frde', so we
X * just say "correct to 'frde'?". Little things make all the difference.
X *
X * Return 1 if we were able to help, 0 otherwise.
X *
X */
int
spell_help(flag)
int flag;
X{
X    DIR *dp; 
X    DIR *opendir();
X    struct direct *readdir();
X    struct direct *entry;
X    register int len = strlen(arg);
X    struct stat buf;
X    int ch;
X
X    /* 
X     * If the file already exists just return - they don't need help. 
X     *
X     */
X    if (stat(arg, &buf) == 0){
X        return 1;
X    }
X
X    /* 
X     * If the current directory can't be read then return. 
X     *
X     */
X    if ((dp = opendir(".")) == NULL){
X        return 0;
X    }
X
X    for (entry = readdir(dp); entry != NULL; entry = readdir(dp)){
X
X#ifdef Sysv
X        register int dlen = strlen(entry->d_name);
X#else
X        register int dlen = entry->d_namlen;
X#endif
X
X        if (stat(entry->d_name, &buf) == -1){
X            continue;
X        }
X
X        /* 
X         * If it's not a regular file then continue. 
X         *
X         */
X        if ((buf.st_mode&S_IFMT) != S_IFREG){
X            continue;
X        }
X
X        /* 
X         * If this entry has a non-zero inode number and
X         *
X         *      name length == sought length +/- 1 
X         *
X         * then it should be checked.
X         *
X         */
X
X        if (entry->d_ino && dlen >= len - 1 && dlen <= len + 1){
X
X            char prompt[MAXPATHLEN + 128];
X
X            /* 
X             * If the distance between this name and the one the user enetered
X             * is too great then just continue.
X             *
X             */
X
X            if (sp_dist(entry->d_name, arg) == 3) continue;
X
X
X            /* 
X             * Otherwise offer them this one and get the response.
X             *
X             */
X            if (flag){
X                ok_sprintf(prompt, "correct '%s' to '%s' [y]? ", arg, 
X                    entry->d_name);
X            }
X            else{
X                ok_sprintf(prompt, "correct to '%s' [y]? ", entry->d_name);
X            }
X            ch = char_in(prompt);
X
X            if (ch == 'N'){
X                /* 
X                 * No, and they mean it. Offer no more help. 
X                 *
X                 */
X                ok_fprintf(stderr, "No!\n");
X                break;
X            }
X
X            else if (ch == 'n'){
X                /* 
X                 * No, but they'd like more help. 
X                 *
X                 */
X                ok_fprintf(stderr, "no\n");
X                continue;
X            }
X
X            else if (ch == 'q' || ch == 'Q' || ch == (int)erase){
X                /* 
X                 * Quit. 
X                 *
X                 */
X                ok_fprintf(stderr, "quit\n");
X                closedir(dp);
X                abandon();
X                exit(0);
X            }
X
X            else{
X                /* 
X                 * Yes. 
X                 *
X                 */
X                ok_fprintf(stderr, "yes\n");
X                closedir(dp);
X                strcpy(arg, entry->d_name);
X                return 1;
X            }
X        }
X    }
X    closedir(dp);
X    return 0;
X}
END_OF_FILE
if test 3614 -ne `wc -c <'spell_help.c'`; then
    echo shar: \"'spell_help.c'\" unpacked with wrong size!
fi
# end of 'spell_help.c'
fi
if test -f 'terminal.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'terminal.c'\"
else
echo shar: Extracting \"'terminal.c'\" \(3469 characters\)
sed "s/^X//" >'terminal.c' <<'END_OF_FILE'
X#include "e.h"
X
X/*
X * terminal()
X *
X * Handles the terminal. Must be first called as terminal(TERM_RECORD)
X * which remembers the initial terminal charcteristics and sets up the
X * "erase" variable. Thereafter can be called either as
X *
X * terminal(TERM_SET)  --  to turn on CBREAK and ECHO off.
X * terminal(TERM_RESET)  --  to set the terminal to its original state.
X *
X * This code is definitely a mess. If you don't have Sysv defined it does 
X * things which are known to work for BSD, SUN, ULTRIX and DYNIX.
X *
X */
void
terminal(what)
int what;
X{
X#ifdef Sysv
X    static struct termio initial_blk;
X    static struct termio set_blk;
X#else
X    static struct sgttyb initial_blk;
X    static struct sgttyb set_blk;
X#endif /* Sysv */
X
X
X
X    switch(what){
X
X        case TERM_RECORD:{
X#ifdef Sysv
X            if (ioctl(0, TCGETA, (char *)&initial_blk) == -1){
X                e_error("Could not ioctl stdin.");
X            }
X
X#ifdef STRUCT_ASST
X            /* Copy the structure in one hit. */
X            set_blk = initial_blk;
X#else
X            /* Copy the structure field by field. */
X            set_blk.c_iflag = initial_blk.c_iflag;
X            set_blk.c_oflag = initial_blk.c_oflag;
X            set_blk.c_cflag = initial_blk.c_cflag;
X            set_blk.c_line = initial_blk.c_line;
X
X            for (i = 0; i < NCC; i++){
X                set_blk.c_cc[i] = initial_blk.c_cc[i];
X            }
X#endif /* STRUCT_ASST */
X
X            /* And now set up the set_blk. */
X            set_blk.c_lflag = (initial_blk.c_lflag &= ~(ICANON|ECHO|ECHONL));
X            set_blk.c_lflag &= ICANON;
X            erase = set_blk.c_cc[VERASE];
X            set_blk.c_cc[VMIN] = 1;
X            set_blk.c_cc[VTIME] = 0;
X#else
X            if (ioctl(0, TIOCGETP, (char *)&initial_blk) == -1){
X                e_error("Could not ioctl stdin.");
X            }
X
X#ifdef STRUCT_ASST
X            /* Copy the structure in one hit. */
X            set_blk = initial_blk;
X#else
X            /* Copy the structure field by field. */
X            set_blk.sg_ispeed = initial_blk.sg_ispeed;
X            set_blk.sg_ospeed = initial_blk.sg_ospeed;
X            set_blk.sg_erase = initial_blk.sg_erase;
X            set_blk.sg_kill = initial_blk.sg_kill;
X            set_blk.sg_flags = initial_blk.sg_flags;
X#endif /* STRUCT_ASST */
X
X            /* And now set up the set_blk. */
X            erase = set_blk.sg_erase;
X
X            /* Go into CBREAK mode or stay that way if we are already. */
X            set_blk.sg_flags |= CBREAK;
X
X            /* Turn off echo. */
X            set_blk.sg_flags &= ~ECHO;
X#endif /* Sysv */
X            break;
X        }
X
X        case TERM_SET:{
X#ifdef Sysv
X            if (ioctl(0, TCSETA, (char *)&set_blk) == -1){
X                e_error("Could not ioctl stdin.");
X            }
X#else
X            if (ioctl(0, TIOCSETP, (char *)&set_blk) == -1){
X                e_error("Could not ioctl stdin.");
X            };
X#endif /* Sysv */
X            break;
X        }
X
X        case TERM_RESET:{
X#ifdef Sysv
X            if (ioctl(0, TCSETA, (char *)&initial_blk) == -1){
X                e_error("Could not ioctl stdin.");
X            }
X#else
X            if (ioctl(0, TIOCSETP, (char *)&initial_blk) == -1){
X                e_error("Could not ioctl stdin.");
X            }
X#endif /* Sysv */
X            break;
X        }
X
X        default:{
X            /* Look! - no ifdefs here. */
X            e_error("terminal() called with unknown parameter (%d).", what);
X        }
X    }
X    return;
X}
X
END_OF_FILE
if test 3469 -ne `wc -c <'terminal.c'`; then
    echo shar: \"'terminal.c'\" unpacked with wrong size!
fi
# end of 'terminal.c'
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
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.