dan@rna.UUCP (Dan Ts'o) (06/27/85)
# 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