VSH source 2 of 6
Dan Ts'o
dan at rna.UUCP
Thu Jun 27 16:26:12 AEST 1985
# Here is part 2 of the sources to VSH, a visual shell.
#
#
# Cheers,
# Dan Ts'o
# Dept. Neurobiology
# Rockefeller Univ.
# 1230 York Ave.
# NY, NY 10021
# 212-570-7671
# ...cmcl2!rna!dan
echo src/account.c
sed 's/^X//' > src/account.c << 'All work and no play makes Jack a dull boy'
X#include "hd.h"
X
X/* This records each usage of Vsh in the file LOGFILE */
X/* Each entry is in the form "User Time(minutes) Date" */
X
Xlong time (), ent_time [1];
Xchar *ctime ();
X
Xcomein ()
X{
X time (ent_time);
X}
X
Xgoout ()
X{
X
X long lv_time [1];
X register char *namep;
X register char *cp;
X FILE *logfile;
X
X if (access(LOGFILE, 2))
X return;
X time (lv_time);
X/*
X for (namep = cp = HOME; *cp; cp++)
X if (*cp == '/') namep = cp;
X namep++;
X */ namep = username;
X logfile = fopen (LOGFILE, "a");
X if (logfile == NULL)
X return;
X fprintf (logfile, "%8.8s %4d %10.10s\n",
X namep, (int)((*lv_time - *ent_time)/60L), ctime (ent_time));
X fclose (logfile);
X}
X
Xleave ()
X{ /* exit after resetting tty */
X int putch();
X
X tty_cooked ();
X ewin();
X window = LI;
X vwin(); /* reset tty scrolling */
X atxy(1, LI);
X if (TE)
X tputs(TE, 0, putch);
X goout ();
X exit (0);
X}
All work and no play makes Jack a dull boy
echo src/ascii.c
sed 's/^X//' > src/ascii.c << 'All work and no play makes Jack a dull boy'
X#include "strings.h" /* See strings.h for comments */
X
Xchar charclass [129] =
X{
X/* -1 */
X EF,
X/* 00-07 */
X EF, UD, UD, EF, EF, UD, UD, UD,
X/* 08-0f */
X UD, WS, EL, UD, UD, EL, UD, UD,
X/* 10-17 */
X UD, UD, UD, UD, UD, UD, UD, UD,
X/* 18-1f */
X UD, UD, UD, UD, WS, UD, UD, UD,
X/* 20-27 */
X WS, SC, SC, SC, SC, SC, SC, SC,
X/* 28-2f */
X SC, SC, SC, SC, SC, SC, SC, SC,
X/* 30-37 */
X NU, NU, NU, NU, NU, NU, NU, NU,
X/* 38-3f */
X NU, NU, SC, SC, SC, SC, SC, SC,
X/* 40-47 */
X SC, UA, UA, UA, UA, UA, UA, UA,
X/* 48-4f */
X UA, UA, UA, UA, UA, UA, UA, UA,
X/* 50-57 */
X UA, UA, UA, UA, UA, UA, UA, UA,
X/* 58-5f */
X UA, UA, UA, SC, SC, SC, SC, SC,
X/* 60-67 */
X SC, LA, LA, LA, LA, LA, LA, LA,
X/* 68-6f */
X LA, LA, LA, LA, LA, LA, LA, LA,
X/* 70-77 */
X LA, LA, LA, LA, LA, LA, LA, LA,
X/* 78-7f */
X LA, LA, LA, SC, SC, SC, SC, EF
X} ;
All work and no play makes Jack a dull boy
echo src/asfix
sed 's/^X//' > src/asfix << 'All work and no play makes Jack a dull boy'
Xed - $1.s
X?.globl?a
X.data
X.
X-2,+2s/.data/.text/
Xw
Xq
Xas - -o $1.o $1.s
Xrm -f $1.s
All work and no play makes Jack a dull boy
echo src/at.c
sed 's/^X//' > src/at.c << 'All work and no play makes Jack a dull boy'
X#
X#include "hd.h"
X/* Display and cursor control routines */
X
X#define BELL 07
X
Xint putch ();
X
X/* Position cursor at the given (x, y) location.
X (1, 1) is the top left, (80, 24) is the lower right
X */
X
Xatxy (x, y) int x, y;
X{
X
X tputs (tgoto (CM, x - 1, y - 1), 0, putch);
X}
X
X/*
X * Erase screen or upper directory window
X */
Xerase ()
X{
X register int i;
X
X bufout();
X if (ewindow) {
X if (CB) {
X atxy(CO, window);
X tputs(CB, 0, putch);
X }
X else {
X atxy(1, 1);
X for (i = 1; i <= window; i++) {
X if (CE)
X tputs(CE, 0, putch);
X else
X clearline();
X printf("\r\n");
X }
X }
X atxy(1, 1);
X }
X else {
X tputs(CL, 0, putch);
X putch(CR);
X }
X unbufout();
X}
X
X/*
X * Erase below a line
X */
Xerasebelow(l)
Xregister int l;
X{
X if (CD) {
X atxy(1, l);
X tputs(CD, 0, putch);
X return;
X }
X do {
X atxy(1, l);
X clearline();
X } while (l++ < LI);
X}
X
X/* erase chars on current line */
Xclearline ()
X{
X bufout ();
X if (CE) {
X putch(CR);
X tputs(CE, 0, putch);
X }
X else
X printf ("%c%80s%s", CR, "", UP);
X unbufout ();
X}
X
X/* Position cursor at specified file */
Xatfile (file, col) int file, col;
X{
X
X atxy (col, 3 + file);
X}
X
X/* buffering subroutines */
X
Xchar outbuf [BUFSIZ]; /* the buffer */
Xint bcount = 0; /* can buffer only once */
X/* additional attempts ignored */
X
Xbufout ()
X{
X
X if (bcount++ == 0) setbuf (stdout, outbuf);
X}
X
Xunbufout ()
X{
X
X fflush (stdout);
X if (--bcount == 0) setbuf (stdout, CNULL);
X}
X
X/* Clear message lines (23-24) for a pcount line message */
X/* Lastcount keeps track of the lines with characters on them */
X/* Dispdir calls with parameter -1 to reset lastcount */
X
Xclearmsg (pcount) int pcount;
X{
X
X static int lastcount;
X
X atxy(1, window-1);
X if (pcount == -1) lastcount = 0;
X else
X {
X if (lastcount == 0);
X else if (lastcount == 1)
X {
X clearline ();
X }
X else
X {
X bufout ();
X if (CE) {
X putch(CR);
X tputs(CE, 0, putch);
X putch(LF);
X tputs(CE, 0, putch);
X }
X else
X printf ("%159s", "");
X unbufout ();
X }
X lastcount = pcount;
X }
X atxy(1, window-1);
X}
X
X/* Putmsg counts the number of lines in its parameter,
X calls clearmsg with that count, and then displays the message. */
X
Xputmsg (msg, a0, a1)
Xregister char * msg;
Xchar *a0, *a1;
X{
X
X clearmsg (any(LF, msg) == NULL ? 1 : 2);
X printf (" ");
X hilite (msg, a0, a1);
X /* Cosmetic */
X if (*msg) {
X while (*msg++);
X if (msg[-2] == ' ')
X printf("%s ", BC);
X }
X}
X
X/* Beep bell on terminal */
Xbeep ()
X{
X putch (BELL);
X}
X
X/* Print error message about a file */
Xmyperror (parm) char * parm;
X{
X
X extern int errno, sys_nerr;
X extern char *sys_errlist[];
X register char *c;
X
X c = "Unknown error";
X if(errno < sys_nerr)
X c = sys_errlist[errno];
X clearmsg (1);
X printf (" ");
X hilite ("%s: %s", parm, c);
X}
All work and no play makes Jack a dull boy
echo src/classify.c
sed 's/^X//' > src/classify.c << 'All work and no play makes Jack a dull boy'
X#include "hd.h"
X#include "classify.h"
X#include "mydir.h"
X#include "strings.h"
X
X#define aout1 0407
X#define aout2 0410
X#define aout3 0411
X#define aout4 0405
X#define aout5 0413
X#define cpio 070707
X#define ar 0177545
X#define packold 017437
X#define pack 017037
X#define compact 017777
X#define compress 0116437
X
X/* Classify return the file type of parameter fname */
X
Xclassify (fname) char * fname;
X{
X register unsigned mode;
X register int fdesc, rdlen;
X unsigned short word;
X int code;
X unsigned short wbuf[5];
X char *cp;
X char *lastfn();
X
X if (stat (fname, &scr_stb)) return CL_NULL;
X
X mode = scr_stb.st_mode & S_IFMT;
X if (mode == S_IFDIR) return CL_DIR;
X if (mode != S_IFREG) return CL_SPCL;
X
X fdesc = open (fname, 0);
X if (fdesc < 0) return CL_PROTPLN;
X
X rdlen = read (fdesc, wbuf, sizeof wbuf);
X if (rdlen < sizeof word)
X code = CL_TEXT;
X else {
X word = wbuf[0];
X cp = (char *)wbuf;
X cp[8] = 0;
X /* Berkeley archive */
X if (rdlen >= 8 && !strcmp(cp, "!<arch>\n"))
X word = ar;
X /* System 5.0 archive (where will it end ?) */
X else {
X cp[4] = 0;
X if (rdlen >= 4 && !strcmp(cp, "<ar>"))
X word = ar;
X }
X switch (word) {
X case aout1:
X case aout2:
X case aout3:
X case aout4:
X case aout5:
X code = CL_AOUT;
X break;
X case ar:
X code = CL_AR;
X break;
X case cpio:
X code = CL_CPIO;
X break;
X case pack:
X case packold:
X code = CL_PACK;
X break;
X case compact:
X code = CL_COMPACT;
X break;
X case compress:
X code = CL_COMPRESS;
X break;
X default:
X if (compe (lastfn (fname), "core"))
X code = CL_CORE;
X else {
X /* Attempt to protect user from binary files */
X if (istext(fdesc))
X code = CL_TEXT;
X else
X code = CL_UNKPLN;
X }
X }
X }
X
X close (fdesc);
X return code;
X}
X
X/*
X * istext(fd) - test if file contents is text-like
X */
Xistext(fd)
Xint fd;
X{
X register int i;
X register char *s;
X register int cc;
X char buf[500];
X
X i = read(fd, buf, 500);
X cc = 0;
X for (s = buf; i > 0; i--) {
X /* Test for NUL, parity bit, control codes */
X if (*s == 0 || (*s&0200) || (ascii[*s] == UD && *s != '\b'))
X cc++;
X s++;
X if (cc > 50)
X break;
X }
X return (i ? 0 : 1);
X}
X
X/* Lastfn returns a pointer to the last file name in path. */
X
Xchar *
X lastfn (path) register char *path;
X{
X register char *cp;
X
X for (cp=path; *cp++;);
X
X cp--;
X while (*--cp != '/' && cp >= path);
X
X return ++cp;
X}
All work and no play makes Jack a dull boy
echo src/classify.h
sed 's/^X//' > src/classify.h << 'All work and no play makes Jack a dull boy'
X/* Vsh will classify a file as one of the following: */
X
X#define CL_NULL 0 /* No such file or protected path */
X#define CL_DIR 1 /* Directory, May NOT be accessable */
X#define CL_SPCL 2 /* Special device file */
X#define CL_PROTPLN 3 /* Plain file protected unknown fmt */
X#define CL_UNKPLN 4 /* Plain file unknown format */
X#define CL_AOUT 5 /* A.out format */
X#define CL_AR 6 /* Ar format */
X#define CL_CPIO 7 /* Cpio format */
X#define CL_CORE 8 /* Core dump */
X#define CL_TEXT 9 /* Ascii text */
X#define CL_PACK 10 /* Pack/pcat Huffman encoded */
X#define CL_COMPACT 11 /* compact Huffman encoded */
X#define CL_COMPRESS 12 /* compress encoded */
All work and no play makes Jack a dull boy
echo src/cmdini.c
sed 's/^X//' > src/cmdini.c << 'All work and no play makes Jack a dull boy'
X#include "hd.h"
X#include "command.h"
X
Xextern date(), showerror(), showgrep(), file(), home(), grep(),
X wmake(), fmake(), callshell(), longlist(), remove(),
X create(), exec(), display(), options(), xecute(), xchdir(), rexecute(),
X chain(), find(), pagexec();
X
Xstruct classstruct classtab[] =
X{
X "date", date, 0, 1,
X "showerror", showerror, 0, 1,
X "showgrep", showgrep, 0, 1,
X "file", file, -1, 1,
X "home", home, 0, 1,
X "grep", grep, 0, 1,
X "wmake", wmake, 0, 1,
X "fmake", fmake, 0, 1,
X "exec", exec, -2, 1,
X "xecute", xecute, -2, 1,
X "rexecute", rexecute, 0, 1,
X "shell", callshell, -1, 1,
X "display", display, -1, 1,
X "create", create, 0, 1,
X "longlist", longlist, 0, 0,
X "remove", remove, 0, 0,
X "options", options, -1, 1,
X "null", 0, 0, 0,
X "chain", chain, -2, 1,
X "find", find, -1, 1,
X "pexec", pagexec, -2, 1,
X "", 0, 0, 0
X} ;
X
Xstatic char *whoargv[] =
X{
X "/bin/who", 0
X} ;
Xstatic char *rootargv[] =
X{
X "/", 0
X} ;
Xstatic char *helpargv[] =
X{
X "/usr/lib/vsh/genhelp", 0
X} ;
Xstatic char *psargv[] =
X{
X "/bin/ps", 0
X} ;
Xstatic char *bshargv[] =
X{
X#ifdef PWBTTY
X "/bin/v7sh", 0
X#else
X "/bin/sh", 0
X#endif
X} ;
X
X/* dyt */
Xextern char wdname0[];
Xstatic char *owdargv[] =
X{
X wdname0, 0
X};
X
Xchar *shargv[] =
X{
X#ifdef PWBTTY
X "/bin/sh", 0
X#else
X "/bin/csh", 0
X#endif
X};
X
Xchar *cnull = 0;
X
Xstruct cmdstruct cmdtab[] =
X{
X 'C', create, &cnull, 1,
X 'D', date, &cnull, 1,
X 'E', showerror, &cnull, 1,
X 'F', file, &cnull, 1,
X 'G', grep, &cnull, 1,
X 'L', longlist, &cnull, 0,
X 'M', wmake, &cnull, 1,
X 'N', fmake, &cnull, 1,
X 'O', options, &cnull, 1,
X 'P', exec, psargv, 1,
X 'R', remove, &cnull, 0,
X 'S', showgrep, &cnull, 1,
X 'T', display, &cnull, 1,
X 'W', exec, whoargv, 1,
X 'X', xecute, &cnull, 1,
X 'Y', rexecute, &cnull, 1,
X '^', home, &cnull, 1,
X '!', callshell, &cnull, 1,
X '%', chain, shargv, 1,
X '$', exec, bshargv, 1,
X '/', file, rootargv, 1,
X '?', display, helpargv, 1,
X/* dyt */
X '\\', file, owdargv, 1,
X '.', find, &cnull, 1,
X
X 'A',0,0,0,'B',0,0,0,
X 'H',0,0,0,'I',0,0,0,'J',0,0,0,'K',0,0,0,
X 'Q',0,0,0, 'U',0,0,0,'V',0,0,0,
X/* dyt */
X 'Z',0,0,0,'#',0,0,0,
X '&',0,0,0,'(',0,0,0,')',0,0,0,
X '*',0,0,0,'=',0,0,0,'{',0,0,0,'}',0,0,0,'[',0,0,0,']',0,0,0,
X '~',0,0,0,',',0,0,0,';',0,0,0,
X ':',0,0,0,'`',0,0,0,'<',0,0,0,'>',0,0,0,'@',0,0,0,'_',0,0,0,
X '|',0,0,0,
X 'e',0,0,0,'f',0,0,0,'g',0,0,0,'h',0,0,0,'i',0,0,0,'j',0,0,0,
X 'k',0,0,0,'l',0,0,0,'m',0,0,0,'n',0,0,0,'o',0,0,0,'p',0,0,0,
X 'q',0,0,0,'r',0,0,0,'s',0,0,0,'t',0,0,0,
X 'u',0,0,0,'v',0,0,0,'w',0,0,0,'x',0,0,0,'y',0,0,0,'z',0,0,0,
X
X CMD_DATE, date, &cnull, 1,
X CMD_SE, showerror, &cnull, 1,
X CMD_SG, showgrep, &cnull, 1,
X 0,0,0,0
X} ;
X
X/* If this is not EX/VI, check out nedit() in show.c
X * It is preferable to leave this alone and change EDITOR in
X * everyone's .vshrc
X */
Xchar stdedit[] = "vi";
X
Xstruct parmstruct parmtab[] =
X{
X "EDITOR", stdedit,
X "make", "/bin/make",
X "grep", "/bin/grep",
X "rmhelp", "/usr/lib/vsh/rmhelp",
X "showhelp", "/usr/lib/vsh/showhelp",
X "makerror", ".makerror",
X "grepout", ".grepout",
X "vshmode", "enter",
X "quitchar", "D",
X "pagechar", "{",
X "PATH", ":/bin:/usr/bin",
X "TERM", "unknown",
X "HOME", "",
X "SHELL", "/bin/sh",
X "entertext", ENTEREDIT,
X "window", "24",
X "helpfile", "",
X "column", "1",
X "noargprompt", "",
X "VImotion", "",
X#ifdef V7TTY
X "MAIL", "/usr/spool/mail/~",
X#else
X "MAIL", "/usr/mail/~",
X#endif
X "moresize", MMAXSIZE,
X "enterpath", ":",
X 0, 0
X} ;
All work and no play makes Jack a dull boy
echo src/cmdload.c
sed 's/^X//' > src/cmdload.c << 'All work and no play makes Jack a dull boy'
X#include "hd.h"
X#include "command.h"
X
X/* This loads the command table from the .vshrc file */
X
Xcmdldrc ()
X{
X FILE *rcstream, /* Stream of .vshrc */
X *fopen(); /* Stdio open proc */
X
X char cbuf [STRMAX], /* Buffer for input parm */
X *argv [ARGVMAX]; /* Pointers to input parm */
X int argc; /* Number of parm */
X
X int line = 1; /* Current line num of rcstream */
X
X /* initialize */
X
X strcpy (cbuf, HOME);
X strcat (cbuf, "/.vshrc");
X rcstream = fopen (cbuf, "r");
X if (rcstream == NULL) return;
X printf ("Loading .vshrc\r\n");
X
X while (!feof (rcstream))
X {
X if (readarg (rcstream, &line, &argc, argv, cbuf) != BAD)
X cmdldarg (line-1, argc, argv);
X }
X}
X
X/* This loads command tables as specified in its arguments */
Xcmdldarg (line, argc, argv)
Xint line, argc; char *argv[];
X{
X
X char *malloc(); /* Standard allocation proc */
X register i; /* An index */
X
X register struct cmdstruct *cmdp; /* Pointers */
X register struct classstruct *classp;
X register struct parmstruct *parmp;
X
X /* An addressable representation of CNULL (0) */
X extern char *cnull;
X
X if (argc <= 0) ;
X else if (argc == 1) lderror ("Too few args", line);
X
X else if (strlen (argv [0]) == 1)
X {
X cmdp = cmdloc (*argv [0]);
X if (cmdp->cmd_char == 0)
X {
X lderror ("Not a proper command",
X line);
X return;
X }
X classp = classloc (argv [1]);
X if (*classp->cl_name == 0)
X {
X lderror ("Illegal keyword", line);
X return;
X }
X if (!(
X argc-2 == classp->cl_count ||
X (classp->cl_count == -1 && argc <= 3) ||
X (classp->cl_count == -2 && argc >= 2)))
X {
X
X lderror
X ("Improper number of parameters", line);
X return;
X }
X /* All testing over with--store new command */
X
X cmdp->cmd_proc = classp->cl_proc;
X cmdp->cmd_xdir = classp->cl_xdir;
X
X if (argc <= 2) cmdp->cmd_argv = &cnull;
X else cmdp->cmd_argv =
X (char **) malloc ((argc - 1) * (sizeof *argv));
X
X for (i=2; i<argc; i++)
X {
X cmdp->cmd_argv [i-2] =
X malloc (strlen (argv [i]) + 1);
X strcpy (cmdp->cmd_argv[i-2], argv [i]);
X cmdp->cmd_argv [i-1] = CNULL;
X }
X }
X else
X {
X for (parmp = parmtab;
X parmp->p_name &&
X strcmp (parmp->p_name, argv[0]);
X parmp++);
X if (parmp->p_name)
X {
X parmp->p_val = malloc
X (strlen (argv[1]) + 1);
X strcpy (parmp->p_val, argv[1]);
X }
X else lderror ("Bad parameter name", line);
X if (argc != 2) lderror
X ("Too many args", line);
X }
X}
All work and no play makes Jack a dull boy
echo src/cmdrun.c
sed 's/^X//' > src/cmdrun.c << 'All work and no play makes Jack a dull boy'
X#
X#include "hd.h"
X#include "command.h"
X
X/* Each command called by command.c must return special information.
X First, the next command to execute is returned in the last eight
X bits (and can be masked out with CMDMASK). If no more commands
X are to be run, these bits are set to 0. The next bit is the
X REPLOT bit. If on, the screen has been altered enough to require
X a replot. The NOOP bit indicates a command was not found.
X Finally, the ENTERDIR bit indicates a new directory has been
X entered.
X*/
X
Xcommand (cmd, ctype) register cmd; int ctype;
X{
X
X register ret; /* return value */
X int next; /* Temp variable for next command */
X register struct cmdstruct *cmdp;
X
X ret = 0;
X selecttype = ctype;
X while (cmd)
X {
X if ((ctype == DIRCMD) &&
X ((next = dircmd (cmd)) != NOOP)
X )
X cmd = next;
X else
X {
X cmdp = cmdloc (cmd);
X if (cmdp->cmd_proc && (
X (cmdp->cmd_xdir)||(ctype == DIRCMD)))
X {
X
X cmd = (*cmdp->cmd_proc) (cmdp->cmd_argv);
X }
X else cmd = NOOP;
X }
X ret |= cmd & (REPLOT | ENTERDIR | NOOP);
X cmd &= CMDMASK;
X }
X if (ret & NOOP)
X {
X putmsg ("Unknown command. Press ? for help. ");
X if (ret & REPLOT) getrtn ();
X }
X return ret;
X}
X
X/* Classloc returns the classtab element corresponding the keyword referenced
X by cp */
X
Xstruct classstruct *
X classloc (cp) register char *cp;
X{
X
X register struct classstruct *classp;
X
X for (classp = classtab;
X *classp->cl_name && strcmp (cp, classp->cl_name);
X classp++);
X return classp;
X}
X
X/* Cmdloc returns the cmdtab element corresponding to ch */
X
Xstruct cmdstruct *
X cmdloc (ch) register char ch;
X{
X
X register struct cmdstruct *cmdp;
X
X for (cmdp = cmdtab;
X cmdp->cmd_char && cmdp->cmd_char != ch;
X cmdp++);
X
X return cmdp;
X}
X
X/* Cmdproc returns a pointer to the procedure which runs the command
X corresponding to ch. */
X
Xint (*
X cmdproc (ch))() char ch;
X{
X extern struct cmdstruct *cmdloc();
X
X return ((*cmdloc)(ch)->cmd_proc);
X}
All work and no play makes Jack a dull boy
echo src/command.h
sed 's/^X//' > src/command.h << 'All work and no play makes Jack a dull boy'
X/* There are two important structures used by the command processor.
X Cmdtab encodes the current commands. Each command corresponds to
X an element in cmdtab and is type struct cmdstruct. Four fields
X determine the command. Cmd_char is the character which, when
X pressed, calls the command. Cmd_proc is the procedure which
X runs the command. Cmd_argv is used as a parameter to that proc.
X Cmd_xdir, when on, indicates the command may be run anywhere, and
X not just on the directory page.
X
X The classtab is used to map statements from the .vshrc file to
X cmdtab elements. The keyword in a .vshrc statement is looked
X up in classtab, and then the classtab element is used to load
X the cmdtab element.
X*/
X
Xstruct classstruct { /* Classification structure */
X char * cl_name; /* Name (key word) */
X int (*cl_proc)(); /* Command procedure */
X short cl_count; /* Number of args */
X char cl_xdir; /* Is ok outside dir page */
X};
X
Xstruct cmdstruct { /* Command structure */
X char cmd_char; /* Command char */
X int (*cmd_proc)(); /* Command procedure */
X char ** cmd_argv; /* Array of arguments for command */
X char cmd_xdir; /* Is ok outside dir page */
X};
X
Xstruct classstruct *classloc();
Xstruct cmdstruct *cmdloc ();
Xextern (*cmdproc ())();
X
Xextern struct classstruct classtab[];
Xextern struct cmdstruct cmdtab[];
X
X/* Command characters for important commands */
X
X#define CMD_DATE 0x80
X#define CMD_SE 0x81
X#define CMD_SG 0x82
All work and no play makes Jack a dull boy
echo src/curdir.c
sed 's/^X//' > src/curdir.c << 'All work and no play makes Jack a dull boy'
X#
X/* Curdir finds the name of the working directory and puts in
X wdname. This is done by calling on the pwd program.
X*/
X#include "hd.h"
X#include "mydir.h"
Xstatic char pwd[] =
X{
X "/bin/pwd"
X} ;
X
Xcurdir ()
X{
X
X int p, rdlen, pipefile [2];
X#define pipein pipefile [0]
X#define pipeout pipefile [1]
X
X pipe (pipefile);
X printf ("%s\r\n", pwd);
X if ((p = myfork ()) == 0)
X {
X close (outfile); dup (pipeout);
X close (pipein); close (pipeout);
X execl (pwd, pwd, 0);
X exit (1);
X }
X else
X {
X close (pipeout);
X join (p);
X rdlen = read (pipein, wdname, sizeof wdname);
X if (rdlen < 2 || rdlen == sizeof wdname || wdname [0] != '/')
X {
X printf ("Cannot find name of working directory\r\n");
X return 1;
X }
X wdname [rdlen - 1] = 0;
X close (pipein);
X }
X return 0;
X}
All work and no play makes Jack a dull boy
echo src/curses.c
sed 's/^X//' > src/curses.c << 'All work and no play makes Jack a dull boy'
X#include "hd.h"
X#include "mydir.h"
X
Xchar *BC, *UP, *CM, *CL;
X/* dyt */
Xchar *CE;
Xchar *SO, *SE;
Xshort PC;
Xint CO, LI;
Xchar *CS, *CB;
Xchar *BE, *BO;
Xchar *SR, *CD;
Xchar *TI, *TE;
Xint AM, XN;
X
Xchar tspace [512], *atspace;
Xchar *tgetstr ();
Xint putch ();
X
Xint ewindow = 0; /* Separate exec window */
Xint xoff = 0; /* Column offset */
X
Xcurs_init ()
X{
X char bp [1024];
X char * tgoto ();
X static char winbuf[10];
X
X tgetent (bp, TERM);
X atspace = tspace;
X PC = *tgetstr ("pc", &atspace);
X CM = tgetstr ("cm", &atspace);
X CL = tgetstr ("cl", &atspace);
X UP = tgetstr ("up", &atspace);
X BC = tgetstr ("bc", &atspace);
X CE = tgetstr ("ce", &atspace);
X CO = tgetnum ("co");
X LI = tgetnum ("li");
X CS = tgetstr ("cs", &atspace);
X /* A new one, clear to beginning of display */
X CB = tgetstr ("cb", &atspace);
X /* Blink and blink end */
X BO = tgetstr ("bo", &atspace);
X BE = tgetstr ("be", &atspace);
X if (BC == CNULL || tgetflag("bs"))
X BC = "\b";
X/*
X * Enables use of reverse video/standout
X */
X SO = tgetstr ("so", &atspace);
X SE = tgetstr ("se", &atspace);
X/*
X * Scroll reverse
X */
X SR = tgetstr ("sr", &atspace);
X CD = tgetstr ("cd", &atspace);
X AM = tgetflag ("am");
X XN = tgetflag ("xn");
X TI = tgetstr ("ti", &atspace);
X TE = tgetstr ("te", &atspace);
X
X if (SO == CNULL)
X SO = "";
X if (SE == CNULL)
X SE = "";
X if (BO == CNULL)
X BO = "";
X if (BE == CNULL)
X BE = "";
X if (CM == CNULL)
X return 1;
X if (CO < 80) {
X fprintf(stderr, "\07Too narrow screen\r\n");
X CO = 80;
X }
X else if (CO > 80)
X xoff = CO - 80;
X setcolumn();
X if (LI < 8)
X return 1;
X sprintf(winbuf, "%8d", LI);
X WINDOW = winbuf;
X setwindow();
X return 0;
X}
X
Xsetwindow()
X{
X register int row;
X register int owin1, owin2;
X
X owin1 = window;
X row = atoi(WINDOW);
X window = (row > (maxnfpp+VSHTOP+VSHBOT))
X ? (maxnfpp+VSHTOP+VSHBOT) : row;
X if (window < 8) {
X putmsg("\07Screen too small");
X window = 8;
X }
X nfpp = window - (VSHTOP+VSHBOT);
X ewindow = (LI-window > PAGEMIN);
X if (owin1 != window) {
X owin2 = window;
X window = owin1;
X ewin();
X window = owin2;
X vwin();
X erase();
X }
X else
X vwin();
X}
X
X/* Multi-column listing */
Xsetcolumn()
X{
X register int i;
X
X i = (CO-VSHLEFT)/19; /* Max number of columns */
X if ((column = atoi(COLUMN)) < 1)
X column = 1;
X if (column > i)
X column = i;
X colfield = (CO-VSHLEFT)/column;
X pageoff = 0;
X}
X
Xstatic int ewinf = 0;
Xewin()
X{
X if (!ewindow)
X return 0;
X bufout();
X if (CS) {
X tputs(tgoto(CS, LI-1, window-VSHBOT), 0, putch);
X ewinf = 1;
X }
X atxy(1, LI);
X if (TE)
X tputs(TE, 0, putch);
X unbufout();
X return ewinf;
X}
X
Xvwin()
X{
X if (!ewinf)
X return;
X bufout();
X if (TI)
X tputs(TI, 0, putch);
X if (CS)
X tputs(tgoto(CS, window-1, 0), 0, putch);
X atxy(1, window-1);
X clearline();
X atxy(1, 1);
X unbufout();
X ewinf = 0;
X}
X
Xhilite(a0, a1, a2)
Xchar *a0, *a1, *a2;
X{
X if ((int)a0 != 0) {
X tputs(SO, 0, putch);
X if ((int)a0 == 1)
X return;
X printf(a0, a1, a2);
X }
X tputs(SE, 0, putch);
X}
All work and no play makes Jack a dull boy
echo src/dflt.vshrc
sed 's/^X//' > src/dflt.vshrc << 'All work and no play makes Jack a dull boy'
XC create
XD date
XE showerror
XF file
XG grep
XL longlist
XM wmake
XN fmake
XO options
XP exec /bin/ps
XR remove
XS showgrep
XT display
XW exec /bin/who
XX xecute
XY rexecute
X^ home
X! shell
X% chain /bin/ksh
X$ exec /bin/sh
X/ file /
X? display /usr/lib/vsh/genhelp
X\ file /src/vsh.d/src
X. find
XEDITOR vi
Xmake /bin/make
Xgrep /bin/grep
Xrmhelp /usr/lib/vsh/rmhelp
Xshowhelp /usr/lib/vsh/showhelp
Xmakerror .makerror
Xgrepout .grepout
Xvshmode enter
Xquitchar D
Xpagechar {
XPATH /usr/5bin/graf:/usr/ucb:/bin:/usr/bin:/usr/local/bin:/etc:/usr/hosts:/usr1/dan/bin:/usr/5bin:/usr/games::
XTERM tvi950
XHOME nowhere
XSHELL /bin/ksh
Xentertext $EDITOR
Xwindow 24
Xhelpfile
Xcolumn 1
Xnoargprompt
XVImotion
XMAIL /usr/spool/mail/dan
Xmoresize 10000
Xenterpath :
All work and no play makes Jack a dull boy
echo src/dir.c
sed 's/^X//' > src/dir.c << 'All work and no play makes Jack a dull boy'
X#include "hd.h"
X#include "mydir.h"
X#ifdef NDIR
X#include <errno.h>
X#endif
X#define curmtime wd_stb.st_mtime
X
X/* See mydir.h for information about these variables */
Xint tfiles, tpages, cpage;
Xint pageoff = 0, column = 1, colfield = 19;
X
Xstruct stat wd_stb;
X
Xint wdfile;
Xchar wdname [MPLEN + 1];
X/* dyt */
Xchar wdname0 [MPLEN + 1];
Xstatic int oldpage = 1;
X
Xchar selectname[STRMAX];
Xint selectcmd;
Xint selectpage;
Xint selecttype;
X
Xint owindow = 0;
X
X#ifndef NDIR
Xstruct direct *dirbuf;
Xchar **d_namep;
X#else
Xstruct direct **d_dirp;
X#endif
X
Xint dir_status;
Xstruct stat scr_stb;
X
Xchar *dirmsg [] =
X{
X "", "(System Error) ", "(Too big) ",
X "(Unreadable) "
X} ;
X
X/* Enterdir -- Enter into new directory.
X The parameter newdir is the file to change to. Pass a single
X element file name or a full path name. "file", "..", or "."
X are OK. "../..", "/a/b/..", "a/", or "a/." must be passed
X to the file procedure instead.
X
X On success, there is a new current directory, and wdname has been
X modified to reflect the new path name. ENTERDIR | REPLOT is the
X return value. On failure, NOREPLOT is returned. Nothing is changed.
X*/
X
Xenterdir (newdir)
Xregister char *newdir;
X{
X char wdname1 [MPLEN + 1];
X register int entermode; /* Type of entry */
X#define FOREWARD 0 /* Deaper into dir */
X#define BACKWARD 1 /* Previous dir (..) */
X#define STOP 2 /* Stay in same place (.) */
X#define LOAD 3 /* Load new path name */
X
X if (compe (newdir, DOT)) entermode = STOP;
X else if (compe (newdir, DOTDOT)) entermode = BACKWARD;
X else if (newdir[0] == '/') entermode = LOAD;
X else entermode = FOREWARD;
X
X if (entermode == FOREWARD && strlen (wdname) > LPLEN)
X {
X putmsg ("Cannot chdir -- Pathname too long");
X return NOREPLOT;
X }
X
X if (chdir (newdir))
X {
X myperror (newdir);
X return NOREPLOT;
X }
X
X /* dyt */
X *wdname1 = 0;
X if (strcmp(wdname, newdir) &&
X (strcmp(DOTDOT, newdir) || strcmp(SLASH, wdname)))
X strcpy(wdname1, wdname);
X
X if (entermode == STOP); /* change to "." */
X else if (entermode == BACKWARD)
X { /* change to ".." */
X todotdot (wdname);
X/* This fails for filesystems not mounted directly off root
X if (ISROOT (wdname)) chdir (SLASH);
X */ if (chdir(wdname)) {
X myperror(wdname);
X return NOREPLOT;
X }
X }
X else if (entermode == LOAD) strcpy (wdname, newdir);
X
X else
X {
X if (!ISROOT (wdname)) strcat (wdname, SLASH);
X strcat (wdname, newdir); /* go deeper into dir */
X }
X
X /* dyt - try to go to old page, save previous directory name */
X entermode = cpage;
X cpage = strcmp(wdname0, wdname) ? 1 : oldpage;
X pageoff = 0;
X oldpage = entermode;
X if (*wdname1)
X strcpy(wdname0, wdname1);
X
X#ifndef NDIR
X close (wdfile); wdfile = open (DOT, 0);
X#endif
X dir_status = unloaded;
X *selectname = 0;
X
X return ENTERDIR | REPLOT;
X}
X
X/* loaddir loads dir and sets assoc parameters */
Xloaddir ()
X{
X register char *s;
X register unsigned i;
X char *malloc();
X static int first=1;
X
X if (!first) {
X#ifndef NDIR
X if (dirbuf != NULL)
X free (dirbuf);
X if (d_namep != NULL)
X free (d_namep);
X#else
X freedir (d_dirp);
X d_dirp = NULL;
X#endif
X }
X else
X first = 0;
X tpages = tfiles = 0;
X
X#ifdef NDIR
X
X dir_status = unloaded;
X if (sortdir())
X dir_status = loaded;
X
X#else
X
X if (wdfile < 0)
X {
X dir_status = protected; return;
X }
X else dir_status = unloaded;
X
X fstat (wdfile, &wd_stb);
X
X/* dyt */
X#ifdef V6
X#define st_size st_size1
X#endif
X
X i = (unsigned)wd_stb.st_size;
X /* Allocate one extra byte for a null (in case last entry is dirsize) */
X s = malloc(i + 1);
X if ((dirbuf = (struct direct *) s) == NULL)
X {
X dir_status = toobig;
X return;
X }
X s[i] = 0;
X lseek (wdfile, 0L, 0); /* read in entire file */
X if (read (wdfile, dirbuf, (unsigned) wd_stb.st_size)
X != (unsigned) wd_stb.st_size)
X return;
X
X /*
X * dyt - Alloc name pointer array
X * Note that this array is larger than necessary since there
X * will be empty slots in the directory file. To economize
X * on this array size, one could put this code in sortdir()
X * after it is determined how many files there are. The trade-off
X * is that sortdir() would have to make two passes through
X * dirbuf. The wager here is that most (especially large)
X * directories don't have too many empty slots anyways.
X */
X d_namep = malloc(((unsigned) wd_stb.st_size/dirsize)*sizeof d_namep[0]);
X if (d_namep == NULL) {
X printf(" Out of memory");
X dir_status = toobig;
X return;
X }
X
X sortdir ();
X dir_status = loaded;
X
X#endif
X
X tpages = tfiles / nfpp + ((tfiles % nfpp) > 0);
X return;
X}
X
X#ifndef NDIR
X/* sortdir sorts the directory entries. when done, the following is true:
X 1) tfiles contains the number of files available
X 2) the d_namep array will contain pointers to the files.
X these will be sorted assending.
X*/
Xsortdir ()
X{
X register struct direct *maxent, *dirp;
X int dircmp ();
X
X tfiles = 0;
X maxent = & dirbuf [(unsigned)wd_stb.st_size / dirsize];
X for (dirp = dirbuf; dirp < maxent; dirp++)
X {
X if (dirp->d_ino) {
X d_namep [tfiles++] = dirp->d_name;
X /* Note: this has the effect of providing a null byte at the end */
X dirp->d_ino = 0;
X }
X }
X qsort (d_namep, tfiles, sizeof d_namep [0], dircmp);
X}
X
Xdircmp (a, b) char **a, **b;
X{
X return strcmp (*a, *b);
X}
X
X#else
X
X/*
X * For the NDIR version, we set a pointer d_dirp to an array of pointers
X * to sorted directory entries. The number of entries is also placed in
X * tfiles
X */
Xsortdir()
X{
X extern int errno;
X extern alphasort();
X
X tfiles = scandir(DOT, &d_dirp, NULL, alphasort);
X if (tfiles == -1) {
X dir_status = protected;
X if (errno == ENOMEM)
X dir_status = toobig;
X tfiles = 0;
X d_dirp = NULL;
X return NULL;
X }
X return 1;
X}
X
X/*
X * Free memory associated with the sorted directory entry array
X */
Xfreedir(p)
Xstruct direct **p;
X{
X register int i;
X
X if (p == NULL)
X return;
X i = tfiles;
X while (i-- > 0)
X free (p[i]);
X free (p);
X}
X#endif
X
X/* Dispdir displays a page of the directory.
X W A R N I N G. Dispdir modifies global data. If the dir is not
X loaded, or is out of date, dispdir will call on loaddir.
X Cpage can be adjusted to conform to the current dir.
X An out of date dir is reloaded only if reload is true.
X
X In general, the goal of dispdir is to make sure the internal
X representation of the directory is consistent with the real
X directory, and what is displayed is consistent with the internal
X directory.
X*/
X
Xdispdir (reload) int reload;
X{
X register int dirx; /* index into dirbuf */
X register int dirchar; /* char to select file assoc. with dirx */
X register int mode;
X int pe, po;
X extern char username[];
X struct stat tmpsbuf;
X extern int didlong; /* from longlist() */
X
X long lastmtime; /* last time dir was modified */
X
X bufout (); clearmsg (-1);
X
X dirx = 0;
X didlong = 0;
X if (window != owindow) {
X owindow = window;
X dirx++;
X }
X if (reload)
X {
X lastmtime = curmtime;
X#ifndef NDIR
X fstat (wdfile, &wd_stb);
X#else
X stat(DOT, &wd_stb);
X#endif
X if (dirx || (lastmtime != curmtime) || dir_status) loaddir ();
X }
X else if (dirx)
X loaddir();
X
X cpage = max (1, min (cpage, tpages));
X
X erase ();
X hilite (1);
X printf ("Directory: %s %sUser: %s", wdname, dirmsg [dir_status],
X username);
X
X if (VSHMODE == SELECTMODE) {
X printf(" (Select mode)");
X mode = 15;
X }
X else
X mode = 0;
X
X if (tfiles == 0)
X {
X hilite(0);
X unbufout (); return;
X }
X
X if (tpages > 1)
X {
X atxy (66+xoff,
X (strlen(wdname)+strlen(username)+mode+strlen(dirmsg[dir_status])
X > 45+xoff) ? 2: 1);
X if (column > 1 && cpage != tpages) {
X po = cpage+column-1;
X if (po > tpages)
X po = tpages;
X printf ("Page %d-%d / %d", cpage, po, tpages);
X }
X else
X printf ("Page %d / %d", cpage, tpages);
X }
X
X hilite(0);
X po = pageoff;
X pageoff = 0;
X
X do {
X pe = pgend();
X for(dirx=0, dirchar='a'; dirx < pe; dirx++, dirchar++) {
X if (pageoff == 0) {
X atfile (dirx, 1);
X printf("%c ", dirchar);
X }
X else
X atfile (dirx, OFFFILE+(pageoff*colfield));
X printf("%s", filename(dirx));
X stat(filename(dirx),&tmpsbuf);
X mode = tmpsbuf.st_mode;
X if ((mode&S_IFMT) == S_IFDIR)
X printf("/");
X else if (mode&S_IEXEC)
X printf("*");
X }
X pageoff++;
X } while (pageoff < column && (cpage+pageoff) <= tpages);
X pageoff = po;
X
X if (pageoff >= column)
X pageoff = column - 1;
X if (cpage+pageoff > tpages)
X pageoff = tpages - cpage;
X if (reload && *selectname
X && (selectcmd >= pgend()
X || strcmp(filename(selectcmd), selectname)))
X *selectname = 0;
X if (*selectname) {
X atfile(selectcmd, OFFARROW+colfield*pageoff);
X printf(arrow);
X }
X if (column > 1)
X colprompt();
X
X if (*HELPFILE) {
X mode = 0;
X atfile (mode, 24+xoff);
X for (dirx = 0; dirchar = helptext[dirx]; dirx++) {
X if (dirchar == '\r')
X continue;
X else if (dirchar == '\n')
X atfile(++mode, 24+xoff);
X else
X putch(dirchar);
X }
X }
X
X unbufout ();
X}
X
X/* Change dir to father of dir */
Xtodotdot (dir) char *dir;
X{
X
X register char *cp;
X
X for (cp = dir; *cp; cp++); /* Scan to end of name */
X while (*--cp != '/'); /* Scan back to a slash */
X if (cp == dir) cp++; /* Must handle root specially */
X *cp = 0;
X}
X
X/* Calculate end of current page including offset */
Xpgend()
X{
X register int pe;
X
X pe = tfiles % nfpp;
X if ((cpage+pageoff) != tpages || pe == 0)
X pe = nfpp;
X return pe;
X}
All work and no play makes Jack a dull boy
echo src/dircmd.c
sed 's/^X//' > src/dircmd.c << 'All work and no play makes Jack a dull boy'
X#include "hd.h"
X#include "mydir.h"
X
Xdircmd (cmd) register cmd;
X{
X static int eotflag;
X register ret; /* return value */
X register int i;
X int scmd, selflag;
X int putch();
X char oldvimotion;
X extern int didlong; /* from longlist() */
X
X ret = REPLOT;
X scmd = cmd;
X selflag = (VSHMODE == SELECTMODE);
X /* Defaults to EOT */
X if (cmd == (QUITCHAR-'@')) {
X if (eotflag++) {
X clearmsg(2);
X printf("\r\n\n");
X leave ();
X }
X putmsg("(Quit)");
X return NOREPLOT;
X }
X else {
X eotflag = 0;
X if ((cmd == '\'' || (cmd == '\r' && cmd != PAGECHAR-'@')) && selflag) {
X if (*selectname)
X cmd = 'a'+selectcmd;
X else {
X putmsg("Nothing selected");
X return NOREPLOT;
X }
X }
X else if (VSHMODE == SELECTMODE && VIMOTION)
X cmd = vi_motion(cmd);
X if (cmd == LF)
X ret = enterdir (DOTDOT);
X else if (tfiles == 0) {
X putmsg("No files");
X return NOOP;
X }
X else if ((cmd == '+') || (column < 2 && cmd == CTLF)) {
X cpage += pageoff ? pageoff : 1;
X if (cpage > tpages)
X cpage = 1;
X pageoff = 0;
X }
X else if ((cmd == EOT) || (cmd == ESNP) || (cmd == (PAGECHAR-'@'))) {
X if (cpage == tpages)
X cpage = 1;
X else {
X cpage += column > 1 ? column-1 : 1;
X if (cpage > tpages)
X cpage = tpages;
X }
X pageoff = 0;
X }
X else if (cmd == TABCMD || cmd == ESRT || cmd == ESLF) {
X if (column > 1) {
X i = pageoff;
X /* Cleanup display after longlisting */
X if (didlong)
X dispdir(0);
X if (cmd == ESLF) {
X if (pageoff == 0) {
X pageoff = column - 1;
X if ((cpage+pageoff) >= tpages)
X pageoff = tpages - cpage;
X }
X else
X pageoff--;
X }
X else {
X if ((cpage+pageoff) >= tpages || pageoff >= (column-1))
X pageoff = 0;
X else
X pageoff++;
X }
X bufout();
X atxy(OFFFILE+colfield*i, 2);
X printf(" ");
X colprompt();
X /* Fix selected item */
X if (cpage != tpages && *selectname) {
X atfile(selectcmd, OFFARROW+colfield*i);
X printf(" ");
X *selectname = 0;
X /* Kludge ! */
X oldvimotion = VIMOTION;
X VIMOTION = 0;
X dircmd(selectcmd+'a');
X VIMOTION = oldvimotion;
X }
X unbufout();
X }
X ret = NOREPLOT;
X }
X else if ((cmd >= 'a' && cmd <= 'z') || cmd == ESUP || cmd == ESDN)
X {
X i = pgend()-1;
X if (cmd == ESUP) {
X if (*selectname) {
X if (i == 0)
X return NOREPLOT;
X cmd = selectcmd-1;
X if (cmd < 0)
X cmd = i;
X }
X else
X cmd = selflag ? 0 : i+1;
X }
X else if (cmd == ESDN) {
X if (*selectname) {
X if (i == 0)
X return NOREPLOT;
X cmd = selectcmd+1;
X if (cmd > i)
X cmd = 0;
X }
X else
X cmd = selflag ? 0 : i+1;
X }
X else
X cmd -= 'a';
X if (cmd > i)
X ret = NOOP;
X else if (selflag && (*selectname == 0 || selectcmd != cmd)) {
X if (*selectname) {
X atfile(selectcmd, OFFARROW+colfield*pageoff);
X printf(" ");
X }
X selectcmd = cmd;
X selectpage = cpage+pageoff;
X atfile(cmd, OFFARROW+colfield*pageoff);
X printf(arrow);
X strcpy(selectname, filename(cmd));
X ret = NOREPLOT;
X }
X else if (enterfile (filename (cmd)) == NOREPLOT)
X {
X/*
X atfile(cmd, OFFARROW+colfield*pageoff); printf(" ");
X longfile (cmd);
X */
X ret = NOREPLOT;
X }
X }
X else if (cmd == ESBS || cmd == ESFS) {
X /* i is max of window */
X ret = (cmd == ESFS);
X if (*selectname)
X i = *selectname;
X else {
X i = ret ? pgend()-1 : 0;
X i = (filename(i))[0];
X }
X if (ret)
X i++;
X else
X i--;
X ret = findc(i, ret);
X }
X else if (cmd > '0' && cmd <= '9') {
X cpage = cmd - '0';
X pageoff = 0;
X }
X else if (cmd == '0') {
X cpage = tpages;
X pageoff = 0;
X }
X else if (cmd == '-')
X {
X cpage--;
X if (cpage < 1) cpage = tpages;
X pageoff = 0;
X }
X else if (cmd == CTLU) {
X if (cpage == 1)
X cpage = tpages;
X else {
X cpage -= column > 1 ? column-1 : 1;
X if (cpage < 1)
X cpage = 1;
X }
X pageoff = 0;
X }
X else if (cmd == CTLL)
X *selectname = 0;
X else
X ret = NOOP;
X }
X /* VI style motion commands */
X if (scmd != cmd && ret == NOOP && 'h' <= scmd && scmd <= 'l' && scmd != 'i') {
X ret = dircmd(vi_motion(scmd));
X }
X if (cpage+pageoff != selectpage)
X *selectname = 0;
X return ret;
X}
X
Xcolprompt()
X{
X atxy(OFFFILE+colfield*pageoff, 2);
X tputs(BO, 0, putch);
X printf("V");
X tputs(BE, 0, putch);
X}
X
Xvi_motion(cmd)
Xregister int cmd;
X{
X switch(cmd) {
X case 'h':
X cmd = ESLF;
X break;
X case 'j':
X cmd = ESDN;
X break;
X case 'k':
X cmd = ESUP;
X break;
X case 'l':
X cmd = ESRT;
X break;
X }
X return cmd;
X}
All work and no play makes Jack a dull boy
echo src/dirlist.c
sed 's/^X//' > src/dirlist.c << 'All work and no play makes Jack a dull boy'
X#include "hd.h"
X#include "mydir.h"
X#include "command.h"
X#include <pwd.h>
X
X#define SHIFT1 13
X#define SHIFT2 6
X#define SHIFT3 3
X#define MASK 07
X
Xchar *pfstatus (fname) char * fname;
X{
X
X/* long listing of a file */
X static char *mchar [2] [8] =
X {
X "---", "--x", "-w-", "-wx",
X "r--", "r-x", "rw-", "rwx",
X "--s", "--s", "-ws", "-ws",
X "r-s", "r-s", "rws", "rws"
X } ;
X
X static char fformat [8] =
X {
X#ifdef VENIX
X '0', '1', '2', '3', ' ', 'c', 'd', 'b'
X#else
X#ifdef V6
X '0', '1', '2', '3', ' ', 'c', 'd', 'b'
X#else
X ' ', 'c', 'd', 'b', '-', 'l', 's', '?'
X#endif
X#endif
X } ;
X
X register mode;
X struct passwd *getpwuid();
X static struct passwd *p;
X#ifdef SYMLINK
X static char slink[STRMAX];
X int sflag;
X
X sflag = 0;
X if (lstat (fname, &scr_stb))
X#else
X if (stat (fname, &scr_stb))
X#endif
X {
X printf ("Cannot Access");
X return 0;
X }
X mode = scr_stb.st_mode;
X
X#ifdef SYMLINK
X if ((mode&S_IFLNK) == S_IFLNK) {
X mode = readlink(fname, slink, STRMAX-1);
X if (mode == -1) {
X printf ("Cannot read link");
X return 0;
X }
X slink[mode] = 0;
X sflag++;
X if (stat (fname, &scr_stb)) {
X printf ("Cannot Access");
X return 0;
X }
X mode = scr_stb.st_mode;
X }
X#endif
X
X printf ("%c%s%s%s%s%2d",
X (mode & S_ISVTX) ? 't' :
X fformat [(mode >> SHIFT1) & MASK],
X mchar [(mode & S_ISUID) != 0] [(mode >> SHIFT2) & MASK],
X mchar [(mode & S_ISGID) != 0] [(mode >> SHIFT3) & MASK],
X mchar [0] [mode & MASK],
X scr_stb.st_nlink > 99 ? "" : " ",
X scr_stb.st_nlink);
X /* dyt */
X if (p == 0 || p->pw_uid != scr_stb.st_uid)
X p = getpwuid(scr_stb.st_uid);
X if (p)
X printf(" %8s", p->pw_name);
X else
X printf(" %8d", scr_stb.st_uid);
X mode &= S_IFMT;
X if (mode == S_IFCHR || mode == S_IFBLK)
X printf ("%5d, %3d",
X#ifdef V6
X major (scr_stb.st_addr[0]), minor (scr_stb.st_addr[0]));
X#else
X major (scr_stb.st_rdev), minor (scr_stb.st_rdev));
X#endif
X else
X#ifdef V6
X printf ("%10ld", (((long)scr_stb.st_size0&0377)<<16L)
X + (unsigned)scr_stb.st_size1);
X#else
X printf ("%10ld", scr_stb.st_size);
X#endif
X printf (" %.24s", ctime (&scr_stb.st_mtime));
X#ifdef NDIR
X return (sflag ? slink : 0);
X#endif
X}
X
X/* This prints out the protection modes of the files on the current
X page. It knows the page from the global variable cpage. The
X value NOREPLOT is always returned, to make globalcmd happy.
X*/
Xint didlong;
X
Xlonglist ()
X{ /* long listing for entire page */
X register i, j;
X
X bufout ();
X j = pgend();
X for (i=0; i < j; i++) longfile (i);
X didlong = j;
X unbufout ();
X
X return CMD_DATE; /* Run date command */
X}
X
Xlongfile (index) int index;
X{
X register char *s;
X register int i;
X int putch();
X
X if (pageoff) {
X cpage += pageoff;
X pageoff = 0;
X i = column;
X column = 1; /* Display only current page */
X dispdir(0);
X column = i;
X }
X atfile (index, 23);
X if (CE)
X tputs(CE, 0, putch);
X s = pfstatus (filename (index));
X#ifdef SYMLINK
X if (s) {
X if (xoff < 10) {
X atfile (index, OFFFILE-2);
X printf(" @");
X }
X printf("%-18.18s", s);
X }
X#endif
X}
X
X/* Warning: some systems have macros which define these in <sys/types.h> */
X#ifdef MACMAJOR
Xmajor(i)
Xdev_t i;
X{
X return (i>>8);
X}
X
Xminor(i)
Xdev_t i;
X{
X return (i&0377);
X}
X#endif
All work and no play makes Jack a dull boy
echo src/enterf.c
sed 's/^X//' > src/enterf.c << 'All work and no play makes Jack a dull boy'
X#include "hd.h"
X#include "mydir.h"
X#include "classify.h"
X
X/* Enterfile selects its parameter fname; Fname may either be a single
X element file name (no slashes) or a full path name. Enterfile
X can handle files which look like ".", "..", "file.c", or "/a/b".
X For files which could look like "/a/b/", "a/b", or "./../../a" use
X the procedure "file" (file expects an argument in argv format).
X*/
Xenterfile (fname) register char *fname;
X{
X register char *s;
X register int flag;
X int i;
X
X flag = classify(fname);
X /* Protect user against entering binary files */
X if (flag == CL_UNKPLN) {
X putmsg(" Binary file, enter ?");
X i = getch();
X if (i == 'y' || i == 'Y')
X flag = CL_TEXT;
X }
X switch (flag)
X {
X
X case CL_NULL:
X case CL_PROTPLN:
X myperror (fname); return NOREPLOT;
X
X case CL_DIR:
X return enterdir (fname);
X
X case CL_CORE:
X f_exec (DEBUGGER, DEBUGGER, fname, 0); return REPLOT;
X
X case CL_AOUT:
X p_exec ("nm", "nm", fname, 0); return REPLOT;
X
X case CL_AR:
X p_exec ("ar", "ar", "tv", fname, 0); return REPLOT;
X
X case CL_CPIO:
X p_exec (0, fname, "cpio", "cpio", "-ivt", 0); return REPLOT;
X
X case CL_PACK:
X p_exec ("pcat", "pcat", fname, 0); return REPLOT;
X
X case CL_COMPACT:
X p_exec (0, fname, "uncompact", "uncompact", 0); return REPLOT;
X
X case CL_COMPRESS:
X p_exec (0, fname, "uncompress", "uncompress", 0); return REPLOT;
X
X case CL_TEXT:
X flag = REPLOT;
X if (strcmp(ENTERTEXT, ENTEREDIT) == 0)
X f_exec (EDITOR, EDITOR, fname, 0);
X else if (strcmp(ENTERTEXT, ENTERDISP) == 0)
X flag = help(fname);
X else {
X s = ENTERTEXT;
X if (*s == ';')
X s++;
X f_exec (s, s, fname, 0);
X if (*ENTERTEXT != ';')
X getrtn();
X }
X return flag;
X
X
X default:
X putmsg (fname); printf (": Vsh cannot handle this file");
X }
X return NOREPLOT;
X}
Xhome ()
X{ /* enter home directory */
X
X return file (&HOME);
X}
All work and no play makes Jack a dull boy
echo src/file.c
sed 's/^X//' > src/file.c << 'All work and no play makes Jack a dull boy'
X#include "hd.h"
X#include "mydir.h"
X#include "strings.h"
X#include "classify.h"
X#include <pwd.h>
X
Xchar *getuser();
X
X/* File gets a file name, converts it into a full path name, and
X selects that file. */
X
Xfile (argv) char **argv;
X{ /* Select specific file */
X register char *msg;
X char nname [STRMAX];
X
X msg = 0;
X if (*argv == CNULL)
X /* Flag path searching */
X msg = "~File: ";
X if (getfname (*argv, nname, msg) == BAD) return NOREPLOT;
X
X return (enterfile (nname));
X}
X
X/* Create accepts a file name, creats that file, and then enters it. */
X
X#define CRTEXT '1'
X#define CRDIR '2'
X#define CRCOPY '3'
X#define CRLINK '4'
X#define CRMOVE '5'
X
Xstatic char *cr_msgs[3] = {
X ";\rCopy from:", ";\rLink from:", ";\rRename from:"
X};
X
Xstatic int force = 0;
X
Xcreate ()
X{
X
X char nnamebuf [STRMAX], oname [STRMAX];
X register char ch, *cp;
X register int class;
X char *nname;
X
X nname = nnamebuf;
X if (getfname (CNULL, nname, "!Create: ") == BAD) return NOREPLOT;
X
X if (!access (nname, 0))
X {
X putmsg (nname); printf (": Already exists");
X if (force) {
X printf(", creating anyways");
X sleep(1);
X }
X else {
X printf(", !filename to overwrite");
X return NOREPLOT;
X }
X }
X else
X force = 0;
X
X /* Can we write-access the directory ? */
X strcpy(oname, nname);
X todotdot (oname);
X class = classify (oname);
X
X if (class == CL_NULL || access (oname, 3))
X {
X myperror (oname); return NOREPLOT;
X }
X else if (class != CL_DIR)
X {
X putmsg (oname); printf (": Not a directory");
X return NOREPLOT;
X }
X
X erase ();
X hilite ("Creating");
X
X printf (" %s\r\n\n1 Text\r\n2 Directory\r\n3 Copy a file\r\n4 Link a file\r\n5 Rename a file or directory\r\n\n", nname);
X hilite ("Select:");
X
X ch = getch (); putch (CR); putch (LF);
X erase();
X if (ch == CRTEXT)
X {
X f_exec (EDITOR, EDITOR, nname, 0);
X }
X else if (ch == CRDIR)
X {
X if (f_exec ("/bin/mkdir", "mkdir", nname, 0))
X getrtn ();
X else {
X hilite("Directory created. Enter new directory?");
X if (getch() == 'y')
X return enterdir (nname) | REPLOT;
X else
X return REPLOT;
X }
X }
X else if (ch == CRCOPY || ch == CRLINK || ch == CRMOVE)
X {
X if (getfname (CNULL, oname, cr_msgs[ch-CRCOPY]) == BAD) return REPLOT;
X
X switch (classify (oname))
X {
X
X case CL_NULL:
X case CL_PROTPLN:
X myperror (oname); break;
X
X case CL_DIR:
X if (ch != CRMOVE) {
X hilite ("Cannot copy or link to directories");
X break;
X }
X
X default:
X if (ch == CRCOPY)
X f_exec ("/bin/cp", "cp", oname, nname, 0);
X else if (ch == CRMOVE)
X f_exec ("/bin/mv", "mv", oname, nname, 0);
X else if (ch == CRLINK)
X {
X hilite ("Linking\r\n");
X if (link (oname, nname)) {
X myperror ("Link failed");
X break;
X }
X }
X/*
X at (1501);
X */
X if (!access (nname, 0))
X {
X hilite("\r\n\nFile created. Do you wish to examine it?");
X if (getch() == 'y')
X {
X putch (CR);
X putch (LF);
X return enterfile (nname) | REPLOT;
X }
X return REPLOT;
X }
X }
X/*
X at (1501);
X */
X hilite ("\r\n\nFile not created.");
X getrtn ();
X }
X return REPLOT;
X}
X
X/* Getfname takes two character arrays as parameters.
X Inname is the partial pathname of a file. If inname == CNULL,
X getfname will instead read the partial pathname from the terminal.
X The full pathname is returned in outname.
X Getfname has a return value of GOOD or BAD.
X*/
Xgetfname (inname, outname, msg) register char *inname, *outname, *msg;
X{
X char inword [STRMAX]; int ilen;
X int ffind;
X static oldfile[STRMAX];
X
X force = 0;
X ffind = 0;
X if (msg && *msg == '~') {
X msg++;
X ffind++;
X }
X if (inname == CNULL)
X {
X tty_push (COOKEDMODE);
X if (msg && *msg == '!') {
X msg++;
X force++;
X }
X if (msg) {
X if (*msg == ';')
X hilite(++msg);
X else
X putmsg(msg);
X }
X ilen = getword (inword);
X tty_pop ();
X if (ilen <= 0)
X {
X clearmsg (0);
X return BAD;
X }
X inname = inword;
X if (*inname == '!' && force) {
X inname++;
X ilen--;
X if (*inname == 0) {
X putmsg("No file name");
X return BAD;
X }
X }
X else
X force = 0;
X if (strcmp("!", inname) == 0)
X strcpy(inname, oldfile);
X if (inname[ilen-1] == '$') {
X if (*selectname == 0) {
X putmsg(" Missing argument");
X return BAD;
X }
X strcpy(inname+ilen-1, selectname);
X putmsg("%s%s", msg, inname);
X }
X }
X
X /*
X * Search for file amongst specified directories
X */
X if (ffind
X && inname[0] != '/'
X && (inname[0] != '.' || inname[1] != '/')
X && srchfile(inname, outname) == GOOD) {
X strcpy(oldfile, outname);
X return GOOD;
X }
X if (pathgen(wdname, inname, outname)) {
X putmsg ("Path name too long");
X return BAD;
X }
X strcpy(oldfile, outname);
X return GOOD;
X}
X
Xsrchfile(inname, outname)
Xchar *inname, *outname;
X{
X register char *s, *t;
X char pbuf[STRMAX];
X
X s = ENTERPATH;
X while (*s) {
X if (*s == ':') {
X s++;
X t = wdname;
X }
X else {
X t = s;
X while (*s)
X if (*s++ == ':') {
X if (*s)
X s[-1] = 0;
X else
X *--s = 0;
X break;
X }
X }
X strcpy(pbuf, t);
X strcat(pbuf, SLASH);
X strcat(pbuf, inname);
X if (pathgen(wdname, pbuf, outname) == 0
X && classify(outname) != CL_NULL) {
X if (*s)
X s[-1] = ':';
X return GOOD;
X }
X if (*s)
X s[-1] = ':';
X }
X return BAD;
X}
X
X/* If one is in dir with pathname "old", and does a chdir "change",
X one ends up in directory "new". Exception: ".." always breaks
X through to the root.
X*/
Xpathgen (old, change, new) char *old, *change, *new;
X{
X
X#ifndef NDIR
X char element [DIRSIZ + 1];
X#else
X char element [MAXNAMLEN + 1];
X#endif
X char chgbuf [STRMAX];
X register char *s;
X register len;
X
X /* Match a user's login directory, or HOME */
X if (getuser(change, chgbuf) == 0)
X strcpy (chgbuf, change);
X s = chgbuf;
X if (*s == '/')
X strcpy(new, SLASH);
X else
X strcpy(new, old);
X
X while (*s)
X {
X extract (element, s);
X if (compe (DOT, element));
X else if (compe (DOTDOT, element))
X todotdot (new);
X else
X {
X len = strlen (new);
X if (len > LPLEN) return 1;
X else if (len > 1) strcat (new, SLASH);
X strcat (new, element);
X }
X }
X return 0;
X}
X
Xextract (element, path) char *element, *path;
X{
X
X register char *cp;
X int eltlen;
X
X for (cp = path; *cp != 0 && *cp != '/'; cp++);
X
X eltlen = cp - path;
X if (eltlen == 0)
X {
X strcpy (element, DOT);
X }
X else
X {
X#ifndef NDIR
X strncpy (element, path, DIRSIZ);
X element [min (eltlen, DIRSIZ)] = 0;
X#else
X strncpy (element, path, MAXNAMLEN);
X element [min (eltlen, MAXNAMLEN)] = 0;
X#endif
X }
X if (*cp) shift (path, eltlen + 1);
X else path [0] = 0;
X}
X
Xshift (path, length) char *path; int length;
X{
X
X register char *cp;
X
X for (cp = path + length; cp [-1];) *path++ = *cp++;
X}
X
X/*
X * getuser(spec, pbuf)
X */
Xchar *getuser(spec, pbuf)
Xchar *spec, *pbuf;
X{
X register char *r, *s, *t;
X struct passwd *p;
X struct passwd *getpwnam();
X
X s = spec;
X if (*s++ != '~')
X return 0;
X t = pbuf;
X while (*t = *s) {
X if (*s++ == '/') {
X *t = 0;
X break;
X }
X t++;
X }
X if (t == pbuf)
X t = HOME;
X else if (p = getpwnam(pbuf))
X t = p->pw_dir;
X else
X t = spec;
X r = pbuf;
X while (*r++ = *t++)
X if (r >= pbuf+LPLEN)
X return 0;
X if (*s) {
X r[-1] = '/';
X while (*r++ = *s++)
X if (r >= pbuf+STRMAX)
X return 0;
X }
X return pbuf;
X}
All work and no play makes Jack a dull boy
echo src/find.c
sed 's/^X//' > src/find.c << 'All work and no play makes Jack a dull boy'
X
X#include "hd.h"
X#include "strings.h"
X#include "command.h"
X#include "classify.h"
X#include "mydir.h"
X
X#ifndef NDIR
Xextern char **d_namep;
X#else
Xextern struct direct **d_dirp;
X#endif
Xextern char quitcmds[];
X
Xfind(argv)
Xchar **argv;
X{
X register int c;
X
X if (*argv == CNULL) {
X putmsg("Find: ");
X c = getch();
X putch(c);
X }
X else
X c = **argv;
X if (c == 0 || c == EOF || any(c, quitcmds) != NULL) {
X clearmsg(1);
X return NOREPLOT;
X }
X if (*argv == CNULL)
X printf("'s");
X return findc(c, 1);
X}
X
Xfindc(c, forw)
Xregister int c;
Xregister int forw;
X{
X register int i;
X
X for (i = 0; i < tfiles; i++)
X#ifndef NDIR
X if (c <= d_namep[i][0]) {
X#else
X if (c <= d_dirp[i]->d_name[0]) {
X#endif
X if (!forw && i)
X i--;
X return findfile(i);
X }
X return findfile(tfiles-1);
X}
X
Xfindfile(index)
Xregister int index;
X{
X register int i, j, f;
X
X i = (index+nfpp)/nfpp;
X j = index%nfpp;
X if ((column < 2 && i != cpage) || i < cpage || i > cpage+column-1) {
X pageoff = 0;
X cpage = i;
X *selectname = 0;
X dispdir(0);
X if (VSHMODE == SELECTMODE)
X dircmd(j+'a');
X }
X else {
X f = (cpage+pageoff > i);
X while (cpage+pageoff != i)
X dircmd(f ? ESLF : TABCMD);
X f = (selectcmd < j);
X if (VSHMODE == SELECTMODE)
X while (*selectname == 0 || selectcmd != j)
X dircmd(f ? ESDN : ESUP);
X }
X return NOREPLOT;
X}
All work and no play makes Jack a dull boy
echo src/grep.c
sed 's/^X//' > src/grep.c << 'All work and no play makes Jack a dull boy'
X#include "hd.h"
X#include "strings.h"
X#include "command.h"
X
X/* Interface to grep */
X
X#define GBUFLEN 200
X#define LIM1 (gbuf + 100)
X
X#define QUOTE '\''
X#define BSLASH '\\'
X
X#define GSTR1 " -n '"
X#define GSTR2 "' /dev/null "
X
X#define CPSET {cp = gbuf + strlen (gbuf);}
X
X#define GREPLEAVE {tty_pop (); clearmsg (0); return NOREPLOT;}
X
X/* User is asked to supply patterns and file names. Grep is then
X run with its output directed to .grepout. If the user changes his
X mind, and leaves without running grep, NOREPLOT is returned.
X Else REPLOT | CMD_SG is returned.
X*/
Xgrep ()
X{
X register char *cp, *clim; register ch;
X char gbuf [GBUFLEN];
X char inline [STRMAX]; int inlength; register char *incp;
X
X FILE *sstream;
X extern FILE *showopen ();
X
X int saveout;
X
X extern char wdname [];
X
X tty_push (COOKEDMODE);
X strcpy (gbuf, GREP); strcat (gbuf, GSTR1);
X clearmsg (2); putmsg("Grep pattern:");
X printf(" ");
X CPSET; clim = LIM1;
X
X inlength = getline (inline); incp = inline;
X if (inlength == 0) GREPLEAVE;
X
X while ((ch = *incp++) && cp < clim)
X {
X if (ch == QUOTE)
X {
X *cp++ = QUOTE; *cp++ = BSLASH;
X *cp++ = QUOTE; *cp++ = QUOTE;
X }
X else *cp++ = ch;
X }
X *cp=0;
X strcat (gbuf, GSTR2);
X atxy (20 + inlength, window - 1);
X hilite ("%sGrep files:", (*SO ? "" : "-- "));
X printf(" ");
X
X CPSET;
X
X ch = inlength;
X inlength = xgetline (stdin, cp, GBUFLEN - strlen (gbuf));
X if (inlength == 0) GREPLEAVE;
X if (strcmp(cp, "$") == 0) {
X if (VSHMODE == SELECTMODE && selecttype == DIRCMD
X && *selectname) {
X strcpy(cp, selectname);
X atxy(ch + 32 + (*SO ? 0 : 3), window - 1);
X printf("%s\r\n", cp);
X }
X else {
X hilite("Nothing selected");
X GREPLEAVE;
X }
X }
X
X /* Now run the command in gbuf */
X
X sstream = showopen ("w", GREPMODE);
X if (sstream == NULL) GREPLEAVE;
X
X hilite ("Searching");
X
X saveout = dup (outfile); /* Set up files */
X close (outfile); dup (fileno (sstream)); fclose (sstream);
X
X printf ("%s is search directory\r\n", wdname);
X mysystem (gbuf);
X close (outfile); dup (saveout); close (saveout);
X
X
X tty_pop (); return CMD_SG | REPLOT;
X}
All work and no play makes Jack a dull boy
exit
More information about the Comp.sources.unix
mailing list