[net.sources] VSH source 1 of 6

dan@rna.UUCP (Dan Ts'o) (06/27/85)

# Here are the sources to VSH, a visual shell, which has been much improved
#	since its original posting a couple of years ago...
#
#
#					Cheers,
#					Dan Ts'o
#					Dept. Neurobiology
#					Rockefeller Univ.
#					1230 York Ave.
#					NY, NY 10021
#					212-570-7671
#					...cmcl2!rna!dan
mkdir src
mkdir doc
echo CHANGES
sed 's/^X//' > CHANGES << 'All work and no play makes Jack a dull boy'
XVERSION 4.2
X- Added more portable VT100 arrowkey kludge using alarm(), see strings.c.
X- Added kludge to handle VT100 arrow keys. It needs an empty() routine to
Xcheck if there is any tty input. It would be better coded with select() for
X4.2BSD and MINTIME/termio for System V, but it would look ugly and non-portable.
X- Added kludge in page.c to handle long lines more gracefully. Not perfect but
Xacceptable.
X- Added facility for defined commands to prompt for arguments. Arguments of the
Xform ??message cause the message to be printed and the entered strings to be
Xused as the argument.
XVERSION 4.1
X- Added parameter enterpath, a list of directories to be searched when entering
Xa file via the keyboard VSH file command.
X- Added an (incomplete, not totally satisfactory) implementation of a reversing
Xmore-like pager. Many more more features are available including forward and
Xreverse string searching and reviewing previous lines and an editor escape.
XThe implementation is via a VSH internal ring buffer which keeps the last
Xmoresize characters. Moresize is a new VSH parameter which determines the
Xmaximum number of characters to keep. This, of course, limits the ability to
Xreverse the pager. It seemed like an efficient way to go, but the code has grown
Xto the point where it may have been better to implement the whole thing with
Xa temporary file - probably somewhat more straightforward, but maybe slower
Xand would require copying all output into a temporary file, not great for
Xpipes of possibly unlimited number of bytes. Anyways, there is a command to
Xseek to the beginning of a regular file, so the buffering limitation is not
Xdisasterous.
X  The other major deficit of the VSH pager is that is makes no attempt to
Xcorrect for lines greater in length than the number of columns on the terminal.
XNaturally this is not easy and kinda messy. Maybe someday in the near future...
X  A compile-time define, MBUFSTACK, if defined in hd.h, puts the more buffer in
Xthe stack segment instead of malloc()'ing it. This is probably best for nonI&D
XPDP-11's and the like, but the VSH parameter moresize is then ignored.
X  Simple cosmetic code for job control has been added. It simply tries to
Xredraw the screen (by stuffing a ^L) upon restart.
XVERSION 4.0
X- Added multicolumn directory displays to better use available screen space.
X	Commands were added to move the select pointer around the display
X	directory page much like in a screen editor. Both VI-like and EMACS-
X	like commands, such as hjkl, and ^F, ^B, ^P, ^N, ^A, ^E, ^V.
X	A new parameter 'window' controls how many lines of the screen to
X	dedicate to the directory display and another new parameter 'column'
X	controls how many columns of files to display.
X- If 'window' is less than the full screen, the remaining lines, if greater
Xthan about 5, is used as a paging and execute scroll window. That is all
Xtext paging and commands that VSH exec's output in this window.
X- VSH uses many more TERMCAP capabilities like CD, CS, CO, LI. I have added
Xthree non-standard TERMCAP capabilities, none of which are really necessary
Xbut are cosmetic. They are mostly found on ANSI-like terminals like the VT100.
XThey are CB (Clear from Beginning) which clears the screen from home to the
Xcurrent cursor position (as opposed to CD), BO (Blink On), BE (Blink End).
XIn addition, VSH uses CS (Change Scroll region) to implement the execute
Xwindow. If a terminal doesn't have it, the display won't be as pretty.
X- Bug: While we're on the subject of TERMCAP, VSH should really modify the
XTERMCAP variable in the environment during the exec in the separate window
Xto reflect the few number of lines (LI). I may do this some day but its messy
Xand not fool proof. This issue I believe is common to many windowing systems
Xand should be solved in a more general way. TERMCAP is too static and is
Xshowing its age.
X- Bug: My experience is that VI doesn't initialize the terminal properly,
Xespecially with respect to changes in CS. Thus VI exec'd from a VSH execute
Xwindow, goofs up scrolling. This can be fixed either by typing ^D, ^U in
XVI, which seems to cause VI to reset CS, or by including a CS reset in the
XTERMCAP entry for CL, which clears the whole screen. Changing CL may screw
Xup other software, but I doubt it - any program which clears the whole screen
Xcan't be interested in maintaining an alternate scrolling window (Murphy?)
X- Bug: After an L (longlist) command, the next motion command should redraw
Xthe display.
X- Bug: For 4.2BSD we should make more use of vfork(), although maybe 4.3BSD
Xwill eliminate vfork().
X- pexec's now page the standard error port as well as stdout.
X- NDIR, new 4.2BSD directory scheme is now conditionally compiled in.
X- commands which are invoked expecting a selected argument now can prompt for
Xarguments if they are missing. The new parameter 'noargprompt' if set,
Xinhibits this prompting. Thus a command defined as
X	vi $
Xwill VI a selected file, or if none, will prompt for a file.
X- The new parameter VImotion if set, allows hjkl to be used as page motion
Xcommands, but they lose their interpretation as direct select commands.
X- The command ' compensates VImotion by allowing the confirmation of a select
X(that is "entering" the file) instead of hitting the direct select key
Xa-z twice (which would be impossible if hjkl are preempted).
X- VSH now understands a few different archive types, PDP-11, Berkeley, 5.0
Xsee classify.c
X- Added code to track down symbolic links, like 4.2BSD ls -l.
X- Added MAIL parameter and code to report new mail.
X
XNotes:
X- VSH should really allow multiple selects, like diff $ $ to compare two
Xselected files, or cp $$ to copy N files somewhere. Maybe someday.
X- VSH should really be a mode within a regular shell, like the C-shell or
Xthe Bourne shell. That way shell commands can have a history, etc. This
Xcould also be implemented via pseudo-ttys to a shell constructed by VSH.
XPersonally, I'd rather spend the time<>money on a BLIT.
X- help menus are implemented crudely (only limited space, only upon VSH
Xentry), but I don't anticipate that this feature will be used much except
Xby novices.
X
XVERSION 3.0.1
X- Arranged default commands to my liking:
X	I is now T (typeout)
X	: is deleted (but definable)
X	% is chain to shell
X- Added more characters available for definition (u-z, @, _, etc.)
X- Removed u as a synonym to +
X- Added ^D as a synonym to + (ala VI, and if 'quitchar' is not ^D)
X- Added ^U as a synonym to - (ala VI)
X- Added ^L command to re-display the current page of files
X- Added 'quitchar' parameter to redefine command to quit (instead of always ^D)
X- The 'quitchar' must be struck twice to quit
X- Added 'pagechar' parameter to redefine a command as a synonym to '+',
X	default is ';'
X- Disabled SIGINT and SIGQUIT
X- Added a rename (mv) function to the create (C) command
X- Added code to recognize $PATH, $SHELL, $TERM, $HOME and $EDITOR parameters,
X	$PATH is used by exec
X- Also added code so exec can handle shell command files
X- Fixed bug where a 14-character filename at the end of a directory would print
X	garbage
X- In at.c, now uses TERMCAP parameter CE (Clear to End line) to erase lines
X	instead of printing spaces
X- Altered makefile to place many strings in text space
X- Added commands
X	chain		exec without fork
X	rexecute	re-exec last xecute
X- Added a 'find' command, which accepts a single character, and locates the
X	page in which filenames begin with that character (default 'find' is .)
X- Added a 'pexec' command, identical to exec except that the output is paged
X	by VSH and the input is re-directed to /dev/null
X- The xecute command can now take arguments instead of always prompting for
X	a shell command line. Useful for defining commands like "cc -c $ &",
X	or "(sleep 30; ps -l) &"
X- The xecute command now loops for shell commands, quitting on a blank line
X- Added code in getfname() to recognize ~username as username's login directory
X- Added argument to getfname() to print a message after the stty to COOKEDMODE,
X	which with some tty drivers would flush the output queue. Most calls
X	to getfname() were changed to use this argument
X- Added \ command to chdir to previous directory (undo last chdir)
X- Added code in remove.c and dir.c to attempt to display the previous page
X	viewed after a '\' or a remove
X- Changed code in remove.c and dir.c to allow loading of directories having
X	greater than 200 files, '0' command now goes to the last page rather
X	than the 10th page
X- Added parameter 'vshmode' to switch between 'enter' mode (standard VSH mode)
X	or 'select' mode...
X- Added 'select' mode, where user first selects a filename, and then a command
X	to execute on that filename
X- Any command which goes through getfname() can use a selected file as an
X	argument (e.g. Create:, From: )
X- Added code to exec and xecute to accept a selected filename as an argument
X- Added code to exec and xecute: if the shell command begins with ';', the ';'
X	is removed and the screen is immediately updated after the command
X	returns (rather than prompting for a <CR>)
X- Changed the options command: if it is executed with an argument, that
X	argument is used as a filename to dump the current options list in
X	.vshrc format and VSH does NOT exit. Old vsh, upon seeing an options
X	argument, would dump always to "vsh.out" and then exit
X- Added code in main.c to accept a "-" option to exec (chain to) the shell if
X	VSH can't find a CRT terminal. Useful for making VSH the top-level
X	shell. Also a "-f" option to force VSH to attempt to continue even if
X	it can't find a CRT terminal. Marginally useful for running VSH in
X	shell command files (e.g. vshrc.gen)
X- Added code to test if the editor parameter is VI, if it isn't, VSH does not
X	use the +## to jump to the ##th line, which is VI-specific
X- The fmake command now sends three bells if the make exitted with an error
X- The make commands can now be aborted with a 'q' at the options prompt
X- Ascii <ESC> is no longer an end-of-line character
X- The display now includes uid/username info
X- The longlist command (L) now includes ownership information
X- Arranged the page/display code to page text more to my liking
X	Page/display is now done in RAW mode, so that single keystrokes can
X	answer the More? prompt. However some tty drivers in RAW mode don't
X	honor the CRMOD to output a <CR> after a <LF>, so an extra <CR> is
X	outputted.
X- Fixed the code to handle cpio archives properly (had to change p_exec())
X- Added Huffman encoded file (ala pack/unpack) interpretation (does a pcat)
X- Added code to strip parity bit in getch(), in RAW mode this caused a few
X	problems
X- Added highlighting of the display via reverse video (see termcap SO, SE)
X- Added "entertext" parameter for setting command to perform when "entering"
X	a text file. The default is exec'ing $EDITOR, but "display" is also
X	specially recognized (calling the internal pager). Any other command
X	is exec'ed
X- Added "helpfile" parameter. If the file named by helpfile is present, it is
X	always printed in the file display. Mostly for novices. In a given
X	session, to shut it off, set helptext to "" (via O).
X- Fixed bug in file.c, in create(), which clobbered the first character of
X	a filename to be created in the root dir / via todotdot().
X
X- Note: I looked into adding tar file types, probably a little messy
X- Note undocumented feature:
X	O command can be left by typing "quit"
X- Note that VSH had several bugs, including a few in the usage of the mpages
X	constant (This version doesn't have a mpages or mfiles)
X- Note that VSH does not free() any malloc()'d strings used to define options.
X	This should probably be fixed, but I'm lazy and so far redefining
X	options is rare.
X- Note that VSH currently screws up on filesystems which are not mounted off
X	a root '/' directory entry (e.g. /usr/mnt).
X
XLOCAL specific changes
X- ttyn(2) call used by the V6 getenv() is replaced by the PWB logtty() which is
X	faster
X- main.c checks for the CRT stty() mode as part of its criterion for CRT
X	terminals
X- made the usually V6 changes, most notably related to stat()
All work and no play makes Jack a dull boy
echo NOTE
sed 's/^X//' > NOTE << 'All work and no play makes Jack a dull boy'
XFor PDP11's and similar machines:
XBecause of the granularity of memory pages on a PDP-11, it is advisable to
Xmonitor closely the size of vsh.
XThe shell command file 'asfix' attempts to place the initialized strings of
Xvsh in text space, and can be incorporated into the makefile to increase the
Xamount of pure code and data that is shared.
XHowever, it can happen that the text space may just cross a 4kword boundary
Xand because vsh should be loaded sharable, deprive the data area of almost
X4k words of data.
XSince vsh does not currently free memory allocated for option parameters,
Xit is possible for vsh to run out of memory.
XThus it may be reasonable to place some of the string data back in data space
Xjust to allow more space for the data segment.
XOne, of course, could always:
X	load vsh I&D
X	load vsh non-sharable
X	recode to free up option data
X	reclaim some of the stack segment
All work and no play makes Jack a dull boy
echo README
sed 's/^X//' > README << 'All work and no play makes Jack a dull boy'
X1/16/83:
X	For 4.2BSD: It should suffice to edit hd.h to
X		define V7TTY, NDIR, SYMLINK, VFORK
X		undefine PWBTTY, USGTTY, V6
X		Use Makefile.bsd
X	For 3.0, 5.0: I'm less able to say, but edit hd.h to
X		define USGTTY
X		undefine PWBTTY, V7TTY, V6, NDIR, SYMLINK, VFORK
X		also look in cmdini.c, classify.c
X		For VT100 arrowkeys, you may wish to write an empty() routine.
X	For 2.9BSD: Should define V7TTY, you may define SYMLINK if you
X		have them. Define NDIR only if you have the 4.2BSD support
X		routines as well (e.g. scandir()). 
X		Use Makefile.bsd
X	For VENIX-11: define VENIX, V7TTY
X		Use Makefile.venix
X	For PDP-11's:
X		You may wish to define MBUFSTACK.
X
X	Then look at the TERMCAP-relevant stuff.
X
XNotes on this version of VSH.
X
X	This version was most recently run on a PWB1.2 and a 4.2BSD system
Xsystem. It should not be difficult to retrofit it to other UNIX's.
XThe things to watch for are:
X
X	- hd.h is the main file to configure.
X
X	- special PWB1.2 subroutines logdir(), logtty(), logname(), which
X	are fast ways to get at the HOME, controlling tty, and LOGNAME.
X	It's a replacement for getenv("HOME") which doesn't work that
X	well on V6 systems. Code like this is bracketed by
X		#ifdef V6
X	- You will need to pick code appropriate for your tty driver. See tty.c
X	- NDIR, 4.2BSD directories and SYMLINK, 4.2BSD symbolic links
X	- Check out stuff in the TERMCAP directory. If you can, add CS, CB,
X	BO, and BE capabilities to /etc/termcap. A sample VT100 entry is given.
X	Also read the discussion in CHANGES.
X	- The makefiles reference a LOCALLIB. This is usually a system dependant
X	library contain things that the system libraries are missing, like the
X	str*() library.
X	- VSH needed to know some magic numbers to type a.out's, archives,
X	packed files, cpio archives, etc. These are found in classify.c.
X	Check them out.
X	- VSH will write out a (boring) log entry every time it exits in a file
X	called /usr/adm/vsh.log, if it exists.
X	- If you're missing the complete str*() string library, you may find
X	what you need in strlib.tar
X	- PDP-11's: VSH will work fine loaded nonI&D, but the largest
X	directories will exhaust memory. Loading VSH nonshared will help. A
X	number of data structures could also be moved to the stack segment.
X	Sorry, VSH is larger now than before.
X
X	The *help files found in DOC belong in /usr/lib/vsh
X
X	The builtin parameters in cmdini.c must be correct before compiling.
XFirst, the "argv" variables must reference the proper programs and files.
XThen the parmtab must be modified to reference other appropriate programs and
Xfiles.
X
All work and no play makes Jack a dull boy
echo termcap/
mkdir termcap
echo termcap/README
sed 's/^X//' > termcap/README << 'All work and no play makes Jack a dull boy'
X	A sample termcap entry with CS, CB, BO, BE.
X
XCS	Change Scroll region
XCB	Clear to Beginning
XBO	Blink On
XBE	Blink End
X
X	CB, BO, BE are non-standard (at least they are not documented,
Xbut then neither is BL or padding for SO and SE), and are not necessary
Xbut are cosmetic.
X	Note also that a CS reset has been included in CL. This change is
Xhighly recommended.
X	See the discussion in CHANGES.
All work and no play makes Jack a dull boy
echo termcap/termcap
sed 's/^X//' > termcap/termcap << 'All work and no play makes Jack a dull boy'
Xd0|vt100|vt100-am|dec vt100:\
X	:cr=^M:do=^J:nl=^J:bl=^G:co#80:li#24:cl=50\E[1;24r\E[;H\E[2J:\
X	:le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:\
X	:ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\
X	:md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:is=\E[1;24r\E[24;1H:\
X	:rf=/usr/lib/tabset/vt100:\
X	:rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\
X	:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
X	:ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:ta=^I:pt:sr=5\EM:vt#3:xn:\
X	:sc=\E7:rc=\E8:cs=\E[%i%d;%dr:cb=50\E[1J:bo=2\E[5m:be=2\E[m:
All work and no play makes Jack a dull boy
echo misc/
mkdir misc
echo misc/ttyn.c
sed 's/^X//' > misc/ttyn.c << 'All work and no play makes Jack a dull boy'
X/*
X * Replace ttyn() with logtty() call (faster).
X */
Xttyn(fd)
X{
X	char *logtty();
X
X	if (fd != 2)
X		write(2, "ttyn() Botch\r\n", 13);
X	return(*logtty());
X}
X
All work and no play makes Jack a dull boy
echo strlib/
mkdir strlib
echo strlib/strcat.c
sed 's/^X//' > strlib/strcat.c << 'All work and no play makes Jack a dull boy'
X/*	@(#)strcat.c	1.2	*/
X/*LINTLIBRARY*/
X/*
X * Concatenate s2 on the end of s1.  S1's space must be large enough.
X * Return s1.
X */
X
Xchar *
Xstrcat(s1, s2)
Xregister char *s1, *s2;
X{
X	register char *os1;
X
X	os1 = s1;
X	while(*s1++)
X		;
X	--s1;
X	while(*s1++ = *s2++)
X		;
X	return(os1);
X}
All work and no play makes Jack a dull boy
echo strlib/strchr.c
sed 's/^X//' > strlib/strchr.c << 'All work and no play makes Jack a dull boy'
X/*	@(#)strchr.c	1.2	*/
X/*LINTLIBRARY*/
X/*
X * Return the ptr in sp at which the character c appears;
X * NULL if not found
X */
X
X#define	NULL	0
X
Xchar *
Xstrchr(sp, c)
Xregister char *sp, c;
X{
X	do {
X		if(*sp == c)
X			return(sp);
X	} while(*sp++);
X	return(NULL);
X}
All work and no play makes Jack a dull boy
echo strlib/strcmp.c
sed 's/^X//' > strlib/strcmp.c << 'All work and no play makes Jack a dull boy'
X/*LINTLIBRARY*/
X/*
X * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
X */
X
Xint
Xstrcmp(s1, s2)
Xregister char *s1, *s2;
X{
X
X	if(s1 == s2)
X		return(0);
X	while(*s1 == *s2++)
X		if(*s1++ == '\0')
X			return(0);
X	return(*s1 - *--s2);
X}
All work and no play makes Jack a dull boy
echo strlib/strcpy.c
sed 's/^X//' > strlib/strcpy.c << 'All work and no play makes Jack a dull boy'
X/*	@(#)strcpy.c	1.2	*/
X/*LINTLIBRARY*/
X/*
X * Copy string s2 to s1.  s1 must be large enough.
X * return s1
X */
X
Xchar *
Xstrcpy(s1, s2)
Xregister char *s1, *s2;
X{
X	register char *os1;
X
X	os1 = s1;
X	while(*s1++ = *s2++)
X		;
X	return(os1);
X}
All work and no play makes Jack a dull boy
echo strlib/strcspn.c
sed 's/^X//' > strlib/strcspn.c << 'All work and no play makes Jack a dull boy'
X/*	@(#)strcspn.c	1.1	*/
X/*LINTLIBRARY*/
X/*
X * Return the number of characters in the maximum leading segment
X * of string which consists solely of characters NOT from charset.
X */
Xint
Xstrcspn(string, charset)
Xchar	*string;
Xregister char	*charset;
X{
X	register char *p, *q;
X
X	for(q=string; *q != '\0'; ++q) {
X		for(p=charset; *p != '\0' && *p != *q; ++p)
X			;
X		if(*p != '\0')
X			break;
X	}
X	return(q-string);
X}
All work and no play makes Jack a dull boy
echo strlib/strlen.c
sed 's/^X//' > strlib/strlen.c << 'All work and no play makes Jack a dull boy'
X/*	@(#)strlen.c	1.2	*/
X/*LINTLIBRARY*/
X/*
X * Returns the number of
X * non-NULL bytes in string argument.
X */
X
Xint
Xstrlen(s)
Xregister char *s;
X{
X	register n;
X
X	n = 0;
X	while(*s++)
X		n++;
X	return(n);
X}
All work and no play makes Jack a dull boy
echo strlib/strncat.c
sed 's/^X//' > strlib/strncat.c << 'All work and no play makes Jack a dull boy'
X/*	@(#)strncat.c	1.2	*/
X/*LINTLIBRARY*/
X/*
X * Concatenate s2 on the end of s1.  S1's space must be large enough.
X * At most n characters are moved.
X * Return s1.
X */
X
Xchar *
Xstrncat(s1, s2, n)
Xregister char *s1, *s2;
Xregister n;
X{
X	register char *os1;
X
X	os1 = s1;
X	while(*s1++)
X		;
X	--s1;
X	while(*s1++ = *s2++)
X		if(--n < 0) {
X			*--s1 = '\0';
X			break;
X		}
X	return(os1);
X}
All work and no play makes Jack a dull boy
echo strlib/strncmp.c
sed 's/^X//' > strlib/strncmp.c << 'All work and no play makes Jack a dull boy'
X/*LINTLIBRARY*/
X/*
X * Compare strings (at most n bytes)
X *	returns: s1>s2; >0  s1==s2; 0  s1<s2; <0
X */
X
Xint
Xstrncmp(s1, s2, n)
Xregister char *s1, *s2;
Xregister n;
X{
X	if(s1 == s2)
X		return(0);
X	while(--n >= 0 && *s1 == *s2++)
X		if(*s1++ == '\0')
X			return(0);
X	return((n < 0)? 0: (*s1 - *--s2));
X}
All work and no play makes Jack a dull boy
echo strlib/strncpy.c
sed 's/^X//' > strlib/strncpy.c << 'All work and no play makes Jack a dull boy'
X/*	@(#)strncpy.c	1.2	*/
X/*LINTLIBRARY*/
X/*
X * Copy s2 to s1, truncating or null-padding to always copy n bytes
X * return s1
X */
X
Xchar *
Xstrncpy(s1, s2, n)
Xregister char *s1, *s2;
Xint	n;
X{
X	register i;
X	register char *os1;
X
X	os1 = s1;
X	for(i = 0; i < n; i++)
X		if((*s1++ = *s2++) == '\0') {
X			while(++i < n)
X				*s1++ = '\0';
X			return(os1);
X		}
X	return(os1);
X}
All work and no play makes Jack a dull boy
echo strlib/strpbrk.c
sed 's/^X//' > strlib/strpbrk.c << 'All work and no play makes Jack a dull boy'
X/*	@(#)strpbrk.c	1.1	*/
X/*LINTLIBRARY*/
X/*
X * Return ptr to first occurance of any character from `brkset'
X * in the character string `string'; NULL if none exists.
X */
X
X#define	NULL	(char *) 0
X
Xchar *
Xstrpbrk(string, brkset)
Xregister char *string, *brkset;
X{
X	register char *p;
X
X	do {
X		for(p=brkset; *p != '\0' && *p != *string; ++p)
X			;
X		if(*p != '\0')
X			return(string);
X	}
X	while(*string++);
X	return(NULL);
X}
All work and no play makes Jack a dull boy
echo strlib/strrchr.c
sed 's/^X//' > strlib/strrchr.c << 'All work and no play makes Jack a dull boy'
X/*	@(#)strrchr.c	1.2	*/
X/*LINTLIBRARY*/
X/*
X * Return the ptr in sp at which the character c last
X * appears; NULL if not found
X*/
X
X#define NULL 0
X
Xchar *
Xstrrchr(sp, c)
Xregister char *sp, c;
X{
X	register char *r;
X
X	r = NULL;
X	do {
X		if(*sp == c)
X			r = sp;
X	} while(*sp++);
X	return(r);
X}
All work and no play makes Jack a dull boy
echo strlib/strspn.c
sed 's/^X//' > strlib/strspn.c << 'All work and no play makes Jack a dull boy'
X/*	@(#)strspn.c	1.1	*/
X/*LINTLIBRARY*/
X/*
X * Return the number of characters in the maximum leading segment
X * of string which consists solely of characters from charset.
X */
Xint
Xstrspn(string, charset)
Xchar	*string;
Xregister char	*charset;
X{
X	register char *p, *q;
X
X	for(q=string; *q != '\0'; ++q) {
X		for(p=charset; *p != '\0' && *p != *q; ++p)
X			;
X		if(*p == '\0')
X			break;
X	}
X	return(q-string);
X}
All work and no play makes Jack a dull boy
echo strlib/strtok.c
sed 's/^X//' > strlib/strtok.c << 'All work and no play makes Jack a dull boy'
X/*	@(#)strtok.c	1.2	*/
X/*LINTLIBRARY*/
X/*
X * uses strpbrk and strspn to break string into tokens on
X * sequentially subsequent calls.  returns NULL when no
X * non-separator characters remain.
X * `subsequent' calls are calls with first argument NULL.
X */
X
X#define	NULL	(char*)0
X
Xextern int strspn();
Xextern char *strpbrk();
X
Xchar *
Xstrtok(string, sepset)
Xchar	*string, *sepset;
X{
X	register char	*p, *q, *r;
X	static char	*savept;
X
X	/*first or subsequent call*/
X	p = (string == NULL)? savept: string;
X
X	if(p == 0)		/* return if no tokens remaining */
X		return(NULL);
X
X	q = p + strspn(p, sepset);	/* skip leading separators */
X
X	if(*q == '\0')		/* return if no tokens remaining */
X		return(NULL);
X
X	if((r = strpbrk(q, sepset)) == NULL)	/* move past token */
X		savept = 0;	/* indicate this is last token */
X	else {
X		*r = '\0';
X		savept = ++r;
X	}
X	return(q);
X}
All work and no play makes Jack a dull boy
echo strlib/strtol.c
sed 's/^X//' > strlib/strtol.c << 'All work and no play makes Jack a dull boy'
X/*LINTLIBRARY*/
X#include <ctype.h>
X#define DIGIT(x) (isdigit(x)? ((x)-'0'): (10+tolower(x)-'a'))
X#define MBASE 36
X
Xlong
Xstrtol(str, ptr, base)
Xchar *str, **ptr;
Xint base;
X{
X	long val;
X	int xx, sign;
X
X	val = 0L;
X	sign = 1;
X	if(base < 0 || base > MBASE)
X		goto OUT;
X	while(isspace(*str))
X		++str;
X	if(*str == '-') {
X		++str;
X		sign = -1;
X	} else if(*str == '+')
X		++str;
X	if(base == 0) {
X		if(*str == '0') {
X			++str;
X			if(*str == 'x' || *str == 'X') {
X				++str;
X				base = 16;
X			} else
X				base = 8;
X		} else
X			base = 10;
X	} else if(base == 16)
X		if(str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
X			str += 2;
X	/*
X	 * for any base > 10, the digits incrementally following
X	 *	9 are assumed to be "abc...z" or "ABC...Z"
X	 */
X	while(isalnum(*str) && (xx=DIGIT(*str)) < base) {
X		/* accumulate neg avoids surprises near maxint */
X		val = base*val - xx;
X		++str;
X	}
XOUT:
X	if(ptr != (char**)0)
X		*ptr = str;
X	return(sign*(-val));
X}
All work and no play makes Jack a dull boy
echo bugs/
mkdir bugs
echo bugs/jobcontrol.fix
sed 's/^X//' > bugs/jobcontrol.fix << 'All work and no play makes Jack a dull boy'
X*** main.c	Tue Jul 17 01:19:12 1984
X--- main.c.old	Sun Jul 15 20:32:15 1984
X***************
X*** 6,18
X  #include <sys/sgtty.h>
X  #endif
X  
X- #ifdef	STOPABLE
X- #define	sigmask(sig)	(1 << ((sig) - 1))
X- #define	sigunblock(mask) sigsetmask(sigblock(0) & ~(mask))
X- int suspend();
X- #include <sgtty.h>
X- #endif
X- 
X  /* Extract data about environment */
X  #define ENV_COUNT	6
X  
X
X--- 6,11 -----
X  #include <sys/sgtty.h>
X  #endif
X  
X  /* Extract data about environment */
X  #define ENV_COUNT	6
X  
X***************
X*** 134,142
X      wdfile = -1;
X      if (curdir () || enterdir (DOT) == NOREPLOT)
X  	leave ();
X- #ifdef	STOPABLE
X-     signal(SIGTSTP, suspend);
X- #endif
X      tty_push (RAWMODE);
X  
X  	/* Read in helpfile once */
X
X--- 127,132 -----
X      wdfile = -1;
X      if (curdir () || enterdir (DOT) == NOREPLOT)
X  	leave ();
X      tty_push (RAWMODE);
X  
X  	/* Read in helpfile once */
X***************
X*** 165,199
X  	setcolumn();
X      process ();
X  }
X- 
X- #ifdef	STOPABLE
X- suspend(signo)
X- int signo;
X- {
X- 	int putch();
X- 	
X- 	tty_push(COOKEDMODE);
X- 	/*
X- 	 * This is debatable: should we give back a full screen
X- 	 *	or just the execute window ?
X- 	 */
X- 	if (CS && ewindow) {
X- 		tputs(tgoto(CS, LI-1, 0), 0, putch);
X- 		atxy(1, LI);
X- 	}
X- #ifdef	SIGVTALRM			/* Kludge to detect 4.2BSD signal */
X- 	/* stop ourselves */
X- 	sigunblock(sigmask(signo));
X- 	signal(signo, SIG_DFL);
X- 	kill(getpid(), signo);
X- 	sigblock(sigmask(signo));
X- #else
X- 	kill(getpid(), signo);
X- #endif
X- 	signal(signo, suspend);
X- 	printf("Vsh restarted.\r");
X- 	fflush(stdout);
X- 	tty_pop();
X- 	ioctl(0, TIOCSTI, "\014");	/* Fake an input of ^L */
X- }
X- #endif
X
X--- 155,157 -----
X  	setcolumn();
X      process ();
X  }
All work and no play makes Jack a dull boy
echo bugs/termcap.fix
sed 's/^X//' > bugs/termcap.fix << 'All work and no play makes Jack a dull boy'
X*** ../src/hd.h	Sun Jul 15 19:43:03 1984
X--- /usr/src/local/vsh/hd.h	Sat Feb 25 03:28:49 1984
X***************
X*** 171,174
X  extern char *BO, *BE;
X  extern char *SR, *CD;
X  extern int AM;
X- extern char *TI, *TE;
X
X--- 171,173 -----
X  extern char *BO, *BE;
X  extern char *SR, *CD;
X  extern int AM;
X*** ../src/curses.c	Sun Jul 15 20:04:27 1984
X--- /usr/src/local/vsh/curses.c	Mon Apr  9 18:03:42 1984
X***************
X*** 10,16
X  char *CS, *CB;
X  char *BE, *BO;
X  char *SR, *CD;
X- char *TI, *TE;
X  int AM;
X  
X  char tspace [512], *atspace;
X
X--- 10,15 -----
X  char *CS, *CB;
X  char *BE, *BO;
X  char *SR, *CD;
X  int AM;
X  
X  char tspace [512], *atspace;
X***************
X*** 55,62
X      SR = tgetstr ("sr", &atspace);
X      CD = tgetstr ("cd", &atspace);
X      AM = tgetflag ("am");
X-     TI = tgetstr ("ti", &atspace);
X-     TE = tgetstr ("te", &atspace);
X  
X      if (SO == CNULL)
X  	SO = "";
X
X--- 54,59 -----
X      SR = tgetstr ("sr", &atspace);
X      CD = tgetstr ("cd", &atspace);
X      AM = tgetflag ("am");
X  
X      if (SO == CNULL)
X  	SO = "";
X***************
X*** 135,142
X  		ewinf = 1;
X  	}
X  	atxy(1, LI);
X- 	if (TE)
X- 		tputs(TE, 0, putch);
X  	unbufout();
X  	return ewinf;
X  }
X
X--- 132,137 -----
X  		ewinf = 1;
X  	}
X  	atxy(1, LI);
X  	unbufout();
X  	return ewinf;
X  }
X***************
X*** 146,153
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
X--- 141,146 -----
X  	if (!ewinf)
X  		return;
X  	bufout();
X  	if (CS)
X  		tputs(tgoto(CS, window-1, 0), 0, putch);
X  	atxy(1, window-1);
X*** ../src/account.c	Sun Jul 15 20:05:24 1984
X--- /usr/src/local/vsh/account.c	Thu Jan 26 21:33:41 1984
X***************
X*** 42,49
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  }
X
X--- 43,48 -----
X      window = LI;
X      vwin();		/* reset tty scrolling */
X      atxy(1, LI);
X      goout ();
X      exit (0);
X  }
X*** ../src/account.c	Sun Jul 15 20:15:15 1984
X--- /usr/src/local/vsh/account.c	Thu Jan 26 21:33:41 1984
X***************
X*** 37,44
X  
X  leave () 
X  {			/* exit after resetting tty */
X-     int putch();
X- 
X      tty_cooked ();
X      ewin();
X      window = LI;
X
X--- 38,43 -----
X  
X  leave () 
X  {			/* exit after resetting tty */
X      tty_cooked ();
X      ewin();
X      window = LI;
X***************
X*** 44,51
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  }
X
X--- 43,48 -----
X      window = LI;
X      vwin();		/* reset tty scrolling */
X      atxy(1, LI);
X      goout ();
X      exit (0);
X  }
All work and no play makes Jack a dull boy
echo bugs/wyse.fix
sed 's/^X//' > bugs/wyse.fix << 'All work and no play makes Jack a dull boy'
XFrom varian!david Thu Jan 10 07:47:23 1985
XReceived: by rna.UUCP (4.12/4.7)
X	id AA26022; Thu, 10 Jan 85 07:47:18 est
XDate: Thu, 10 Jan 85 07:47:18 est
XFrom: varian!david
XMessage-Id: <8501101247.AA26022@rna.UUCP>
XTo: rna!dan
XSubject: vsh
XCc: david
XStatus: RO
X
XI picked up vsh.tar from /usr/spool/uucppublic without problem.  I
Xcompiled it on our pdp11 (11/70, 2.8bsd) without problem and it
Xseems to be running beautifully -- a very nice job.
X
XMy main complaint at the moment is the extensive use of standout mode;
Xon my Wyse 50, reverse video is just too bright, and the magic cookie
Xglitch causes some fields to be off.  I notice that you do not use the
XSG field of termcap (# of spaces occupied by attributes).  Currently I'm
Xrunning with standout mode set to half-intensity (called protect mode in
XTeleVideo manuals), which does not take up a space and is less obnoxious.
XI haven't figured out whether I want to go through the code and reduce the
Xnumber of calls to hilite(), or arrange it so everyone uses half-intensity
Xinstead of reverse video for highlighting.  I don't think I want to change
XSO in /etc/termcap, as a lot of folks are used to seeing highlighted error
Xmessages from vi, etc.
X
XMy current plan of implementation is to use 2 more fields in termcap
X(MH & ME -- I understand these are already used by ul and other things
Xin 4.2bsd though they're not in the manual page; they've been mentioned
Xon the net) for start and end half-intensity; if they exist, then they
Xwill be used in place of SO & SE.   Does this sound like a reasonable
Xapproach?  Do you have any other ideas or suggestions?
X
XAlso related to the non-use of SG, if I set BO & BE (blink on & off),
Xthen the column pointer gets displayed nicely, but does not get cleared
Xwhen the pointer is moved, because only a single blank is sent to
Xclear the pointer, when really 3 are needed (blink on, V, blink
Xoff).  This looks like a simple change in dircmd.c (plus misc other
Xplaces to set the SG variable).
X
XAnyway, thanks a lot.  I'll be sending you mods after things settle
Xdown.
X
X	David Brown	 (415) 945-2199
X	Varian Instruments 2700 Mitchell Dr.  Walnut Creek, Ca. 94598
X	{zehntel,amd,fortune,resonex}!varian!david
X
X
All work and no play makes Jack a dull boy
exit