[comp.sources.misc] v10i054: MSDOS Shell

istewart@datlog.co.uk (Ian Stewartson) (02/14/90)

Posting-number: Volume 10, Issue 54
Submitted-by: istewart@datlog.co.uk (Ian Stewartson)
Archive-name: sh_dos/part02

#!/bin/sh
# shar:	Shell Archiver  (v1.23)
#
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files.
#
#
# This is part 1 of a multipart archive                                    
# do not concatenate these parts, unpack them in order with /bin/sh        
#
#	The following text will create:
#	  Install
#	  MANIFEST
#	  Notes
#	  ReadMe
#	  sh.1
#	  include/Changes
#	  include/sys/dirent.h
#	  include/sys/proto.h
#	  include/dirent.h
#	  include/unistd.h
#	  include/ms_dio.h
#	  lib/ms_dio.c
#	  lib/director.c
#	  lib/popen.c
#	  lib/syserr.c
#	  lib/stdargv.c
#	  lib/pnmatch.c
#	  lib/getopt.c
#	  scripts/l
#	  scripts/extend.lst
#	  scripts/profile.sh
#	  shell/Makefile
#	  shell/sh1.c
#	  shell/sh2.c
#	  shell/sh3.c
#	  shell/sh4.c
#	  shell/sh5.c
#	  shell/sh6.c
#	  shell/sh7.c
#	  shell/sh8.c
#	  shell/sh9.c
#	  shell/sh10.c
#	  shell/sh0.asm
#	  shell/sh.h
#
if test -r s2_seq_.tmp
then echo "Must unpack archives in sequence!"
     next=`cat s2_seq_.tmp`; echo "Please unpack part $next next"
     exit 1; fi
for i in include include/sys lib scripts shell
do
echo "x - creating directory $i"
mkdir $i
done
echo "x - extracting Install (Text)"
sed 's/^X//' << 'SHAR_EOF' > Install &&
X MS-DOS Shell Version 1.4	INSTALL				January 1990
X
X MS-DOS SHELL - Copyright (c) 1990 Data Logic Limited and Charles Forsyth
X
X This code is based on (in part) the shell program written by Charles
X Forsyth and is subject to the following copyright restrictions:
X
X 1.  Redistribution and use in source and binary forms are permitted
X     provided that the above copyright notice is duplicated in the
X     source form and the copyright notice in file sh6.c is displayed
X     on entry to the program.
X
X 2.  The sources (or parts thereof) or objects generated from the
X     sources (or parts of sources) cannot be sold under any circumstances.
X
X    $Header: install 1.1 90/01/29 18:03:04 MS_user Exp $
X
X    $Log:	install $
X# Revision 1.1  90/01/29  18:03:04  MS_user
X# Initial revision
X# 
X________________________________________________________________________________
X
XTo rebuild and install the shell, you should follow the following the
Xsteps:
X
X1)  Load the include files in the include directory into the standard
X    location (\msc\include or equivalent).  Read CHANGES file for the
X    additional definitions which are required in the standard Microsoft
X    5 include files and edit them in to the appropriate files.
X
X    We have standardised our MSDOS and Unix include files such that
X    the same include file exists our Unix system and MSDOS systems.
X    This makes porting a lot easier.  If you don't want to edit the
X    standard include files, you will have to generate an new include
X    file for the shell and include it as the first include in all the
X    C sources for the additional library functions and the Shell itself
X
X2)  Modify the library function open so that the O_NOINHERIT flag is
X    passed to MSDOS by the library.  This is not strictly necessary.
X    I did it using CodeView to see where the library function masks
X    the bottom three bits, noted the bytes around this location,
X    extracted the open function from the library, patched the mask
X    to be 0x83 instead of 0x03, and then replaced the function in the
X    library.
X
X3)  Compile the library files in the directory /lib in large model mode
X    and add the objects to your large model library
X
X    cl -c -AL -Olt *.c
X    <appropriate library commands>
X
X4)  Build the shell, either using make or
X
X    cl -c -AL -Olt *.c
X    masm /Ml sh0.asm
X    link sh0+sh1+sh2+sh3+sh4+sh5+sh6+sh7+sh8+sh9+sh10/noi, sh.exe;
X
X    Note that the order is important.  SH0.OBJ must be the first object
X    file in the load line.
X
X    Install the shell in its correct location.
X
X5)  Modify the scripts as appropriate for your installation and install
X    them in the correct directories.
X
X6)  Type "sh -0" and see what happens.
SHAR_EOF
chmod 0644 Install || echo "restore of Install fails"
set `wc -c Install`;Sum=$1
if test "$Sum" != "2694"
then echo original size 2694, current size $Sum;fi
echo "x - extracting MANIFEST (Text)"
sed 's/^X//' << 'SHAR_EOF' > MANIFEST &&
XInstall			| Installation instructions
XMANIFEST		| This list
XNotes			| Some addition notes
XReadMe			| The Release Readme
Xsh.1			| The Manual page in *roff format
Xinclude/Changes		| Changes to standard include files
Xinclude/dirent.h	| Directory (3) functions include
Xinclude/unistd.h	| unistd for MSDOS
Xinclude/ms_dio.h	| MSDOS raw disk/memory I/O include file
Xinclude/sys/dirent.h	| Second part of directory (3) functions include file
Xinclude/sys/proto.h	| Prototype definitions
Xlib/ms_dio.c		| MSDOS raw disk/memory I/O functions
Xlib/director.c		| POSIX directory (3) functions for MSDOS
Xlib/popen.c		| popen/pclose for MSDOS
Xlib/syserr.c		| Modified sys_errlist for MSDOS
Xlib/stdargv.c		| Replacement command list processing for programes
Xlib/pnmatch.c		| Pattern matching function
Xlib/getopt.c		| getopt function
Xscripts/l		| A sample shell script
Xscripts/extend.lst	| A sample extended command line processing list
Xscripts/profile.sh	| A sample start up shell script
Xshell/Makefile		| Shell - makefile 
Xshell/sh0.asm		| Shell - Swap functions
Xshell/sh1.c		| Shell - Main program and memory control functions
Xshell/sh2.c		| Shell - Parser functions
Xshell/sh3.c		| Shell - Parse tree processing functions
Xshell/sh4.c		| Shell - Word processing functions
Xshell/sh5.c		| Shell - Filename expansion functions
Xshell/sh6.c		| Shell - Global variables
Xshell/sh7.c		| Shell - Built-in functions
Xshell/sh8.c		| Shell - Unix I/O Emulation
Xshell/sh9.c		| Shell - History processing functions
Xshell/sh10.c		| Shell - Function print/save/delete functions
Xshell/sh.h		| Shell - Header file
SHAR_EOF
chmod 0644 MANIFEST || echo "restore of MANIFEST fails"
set `wc -c MANIFEST`;Sum=$1
if test "$Sum" != "1578"
then echo original size 1578, current size $Sum;fi
echo "x - extracting Notes (Text)"
sed 's/^X//' << 'SHAR_EOF' > Notes &&
XThe following addition points are noted about the Shell.
X
X1)  EMS 3.2 or above is required if expanded memory is to be used.
X
X2)  It has been tested on MS-DOS 3.3 and 4.0 and under OS/2 in the
X    DOS box.
X
X3)  Not all the addition library functions are required.  Some are
X    just included for your interest.  Their functionality is
X    briefly described below:
X
X	director.c (required)
X
X	MSDOS versions of the POSIX directory (3) functions (see
X	POSIX standards and Unix manual pages for further information).
X
X	getopt.c (required)
X
X	The getopt function
X
X	stdargv.c (required)
X
X	A replacement for the standard Microsoft library stdargv.obj.
X	This function tries to provide the wildcard expansion functionality
X	normally provided by Unix.  *, ?, [] and \ are supported.
X	Environment variables are expanded and the selection of files
X	across wildcard drive letters is supported (ie *:*.c will
X	expand to all the .c files in the current directory of all
X	drives).
X
X	pnmatch.c (required)
X
X	A pattern match function used by stdargv
X
X	ms_dio.c
X
X	A set of functions to allow you to do raw disk and memory
X	I/O.  The include file ms_dio has a set of macros to
X	change the normal library calls so that they go via this
X	package.
X
X	popen.c
X
X	A version of popen for MS-DOS
X
X	syserr.c
X
X	A modified version of the standard Microsoft error list.
SHAR_EOF
chmod 0644 Notes || echo "restore of Notes fails"
set `wc -c Notes`;Sum=$1
if test "$Sum" != "1334"
then echo original size 1334, current size $Sum;fi
echo "x - extracting ReadMe (Text)"
sed 's/^X//' << 'SHAR_EOF' > ReadMe &&
X MS-DOS Shell Version 1.4	README				January 1990
X
X MS-DOS SHELL - Copyright (c) 1990 Data Logic Limited and Charles Forsyth
X
X This code is based on (in part) the shell program written by Charles
X Forsyth and is subject to the following copyright restrictions:
X
X 1.  Redistribution and use in source and binary forms are permitted
X     provided that the above copyright notice is duplicated in the
X     source form and the copyright notice in file sh6.c is displayed
X     on entry to the program.
X
X 2.  The sources (or parts thereof) or objects generated from the
X     sources (or parts of sources) cannot be sold under any circumstances.
X
X    $Header: readme 1.1 90/01/25 13:43:20 MS_user Exp $
X
X    $Log:	readme $
X# Revision 1.1  90/01/25  13:43:20  MS_user
X# Initial revision
X# 
X________________________________________________________________________________
X
XThis is an implementation of the Unix Shell for MSDOS.  As far as
Xpossible it is compatible with the System V.3 program sh(1).  The
Xfollowing differences are noted:
X
X1)  Background or asynchronous commands are not supported
X
X2)  Certain internal commands which have no equivalent MSDOS supported
X    functionality support (ulimit, time etc) are not provided.
X
X3)  Command hashing and accounting are not supported.
X
X4)  The Shell uses all variables starting with a ~ (tilde) internally
X    and will not allow you to display them.  I don't think this is a
X    difference from the user's view, just internally.
X
X5)  8 bit character sets are not supported.
X
XThe following enhancements have been made for the MSDOS environment.
XThese enhancements are described in the appropriate section of the
Xmanual pages.
X
X1)  The Shell will swap itself out to one of the following:
X
X    - Expanded memory
X    - Extended memory
X    - Disk (this is the slowest)
X
X    The swapping is controlled by the shell internal command swap.  If
X    swapping is enabled, the shell only uses 3K of memory whilst a
X    child process is executing.
X
X    Note: Swapping to Extended memory is probably the most dangerous
X	  because there is no memory manager available for it.
X
X2)  History processing has been added.
X
X3)  Command line editing has been added.
X
X4)  The command line prompt can be programmed to display 'useful'
X    information.
X
X5)  The shell uses Unix format file names (ie slashes and not
X    backslashes) to delimit directories.  Some programs require certain
X    environment variables to be in MS-DOS format (using backslashes).
X    The msdos command allows these variables to be marked so that they
X    are set correctly when the environment for a program is set up.
X
X6)  Extended command line processing is supported using the parameter
X    @<filename> to a command.  Examples of this include the Microsoft
X    Linker and Librarian and of course the Shell itself.  A version of
X    stdargv.c which supports this format (and wildcards from a normal
X    command line) is included.
X
X7)  Wild cards on drives (ie echo *:*.c will echo all the C files in 
X    the current directories of each drive) are supported.
X
XIn order to rebuild this program, you need the DIRECTORY(3) functions
Xfor MSDOS (also included) and the version of open in your library must
Xpass the O_NOINHERIT bit on the MSDOS kernel.  The Microsoft C V5.1
Xlibrary does not pass this bit on to the MSDOS open System call.  I
Xfixed this using CodeView to find where the library function masks off
Xthe bottom 2 bits.  Extracted the object from the library and patched
Xmask from 0x03 to 0x83 in the object and reload into the library.  No
XProblem.
X
XYou can do want you like with this software as long as you don't sell
Xit or remove the Copyright notices in the sources or object.
X
XIf you have any problems or want to let me know about any enhancements
Xyou have made (which could be included in a new general release), you
Xcan contact me at
X
X    Data Logic Limited
X    Queens House
X    Greenhill Way
X    Harrow
X    Middlesex, HA1 1YR
X    UK.
X
X    Phone : +44 1 863 0383
X    E-Mail: istewart@datlog.co.uk or ukc!datlog!istewart
X
XNote:
X    Unix is a registered trademark of AT&T Bell Laboratories
X    Microsoft, MSDOS and CodeView are registered trademarks of Microsoft
X    Corporation
SHAR_EOF
chmod 0644 ReadMe || echo "restore of ReadMe fails"
set `wc -c ReadMe`;Sum=$1
if test "$Sum" != "4188"
then echo original size 4188, current size $Sum;fi
echo "x - extracting sh.1 (Text)"
sed 's/^X//' << 'SHAR_EOF' > sh.1 &&
X.\"
X.\" MS-DOS SHELL - Manual Page
X.\"
X.\" MS-DOS SHELL - Copyright (c) 1990 Data Logic Limited
X.\"
X.\" This code is subject to the following copyright restrictions:
X.\"
X.\" 1.  Redistribution and use in source and binary forms are permitted
X.\"     provided that the above copyright notice is duplicated in the
X.\"     source form and the copyright notice in file sh6.c is displayed
X.\"     on entry to the program.
X.\"
X.\" 2.  The sources (or parts thereof) or objects generated from the sources
X.\"     (or parts of sources) cannot be sold under any circumstances.
X.\"
X.\"    $Header: sh.1 1.1 90/01/24 14:17:00 MS_user Locked $
X.\"
X.\"    $Log:	sh.1 $
X.\"	Revision 1.1  90/01/24  14:17:00  MS_user
X.\"	Initial revision
X.\"	
X.\"
X.\"
X.ds OK [\|
X.ds CK \|]
X.TH SH 1L "Data Logic Limited" "MS-DOS Version 1.4"
X.SH NAME
Xsh, rsh - shell, the standard/restricted command programming language
X.SH SYNOPSIS
X\fBsh\fR [ \fB-acefhiknmrstuvx\fR ] [ args ]
X.br
X\fBrsh\fR [ \fB-acefhiknmrstuvx\fR ] [ args ]
X.SH DESCRIPTION
X\fISh\fR is a command programming language that executes commands read from a
Xterminal or a file.  \fIRsh\fR is a restricted version of the standard command
Xinterpreter \fIsh\fR; it is used to set up login names and execution
Xenvironments whose capabilities are more controlled than those of the standard
Xshell.  See \fIInvocation\fR below for the meaning of arguments to the shell.
X.SS Definitions
XA \fIblank\fR is a tab or a space.  A \fIname\fR is a sequence of letters,
Xdigits, or underscores beginning with a letter or underscore.  A \fIparameter\fR
Xis a name, a digit, or any of the characters \fB*\fR, \fB@\fR, \fB#\fR, \fB?\fR,
X\fB-\fR, \fB$\fR, and \fB!\fR.
X.SS Commands
XA \fIsimple-command\fR is a sequence of non-blank \fIwords\fR separated by
X\fIblanks\fR.  The first word specifies the name of the command to be executed.
XExcept as specified below, the remaining words are passed as arguments to the
Xinvoked command.  The command name is passed as argument 0 (see \fIexec\fR(2)).
XThe \fIvalue\fR of a simple-command is its exit status if it terminates
Xnormally, or (octal) 200+\fIstatus\fR if it terminates abnormally (see
X\fIsignal\fR(2) for a list of status values).
X.PP
XA \fIpipeline\fR is a sequence of one or more \fIcommands\fR separated by
X\fB\(bv\fR (or, for historical compatibility, by \fB^\fR).
XThe standard output of each command but the last is connected by a \fIpipe\fR(2)
Xto the standard input of the next command.  Each command is run as a separate
Xprocess; the shell waits for the last command to terminate.  The exit status
Xof a pipeline is the exit status of the last command.
X.PP
XA \fIlist\fR is a sequence of one or more pipelines separated by \fB;\fR,
X\fB&&\fR, or \fB\(bv\(bv\fR, and optionally terminated by \fB;\fR.  Of these
Xthree symbols, \fB;\fR has a lower precedence than that of \fB&&\fR and
X\fB\(bv\(bv\fR.  The symbols \fB&&\fR and \fB\(bv\(bv\fR also have equal
Xprecedence.  A semicolon (\fB;\fR) causes sequential execution of the
Xpreceding pipeline.  The symbol \fB&&\fR (\fB\(bv\(bv\fR) causes the
X\fIlist\fR following it to be executed only if the preceding pipeline returns
Xa zero (non-zero) exit status.  An arbitrary number of new-lines may appear in a
X\fIlist\fR, instead of semicolons, to delimit commands.
X.PP
XA \fIcommand\fR is either a simple-command or one of the following.  Unless
Xotherwise stated, the value returned by a command is that of the last
Xsimple-command executed in the command.
X.PP
X.PD 0
X.TP
X\fBfor \fIname\fR \*(OK \fBin \fIword\fR ... \*(CK \fBdo \fIlist \fBdone\fR
XEach time a \fBfor\fR command is executed, \fIname\fR is set to the next
X\fIword\fR taken from the \fBin\fR \fIword\fR list.  If \fBin\fI word\fR ...
Xis omitted, then the \fBfor\fR command executes the \fBdo\fR
X\fIlist\fR once for each positional parameter that is set (see \fIParameter
XSubstitution\fR below).  Execution ends when there are no more words in the
Xlist.
X.TP
X\fBcase \fIword \fBin\fR \*(OK \fIpattern\fR \*(OK \(br \
X\fIpattern\fR \*(CK ... \fB) \fIlist \fB;;\fR \*(CK ... \fBesac\fR
XA \fBcase\fR command executes the \fIlist\fR associated with the first
X\fIpattern\fR that matches \fIword\fR.  The form of the patterns is the same
Xas that used for file-name generation (see \fIFile Name Generation\fR) except
Xthat a slash, a leading dot, or a dot immediately following a slash need not
Xbe matched explicitly, and the match is case sensitive. 
X.TP
X\fBif \fIlist \fBthen \fIlist\fR \*(OK \fBelif \fIlist \fBthen \fIlist\fR \*(CK ... \*(OK \fBelse \fIlist\fR \*(CK \fBf\&i\fR
XThe \fIlist\fR following \fBif\fR is executed and, if it returns a zero exit
Xstatus, the \fIlist\fR following the first \fBthen\fR is executed.  Otherwise,
Xthe \fIlist\fR following \fBelif\fR is executed and, if its value is zero, the
X\fIlist\fR following the next \fBthen\fR is executed.  Failing that, the
X\fBelse \fIlist\fR is executed.  If no \fBelse \fIlist\fR or \fBthen \fIlist\fR
Xis executed, then the \fBif\fR command returns a zero exit status.
X.TP
X\fBwhile \fIlist \fBdo \fIlist \fBdone\fR
XA \fBwhile\fR command repeatedly executes the \fBwhile \fIlist\fR and, if
Xthe exit status of the last command in the list is zero, executes the
X\fBdo \fIlist\fR; otherwise the loop terminates.  If no commands in the
X\fBdo \fIlist\fR are executed, then the \fBwhile\fR command returns a zero
Xexit status; \fBuntil\fR may be used in place of \fBwhile\fR to negate the
Xloop termination test.
X.TP
X\fB(\fIlist\fB)\fR
X.br
XExecute \fIlist\fR in a sub-shell.  The shell creates a new environment in
Xwhich to execute the \fIlist\fR, but does not fork a sub-shell as a Unix
Xsystem would.  The original environment is restored on completion.
X.TP
X\fB{\fIlist\fB;}\fR
X.br
X\fIlist\fR is simply executed.
X.TP
X\fIname \fB() {\fIlist\fB;}\fR
XDefine a function which is referenced by \fIname\fR.  The body of the function
Xis the \fIlist\fR of commands between \fB{\fR and \fB}\fR.  Execution of
Xfunctions is described below (see \fIExecution\fR).
X.PD
X.PP
XThe following words are only recognized as the first word of a command and
Xwhen not quoted:
X.if t .RS
X.PP
X.B
X.if n if then else elif fi case esac for while until do done { }
X.if t if  then  else  elif  f\&i  case  esac  for  while  until  do  done  {  }
X.if t .RE
X.SS Comments
XA word beginning with \fB#\fR causes that word and all the following
Xcharacters up to a new-line to be ignored.
X.SS Command Substitution
XThe standard output from a command enclosed in a pair of grave accents
X(\fB\(ga\(ga\fR) may be used as part or all of a word; trailing new-lines
Xare removed.
X.SS Parameter Substitution
XThe character \fB$\fR is used to introduce substitutable \fIparameters\fR.
XThere are two types of parameters, positional and keyword.  If \fIparameter\fR
Xis a digit, it is a positional parameter.  Positional parameters may be
Xassigned values by \fBset\fR.  Keyword parameters (also known as variables)
Xmay be assigned values by writing:
X.RS
X.PP
X\fIname \(eq value\fR \*(OK \fIname \(eq value\fR \*(CK ...
X.RE
X.PP
XPattern-matching is not performed on \fIvalue\fR.  There cannot be a function
Xand a variable with the same \fIname\fR.
X.PP
X.PD 0
X.TP
X\fB${\fIparameter\fB}\fR
XThe value, if any, of the parameter is substituted.  The braces are required
Xonly when \fIparameter\fR is followed by a letter, digit, or underscore that
Xis not to be interpreted as part of its name.  If \fIparameter\fR is
X\fB*\fR or \fB@\fR, all the positional parameters, starting with \fB$1\fR,
Xare substituted (separated by spaces).  Parameter \fB$0\fR is set from argument
Xzero when the shell is invoked.
X.TP
X\fB${\fIparameter\fB:-\fIword\fB}\fR
XIf \fIparameter\fR is set and is non-null, substitute its value; otherwise
Xsubstitute \fIword\fR.
X.TP
X\fB${\fIparameter\fB:\(eq\fIword\fB}\fR
XIf \fIparameter\fR is not set or is null set it to \fIword\fR; the value of
Xthe parameter is substituted.  Positional parameters may not be assigned to
Xin this way.
X.TP
X\fB${\fIparameter\fB:?\fIword\fB}\fR
XIf \fIparameter\fR is set and is non-null, substitute its value; otherwise,
Xprint \fIword\fR and exit from the shell.  If \fIword\fR is omitted, the
Xmessage \(ga\(gaparameter null or not set\(aa\(aa is printed.
X.TP
X\fB${\fIparameter\fB:+\fIword\fB}\fR
XIf \fIparameter\fR is set and is non-null, substitute \fIword\fR; otherwise
Xsubstitute nothing.
X.PD
X.PP
XIn the above, \fIword\fR is not evaluated unless it is to be used as the
Xsubstituted string, so that, in the following example, \fBpwd\fR is executed
Xonly if \fBd\fR is not set or is null:
X.RS
X.PP
Xecho ${d:-\(gapwd\(ga}
X.RE
X.PP
XIf the colon (\fB:\fR) is omitted from the above expressions, the shell only
Xchecks whether \fIparameter\fR is set or not (\fIIt is not clear what this
Xmeans\fR).
X.PP
XThe following parameters are automatically set by the shell:
X.RS
X.PD 0
X.TP
X.B #
XThe number of positional parameters in decimal.
X.TP
X.B \-
XFlags supplied to the shell on invocation or by the \fBset\fR command.
X.TP
X.B ?
XThe decimal value returned by the last synchronously executed command.
X.TP
X.B $
XThe process number of this shell.
X.TP
X.B !
XThe process number of the last background command invoked.
X.TP
X.B ~
XThe shell reserves all variables beginning with a \fB~\fR for its own
Xinternal use and these variables cannot be accessed by the user.
X.PD
X.RE
X.PP
XThe following parameters are used by the shell:
X.RS
X.PD 0
X.TP
X.B
X.SM CDPATH
XThe search path for the \fIcd\fR command.  (Note that becuase a colon is used
Xby MSDOS to indicate a drive, a semi-colon is used to separate the path names
Xinstead of a colon - this implies that the CDPATH variable must be set using
Xsingle or double quotes to surround the value).
X.TP
X.B
X.SM EXTENDED_LINE
XThis parameter defines a file containing a list of command which can accept
Xan Extended Command Line using the indirect command file character \fB@\fR.
XWhen a command which can process the Extended Command Line finds a parameter
Xstarting with a \fB@\fR in the command list, treats the rest of the parameter
Xas a file and reads the parameters from that file.  Examples of this
Xfunctionality include the Standard \fBLinker\fR and \fBLibrarian\fR.  The
Xfilename defined by \fBEXTENDED_LINE\fR contains a list of command (including
Xthe .exe or .com extension) separated by a newlines.   If the command is in
Xupper case, the file name on the command line is set up with backslashes as
Xthe directory separator.  Otherwise, slashes (Unix style) are used.  This
Xfunctionality allows the user to get round the 127 byte command line length
Xlimit of MSDOS.
X.TP
X.B
X.SM HISTFILE
XThe file where command history is saved across login sessions.  The default
Xvalue is \fB\s-1$HOME\s+1/history.sh\fR.
X.TP
X.B
X.SM HOME
XThe default argument (home directory) for the \fIcd\fR command.
X.TP
X.B
X.SM IFS
XInternal field separators, normally \fBspace\fR, \fBtab\fR, and \fBnew-line\fR.
X.TP
X.B
X.SM MAIL
XIf this parameter is set to the name of a mail file \fIand\fR the
X\fB\s-1MAILPATH\s+1\fR parameter is not set, the shell informs the user of
Xthe arrival of mail in the specified file.
X.TP
X.B
X.SM MAILCHECK
XThis parameter specifies how often (in seconds) the shell will check for the
Xarrival of mail in the files specified by the \fB\s-1MAILPATH\s+1\fR or
X\fB\s-1MAIL\s+1\fR parameters.  If set to 0, the shell will check before each
Xprompt.
X.TP
X.B
X.SM MAILPATH
XA colon (\fB:\fR) separated list of file names.  If this parameter is set,
Xthe shell informs the user of the arrival of mail in any of the specified
Xfiles. Each file name can be followed by \fB%\fR and a message that will be
Xprinted when the modification time changes.  The default message is
X\fI"you have mail"\fR.
X.TP
X.B
X.SM PATH
XThe search path for commands (see \fIExecution\fR below).  The user may not
Xchange \fB\s-1PATH\s+1\fR if executing under \fIrsh\fR.  (Note that because a
Xcolon is used by MSDOS to indicate a drive, a semi-colon is used to separate
Xthe path names instead of a colon - this implies that the PATH variable must
Xbe set using single or double quotes to surround the value).
X.TP
X.B
X.SM PS1
XPrimary prompt string, by default \(ga\(ga\fB$ \fR\(aa\(aa.  
X.TP
X.B
X.SM PS2
XSecondary prompt string, by default \(ga\(ga\fB> \fR\(aa\(aa. 
X.TP
X.B
X.SM SHELL
XWhen the shell is invoked, it scans the environment (see \fIEnvironment\fR
Xbelow) for this name.  If it is found and there is an 'r' in the file name
Xpart of its value, the shell becomes a restricted shell.
X.TP
X.B
X.SM TMP
XThe location of temporary files created by the shell.
X.RE
X.PP
XThe shell gives default values to \fB\s-1PATH\s+1\fR, \fB\s-1PS1\s+1\fR,
X\fB\s-1PS2\s+1\fR, \fB\s-1SHELL\s+1\fR, \fB\s-1HOME\s+1\fR and
X\fB\s-1IFS\s+1\fR.
X.SS Blank Interpretation
XAfter parameter and command substitution, the results of substitution are
Xscanned for internal field separator characters (those found in
X\fB\s-1IFS\s+1\fR) and split into distinct arguments where such characters
Xare found.  Explicit null arguments (\fB""\fR or \fB\(aa\(aa\fR) are retained.
XImplicit null arguments (those resulting from \fIparameters\fR that have no
Xvalues) are removed.
X.SS File Name Generation
XFollowing substitution, each command \fIword\fR is scanned for the characters
X\fB*\fR, \fB?\fR and \fB\*(OK\fR.  If one of these characters appears the word
Xis regarded as a \fIpattern\fR.  The word is replaced with alphabetically
Xsorted file names that match the pattern.  If no file name is found that
Xmatches the pattern, the word is left unchanged.  The character \fB.\fR at the
Xstart of a file name or immediately following a \fB/\fR, as well as the
Xcharacter \fB/\fR itself, must be matched explicitly.  When matching
Xpatterns for file names, the shell ignores the case of the pattern and the
Xfile directory entries.  Generated file names are always in lower case.
X.PP
X.PD 0
X.RS
X.TP
X\fB*\fR
XMatches any string, including the null string.
X.TP
X\fB?\fR
XMatches any single character.
X.TP
X\fB\*(OK ... \*(CK\fR
XMatches any one of the enclosed characters.  A pair of characters separated by
X\fB-\fR matches any character lexically between the pair, inclusive.  If the
Xfirst character following the opening \(ga\(ga\*(OK\(aa\(aa is a
X\fB\(ga\(ga!\(aa\(aa\fR any character not enclosed is matched.
X.PD
X.RE
X.SS Quoting
XThe following characters have a special meaning to the shell and cause
Xtermination of a word unless quoted:
X.RS
X.PP
X\fB;  &  (  )  \(br  ^  <  >  new-line  space  tab\fR
X.RE
X.PP
XA character may be \fIquoted\fR (i.e., made to stand for itself) by preceding
Xit with a \fB\e\fR.  The pair \fB\enew-line\fR is ignored.  All characters
Xenclosed between a pair of single quote marks (\fB\(aa\(aa\fR), except a
Xsingle quote, are quoted.  Inside double quote marks (\fB""\fR), parameter
Xand command substitution occurs and \fB\e\fR quotes the characters \fB\e\fR,
X\fB\(ga\fR, \fB"\fR, and \fB$\fR. \fB"$*"\fR is equivalent to \fB"$1 $2 ..."\fR,
Xwhereas \fB"$@"\fR is equivalent to \fB"$1" "$2" ...\fR.
X.SS Prompting
XWhen used interactively, the shell prompts with the value of \fBPS1\fR
Xbefore reading a command.  If at any time a new-line is typed and further
Xinput is needed to complete a command, the secondary prompt (i.e., the value
Xof \fB\s-1PS2\s+1\fR) is issued.
X.PP
XMany people like to have the shell provide them with useful information in
Xtheir prompt.  To accommodate this, the shell recognises special sequences of
Xcharacters in the values of \fBPS1\fR and \fBPS2\fR, and substitutes the
Xappropriate information for them.  The special sequences and what they signify
Xare:
X.RS
X.TP
X\fB%d\fR
XPlace the current date, in the form \s-1DAY DD-MM-YY\s+1 into the prompt.
X.TP
X\fB%e\fR
XPlace the current event number (as defined by the \fBhistory\fR command) into
Xthe prompt.  If history evaluation has been turned off (via \fBhistory -d\fR),
Xno number will be substituted in (i.e. the \fB%e\fR will be removed).
X.TP
X\fB%n\fR
XPlace the current working drive into the prompt.
X.TP
X\fB%p\fR
XPlace the current working directory into the prompt.
X.TP
X\fB%t\fR
XPlace the current time of day, in the form \s-1HH:MM\s+1 into the prompt.
XThe time is on a 24 hour clock, i.e. 1:30 in the afternoon will be 13:30.
X.TP
X\fB%v\fR
XPlace the MSDOS version number, in the form \s-1 MSDOS MM:MM\s+1 into the
Xprompt.
X.TP
X\fB%%\fR
XPlace the character \fI%\fR into the prompt.
X.TP
X\fB\exxx\fR
XPlace the character \fI\exxx\fR into the prompt.  The processing of escape
Xsequences is the same as that for \fBecho\fR.
X.RE
X.PP
XSome of these facilities are of more use than others.
X.SS Input/Output
XBefore a command is executed, its input and output may be redirected using a
Xspecial notation interpreted by the shell.  The following may appear anywhere
Xin a simple-command or may precede or follow a \fIcommand\fR and are \fInot\fR
Xpassed on to the invoked command; substitution occurs before \fIword\fR or
X\fIdigit\fR is used:
X.PP
X.PD 0
X.TP 14
X\fB<word\fR
XUse file \fIword\fR as standard input (file descriptor 0).
X.TP
X\fB>word\fR
XUse file \fIword\fR as standard output (file descriptor 1).  If the file does
Xnot exist it is created; otherwise, it is truncated to zero length.
X.TP
X\fB>\h@-.3m@>word\fR
XUse file \fIword\fR as standard output.  If the file exists output is appended
Xto it (by first seeking to the end-of-file); otherwise, the file is created.
X.TP
X\fB<\h@-.3m@<\fR\*(OK\fB-\fR\*(CK\fBword\fR
XThe shell input is read up to a line that is the same as \fIword\fR, or to an
Xend-of-file.  The resulting document becomes the standard input.  If any
Xcharacter of \fIword\fR is quoted, no interpretation is placed upon the
Xcharacters of the document; otherwise, parameter and command substitution
Xoccurs, (unescaped) \fB\enew-line\fR is ignored, and \fB\e\fR must be used to
Xquote the characters \fB\e\fR, \fB$\fR, \fB\(ga\fR, and the first character of
X\fIword\fR.  If \fB-\fR is appended to \fB<\h@-.3m@<\fR, all leading tabs are
Xstripped from \fIword\fR and from the document.
X.TP
X\fB<\h@-.1m@&digit\fR
XUse the file associated with file descriptor \fIdigit\fR as standard input.
XSimilarly for the standard output using \fB>\h@-.1m@&digit\fR.
X.TP
X\fB<\h@-.1m@&\h@-.1m@\-\fR
XThe standard input is closed.  Similarly for the standard output using
X\fB>\h@-.1m@&\h@-.1m@\-\fR.
X.PD
X.PP
XIf any of the above is preceded by a digit, the file descriptor which will be
Xassociated with the file is that specified by the digit (instead of the
Xdefault 0 or 1).  For example:
X.RS
X.PP
X\&... 2>&1
X.RE
X.PP
Xassociates file descriptor 2 with the file currently associated with file
Xdescriptor 1.
X.PP
XThe order in which redirections are specified is significant.  The shell
Xevaluates redirections left-to-right.  For example:
X.RS
X.PP
X\&... 1>\fIxxx\fR 2>&1
X.RE
X.PP
Xfirst associates file descriptor 1 with file \fIxxx\fR.  It associates file
Xdescriptor 2 with the file associated with file descriptor 1 (i.e. \fIxxx\fR).
XIf the order of redirections were reversed, file descriptor 2 would be
Xassociated with the terminal (assuming file descriptor 1 had been) and file
Xdescriptor 1 would be associated with file \fIxxx\fR .
X.PP
XThe environment for the execution of a command contains the file descriptors
Xof the invoking shell as modified by input/output specifications.
X.PP
XRedirection of output is not allowed in the restricted shell.
X.SS Environment
XThe \fIenvironment\fR (see \fIenviron\fR(5)) is a list of name-value pairs
Xthat is passed to an executed program in the same way as a normal argument
Xlist.  The shell interacts with the environment in several ways.  On invocation,
Xthe shell scans the environment and creates a parameter for each name found,
Xgiving it the corresponding value.  If the user modifies the value of any of
Xthese parameters or creates new parameters, none of these affects the
Xenvironment unless the \fBexport\fR command is used to bind the shell's
Xparameter to the environment (see also \fBset -a\fR).  A parameter may be
Xremoved from the environment with the \fBunset\fR command.  The environment
Xseen by any executed command is thus composed of any unmodified name-value
Xpairs originally inherited by the shell, minus any pairs removed by \fBunset\fR,
Xplus any modifications or additions, all of which must be noted in \fBexport\fR
Xcommands.
X.PP
XThe environment for any \fIsimple-command\fR may be augmented by prefixing it
Xwith one or more assignments to parameters.  Thus:
X.RS
X.PP
X\s-1TERM\s+1\(eq450 cmd args			and
X.br
X(export \s-1TERM\s+1; \s-1TERM\s+1\(eq450; cmd args)
X.RE
X.PP
Xare equivalent (as far as the execution of \fIcmd\fR is concerned).
X.PP
XIf the \fB-k\fR flag is set, \fIall\fR keyword arguments are placed in the
Xenvironment, even if they occur after the command name.  The following first
Xprints \fBa\(eqb c\fR and \fBc\fR:
X.PP
X.RS
X.nf
Xecho a\(eqb c
Xset -k
Xecho a\(eqb c
X.fi
X.RE
X.SS Signals
XThe \s-1INTERRUPT\s+1 and \s-1QUIT\s+1 signals for an invoked command are
Xignored if the command is followed by \fB&\fR; otherwise signals have the
Xvalues inherited by the shell from its parent, with the exception of signal 11
X(but see also the \fBtrap\fR command below).
X.SS History
XWhen reading input from an interactive terminal, a \(ga\(ga!\(aa\(aa at the
Xstart of a line signals to the shell that it should attempt to perform a history
Xsubsitution.  A history subsitution is a short-hand method which allows the
Xuser to recall a previous command for execution or editing.  The recalled
Xcommand is placed in the command line for editing or passing to the rest of
Xthe shell for normal processing.  A history substitution takes the form:
X.RS
X.PP
X\fB!\fR \*(OK \fIstr\fR \(br \fInum\fR \*(CK \fIterminator\fR
X.RE
X.PP
X\fB!\fInum\fR will place the history command with the specified number
Xin the command line.  \fB!\fIstr\fR will find the most recent command
Xline that started with the characters in \fIstr\fR.
X.PP
XThe \fIterminator\fR determines what action is performed after the history
Xline has been found.  If the original history command is entered using the
X\fB<return>\fR key, the new command line is passed directly to the shell.
XIf the \fB<end>\fR key is pressed, the new command line can be edited in the
Xmanner described below.
X.SS Command Line Editing
XWhen reading input from an interactive terminal, certain keystrokes allow
Xthe current input line to be edited.  The following keystrokes are
Xavailable:
X.TP
X.SM "Cursor Right"
XMove the cursor right one character
X.TP
X.SM "Control-Cursor Right"
XMove the cursor right one word
X.TP
X.SM "Cursor Left"
XMove the cursor left one character
X.TP
X.SM "Control-Cursor Left"
XMove the cursor left one word
X.TP
X.SM "Cursor Up"
XGet the previous command from the history file
X.TP
X.SM "Cursor Down"
XGet the next command from the history file
X.TP
X.SM "Insert"
XToggle insert/overwrite mode
X.TP
X.SM "Delete"
XDelete the current character
X.TP
X.SM "Home"
XMove the cursor to the start of the command
X.TP
X.SM "End"
XMove the cursor to the end of the command, unless the first character of
Xthe command is a \fB!\fR, in which case the appropriate history search is
Xdone.
X.TP
X.SM "Control-End"
XDelete to the end of the line
X.TP
X.SM "Page-Up"
XSearch backwards from the current history command for the next match against
Xthe last history request.  This command can only be used after \fBEnd\fR has
Xbeen used to select a history line.
X.TP
X.SM "Page-Down"
XSearch forewards from the current history command for the next match against
Xthe last history request.  This command can only be used after \fBEnd\fR has
Xbeen used to select a history line.
X.TP
X.SM "Backspace"
XMove the cursor back one character, erasing the current character.
X.TP
X.SM "Return"
XExecute the command line, unless the first character of the command is a
X\fB!\fR, in which case the appropriate history processing is done.
X.PD
X.RE
X.SS Execution
XEach time a command is executed, the above substitutions are carried out.  If
Xthe command name matches one of the \fISpecial Commands\fR listed below, it
Xis executed in the shell process.  If the command name does not match a
X\fISpecial Command\fR, but matches the name of a defined function, the
Xfunction is executed in the shell process (note how this differs from the
Xexecution of shell procedures).  The positional parameters \fB$1\fR,
X\fB$2\fR, ....  are set to the arguments of the function.  If the command
Xname matches neither a \fISpecial Command\fR nor the name of a defined function,
Xa new process is created and an attempt is made to execute the command via
X\fIexec\fR(2).
X.PP
XThe shell parameter \fBPATH\fR defines the search path for the directory
Xcontaining the command.  Alternative directory names are separated by a
Xsemi-colon (\fB;\fR).  The default path is \fB;c:/bin;c:/usr/bin\fR (specifying
Xthe current directory, \fBc:/bin\fR, and \fBc:/usr/bin\fR, in that order).
XNote that the current directory is specified by a null path name, which can
Xappear immediately after the equal sign or between the semi-colon delimiters
Xanywhere else in the path list.  If the command name contains a \fB/\fR or
Xstarts with \fBx:\fR (where x is a drive letter) the search path is not used;
Xsuch commands will not be executed by the restricted shell.  Otherwise, each
Xdirectory in the path is searched for an executable file.
X.PP
XIf the file does not have a .com or .exe extension, it is opened and the first
X5 characters are read.  If the first 5 characters are the string
X\fB#!sh\\n\fR it is assumed to be a file containing shell commands.  Note
Xthat the shell will check the file and if that file does not exist or is not a
Xscript, it will try the file with an extension of \fB.sh\fR.  If a \fB.sh\fR
Xfile is found, that will be processed.  A sub-shell is spawned to read it.
XA parenthesized command is also executed in a sub-shell.
X.SS Special Commands
XInput/output redirection is permitted for these commands.  File descriptor 1
Xis the default output location.
X.PP
X.PD 0
X.TP
X\fB:\fR
XNo effect; the command does nothing.  A zero exit code is returned.
X.TP
X\fIletter\fB:\fR
XSelect the drive specified by \fIletter\fR.
X.TP
X\fB\&. \fIfile\fR
XRead and execute commands from \fIfile\fR and return.  The search path
Xspecified by \fBPATH\fR is used to find the directory containing \fIfile\fR.
X.TP
X\fBbreak\fR \*(OK \fIn\fR \*(CK
XExit from the enclosing \fBfor\fR or \fBwhile\fR loop, if any.  If \fIn\fR is
Xspecified, break \fIn\fR levels.
X.TP
X\fBcontinue\fR \*(OK \fIn\fR \*(CK
XResume the next iteration of the enclosing \fBfor\fR or \fBwhile\fR loop.  If
X\fIn\fR is specified, resume at the \fIn\fR-th enclosing loop.
X.TP
X\fBcd\fR \*(OK \fIarg\fR \*(CK
XChange the current directory to \fIarg\fR.  The shell parameter \fBHOME\fR is
Xthe default \fIarg\fR.  The shell parameter \fBCDPATH\fR defines the search
Xpath for the directory containing \fIarg\fR.  Alternative directory names are
Xseparated by a semi-colon (\fB;\fR).  The default path is \fB<null>\fR
X(specifying the current directory).  Note that the current directory is
Xspecified by a null path name, which can appear immediately after the equal
Xsign or between the semi-colon delimiters anywhere else in the path list.
XIf \fIarg\fR begins with a \fB/\fR or \fBx:\fR (where x is a drive letter),
Xthe search path is not used.  Otherwise, each directory in the path is searched
Xfor \fIarg\fR.  The \fIcd\fR command may not be executed by \fIrsh\fR.
X.TP
X\fBecho\fR \*(OK \fIarg\fR ... \*(CK
XEcho arguments. \fBEcho\fR writes its arguments separated by blanks and
Xterminated by a new-line on the standard output.  It also understands C-like
Xescape conventions; beware of conflicts with the shell's use of \fB\e\fR:
X.PP
X.RS
X.PD 0
X.TP
X\fB\eb\fR
Xbackspace
X.TP
X\fB\ec\fR
Xprint line without new-line
X.TP
X\fB\ef\fR
Xform-feed
X.TP
X\fB\en\fR
Xnew-line
X.TP
X\fB\er\fR
Xcarriage return
X.TP
X\fB\et\fR
Xtab
X.TP
X\fB\ev\fR
Xvertical tab
X.TP
X\fB\e\e\fR
Xbackslash
X.TP
X\fB\e\fIn\fR
Xthe 8-bit character whose \s-1ASCII\s0 code is the 1-, 2- or 3-digit octal
Xnumber \fIn\fR, which must start with a zero.
X.PD
X.PP
X\fIEcho\fR is useful for producing diagnostics in command files and for
Xsending known data into a pipe.
X.RE
X.TP
X\fBeval\fR \*(OK \fIarg\fR ... \*(CK
XThe arguments are read as input to the shell and the resulting command(s)
Xexecuted.
X.TP
X\fBexec\fR \*(OK \fIarg\fR ... \*(CK
XThe command specified by the arguments is executed in place of this shell
Xwithout creating a new process.  Input/output arguments may appear and, if no
Xother arguments are given, cause the shell input/output to be modified.
X.TP
X\fBexit\fR \*(OK \fIn\fR \*(CK
XCauses a shell to exit with the exit status specified by \fIn\fR.
XIf \fIn\fR is omitted the exit status is that of the last command executed
X(an end-of-file will also cause the shell to exit.)
X.TP
X\fBexport\fR \*(OK \fIname\fR ... \*(CK
XThe given \fIname\fRs are marked for automatic export to the \fIenvironment\fR
Xof subsequently-executed commands.  If no arguments are given, a list of all
Xnames that are exported in this shell is printed.  Function names may \fInot\fR
Xbe exported.
X.TP
X\fBgetopt\fR \fIoptstring name\fR \*(OK \fIargs\fR ... \*(CK
XParse command options and write them to standard output.  \fBGetopt\fR is used
Xto break up options in command lines for easy parsing by shell procedures and
Xto check for legal options.  \fIOptstring\fR is a string of recognized option
Xletters (see \fIgetopt\fR(3C)); if a letter is followed by a colon, the option
Xis expected to have an argument which may or may not be separated from it by
Xwhite space.  The special option \fB\-\-\fP is used to delimit the end of the
Xoptions.  If it is used explicitly, \fBgetopt\fR will recognize it; otherwise,
X\fBgetopt\fR will generate it; in either case, \fBgetopt\fR will place it at
Xthe end of the options.  Each option is preceded by a \fB-\fR and is in its
Xown positional parameter; each option argument is also parsed into its own
Xpositional parameter.
X.sp
XThe following code fragment shows how one might process the arguments for a
Xcommand that can take the options \fBa\fR or \fBb\fR, as well as the option
X\fBo\fR, which requires an argument:
X.sp
X.RS
X.nf
X.ss 18
X.ta +.5i +1i
Xset -- \(gagetopt abo: $*\(ga
Xif [ $? !\(eq 0 ]
Xthen
X	echo $\s-1USAGE\s+1
X	exit 2
Xfi
Xfor i in $\(**
Xdo
X	case $i in
X	\-a \(bv \-b)	\s-1FLAG\s+1\(eq$i; shift;;
X	\-o)	\s-1OARG\s+1\(eq$2; shift 2;;
X	\-\-)	shift; break;;
X	esac
Xdone
X.fi
X.ta
X.ss 12
X.sp
XThis code will accept any of the following as equivalent:
X.sp
X.nf
X.ss 18
Xcmd \-aoarg file file
Xcmd \-a \-o arg file file
Xcmd \-oarg \-a file file
Xcmd \-a \-oarg \-\- file file
X.fi
X.ss 12
X.RE
X.TP
X\fBhistory\fR \*(OK \fB-dei\fR \*(CK
XThe \fBhistory\fR command, with no arguments, will print all the commands that
Xare currently saved in the shell's history buffers.  As new commands are
Xexecuted, and space in the buffers runs out, old commands will be deleted.  The
X\fBhistory\fR commands prints out the stored commands with sequence numbers.
XNegative numbered commands, through command number zero, are commands that were
Xretrieved from the saved history file.  Commands starting at one were entered
Xduring the current login session.  If a saved command contains embedded
Xnewlines, these will be printed out as the sequence \fB\en\fR, so that
Xindividual command stay on one line.
X.sp
XThe arguments changes the way the shell processes history information as
Xfollows:
X.RS
X.TP
X\fB-d\fR
XDisable the saving of commands in the history file.
X.TP
X\fB-e\fR
XEnable the saving of commands in the history file.
X.TP
X\fB-i\fR
XInitialise the history file.
X.RE
X.TP
X\fBmsdos\fR \*(OK \fIname\fR ... \*(CK
XThe given \fIname\fRs are marked \fImsdos\fR format and if the \fB-m\fR flag
Xis set, the values of the these \fIname\fRs are exported to child processes
Xwith the any slashes in the value replaced by backslashes.
X.TP
X\fBpwd\fR
XPrint the current working directory.  
X.TP
X\fBread\fR \*(OK \fIname\fR ... \*(CK
XOne line is read from the standard input and the first word is assigned to the
Xfirst \fIname\fR, the second word to the second \fIname\fR, etc., with leftover
Xwords assigned to the last \fIname\fR.  The return code is 0 unless an
Xend-of-file is encountered.
X.TP
X\fBreadonly\fR \*(OK \fIname\fR ... \*(CK
XThe given \fIname\fRs are marked \fIreadonly\fR and the values of the these
X\fIname\fRs may not be changed by subsequent assignment.  If no arguments are
Xgiven, a list of all \fIreadonly\fR names is printed.
X.TP
X\fBreturn\fR \*(OK \fIn\fR \*(CK
XCauses a function to exit with the return value specified by \fIn\fR.  If
X\fIn\fR is omitted, the return status is that of the last command executed.
X.TP
X\fBset\fR \*(OK \fB--aefkmntuvx\fR \*(OK \fIarg\fR ... \*(CK \*(CK
X.RS
X.TP
X\fB-a\fR
XMark variables which are modified or created for export.
X.TP
X\fB-e\fR
XExit immediately if a command exits with a non-zero exit status.
X.TP
X\fB-f\fR
XDisable file name generation
X.TP
X\fB-k\fR
XAll keyword arguments are placed in the environment for a command, not just
Xthose that precede the command name.
X.TP
X\fB-m\fR
XFor those variables marked as \fBmsdos\fR variables, the values are
Xexported to child processes with the slashes replaced by backslashes.  Most
XMSDOS utilities do not care if a file name contains a slash or backslash as
Xa directory separator.  However, some like the \fIlinker\fR require
Xbackslashes in the value of the \fBLIB\fR variable.
X.TP
X\fB-n\fR
XRead commands but do not execute them.
X.TP
X\fB-t\fR
XExit after reading and executing one command.
X.TP
X\fB-u\fR
XTreat unset variables as an error when substituting.
X.TP
X\fB-v\fR
XPrint shell input lines as they are read.
X.TP
X\fB-x\fR
XPrint commands and their arguments as they are executed.
X.TP
X\fB--\fR
XDo not change any of the flags; useful in setting \fB$1\fR to \fB\-\fR.
X.PP
XUsing \fB+\fR rather than \fB-\fR causes these flags to be turned off.  These
Xflags can also be used upon invocation of the shell.  The current set of flags
Xmay be found in \fB$-\fR.  The remaining arguments are positional parameters
Xand are assigned, in order, to \fB$1\fR, \fB$2\fR, ....  If no arguments
Xare given the values of all names are printed.
X.RE
X.TP
X\fBshift\fR \*(OK \fIn\fR \*(CK
X.br
XThe positional parameters from \fB$n+1\fR ...  are renamed \fB$1\fR ....  If
X\fIn\fR is not given, it is assumed to be 1.
X.TP
X\fBswap\fR \*(OK \fIoptions\fR \*(CK
XThis command defines how the shell will handle swapping.  The options are
X.RS
X.TP
X\fBoff\fR
XDisable swapping.  The shell remains in memory whilst the child is running
Xand reduces the available memory by about 200K (depending on the size of
Xthe environment and history).
X.TP
X\fBon\fR
XEnable all devices.  The shell will swap out to either expanded or extended
Xmemory or to disk, execute the command and then swap back in.  Whilest
Xswapped, the shell reduces the available memory by about 3K.
X.TP
X\fBexpand\fR
XEnable swapping to Expanded Memory.  The EMS drive must exist on your
Xsystem for this to work.
X.TP
X\fBextent\fR \*(OK \fIstart address\fR \*(CK
XEnable swapping to Extended Memory.  The optional start address defines the
Xbased address in the Extended Memory at which point the shell writes its
Xswap area.  The default location is \fI0x100000\fR.
X.TP
X\fBdisk\fR
XEnable swapping to disk.  The shell creates a temporary file and saves
Xitself in it.  On completion, the file is deleted.  This is the slowest method
Xof swapping.
X.PD
X.PP
XWith no options, the current swapping options are displayed.
X.RE
X.TP
X\fBtest \fIexpr\fR or \fB\*(OK \fIexpr\fB \*(CK\fR
XEvaluate conditional expressions.  \fBTest\fR evaluates the expression
X\fIexpr\fR and, if its value is true, returns a zero (true) exit status;
Xotherwise, a non-zero (false) exit status is returned; \fBtest\fR also returns
Xa non-zero exit status if there are no arguments.  The following primitives
Xare used to construct \fBexpr\fR:
X.RS
X.TP 12
X\fB-r \fIfile\fR
Xtrue if \fIfile\fR exists and is readable.
X.TP
X\fB-w \fIfile\fR
Xtrue if \fIfile\fR exists and is writable.
X.TP
X\fB-x \fIfile\fR
Xtrue if \fIfile\fR exists and is executable.
X.TP
X\fB-f \fIfile\fR
Xtrue if \fIfile\fR exists and is a regular file.
X.TP
X\fB-d \fIfile\fR
Xtrue if \fIfile\fR exists and is a directory.
X.TP
X\fB-c \fIfile\fR
Xtrue if \fIfile\fR exists and is a character special file.
X.TP
X\fB-b \fIfile\fR
Xtrue if \fIfile\fR exists and is a block special file.
X.TP
X\fB-s \fIfile\fR
Xtrue if \fIfile\fR exists and has a size greater than zero.
X.TP
X\fB-t\fR \*(OK \fIfildes\fR \*(CK
Xtrue if the open file whose file descriptor number is \fIfildes\fR (1 by
Xdefault) is associated with a terminal device.
X.TP
X\fB-n \fIs1\fR
Xtrue if the length of the string \fIs1\fR is zero.
X.TP
X\fB-n \fIs1\fR
Xtrue if the length of the string \fIs1\fR is non-zero.
X.TP
X\fIs1 \fB\(eq\fI s2\fR
Xtrue if strings \fIs1\fR and \fIs2\fR are identical.
X.TP
X\fIs1 \fB!\(eq\fI s2\fR
Xtrue if strings \fIs1\fR and \fIs2\fR are \fInot\fR identical.
X.TP
X\fIs1\fR
Xtrue if \fIs1\fR is \fInot\fR the null string.
X.TP
X\fIn1 \fB-eq \fIn2\fR
Xtrue if the integers \fIn1\fR and \fIn2\fR are algebraically equal.  Any of
Xthe comparisons \fB-ne\fR, \fB-gt\fR, \fB-ge\fR, \fB-lt\fR, and \fB-le\fR
Xmay be used in place of \fBR-eq\fR.
X.PP
XThese primaries may be combined with the following operators:
X.TP  12
X\fB!\fR
Xunary negation operator.
X.TP
X\fB-a\fR
Xbinary \fIand\fR operator.
X.TP
X\fB-o\fR
Xbinary \fIor\fR operator (\fB-a\fR has higher precedence than \fB-o\fR).
X.TP
X\fB(\fR expr \fB)\fR
Xparentheses for grouping.
X.PP
XNotice that all the operators and flags are separate arguments to \fBtest\fR.
XNotice also that parentheses are meaningful to the shell and, therefore,
Xmust be escaped.
X.RE
X.TP
X\fBtrap\fR \*(OK \fIarg\fR \*(CK \*(OK \fIn\fR \*(CK ...
XThe command \fIarg\fR is to be read and executed when the shell receives
Xsignal(s) \fIn\fR.  (Note that \fIarg\fR is scanned once when the trap is set
Xand once when the trap is taken.) Trap commands are executed in order of
Xsignal number.  Any attempt to set a trap on a signal that was ignored on
Xentry to the current shell is ineffective.  An attempt to trap on signal 11
X(memory fault) produces an error.  If \fIarg\fR is absent all trap(s) \fIn\fR
Xare reset to their original values.  If \fIarg\fR is the null string this
Xsignal is ignored by the shell and by the commands it invokes.  If \fIn\fR is
X0 the command \fIarg\fR is executed on exit from the shell.  The \fBtrap\fR
Xcommand with no arguments prints a list of commands associated with each
Xsignal number.
X.TP
X\fBtype\fR \*(OK \fIname\fR ... \*(CK
XFor each \fIname\fR, indicate how it would be interpreted if used as a command
Xname.
X.TP
X\fBumask\fR \*(OK \fInnn\fR \*(CK
XThe user file-creation mask is set to \fInnn\fR (see \fIumask\fR(2)).  If
X\fInnn\fR is omitted, the current value of the mask is printed.
X.TP
X\fBunset\fR \*(OK \fIname\fR ... \*(CK
XFor each \fIname\fR, remove the corresponding variable or function.  The
Xvariables \fB\s-1PATH\s+1\fR, \fB\s-1PS1\s+1\fR, \fB\s-1PS2\s+1\fR, and
X\fB\s-1IFS\s+1\fR cannot be unset.
X.TP
X\fBver\fR
XDisplay the current version of the shell.
X.PD
X.PP
X.SS Invocation
XIf the shell is invoked through \fIexec\fR(2) and the first character of
Xargument zero is \fB-\fR or the \fB-0\fR(zero) switch is in the invokation line,
Xcommands are initially read from \fB/etc/profile.sh\fR and from
X\fB\s-1$HOME\s+1/profile.sh\fR, if such files exist.  Thereafter, commands are
Xread as described below, which is also the case when the shell is invoked as
X\fB/bin/sh\fR.  The flags below are interpreted by the shell on invocation only;
XNote that unless the \fB-c\fR or \fB-s\fR flag is specified, the first argument
Xis assumed to be the name of a file containing commands, and the remaining
Xarguments are passed as positional parameters to that command file:
X.PP
X.PD 0
X.TP 10
X\fB-c\fR string
XIf the \fB-c\fR flag is present commands are read from \fIstring\fR.
X.TP
X\fB-s\fR
XIf the \fB-s\fR flag is present or if no arguments remain commands are read
Xfrom the standard input.  Any remaining arguments specify the positional
Xparameters.  Shell output (except for \fISpecial Commands\fR) is written to
Xfile descriptor 2.
X.TP
X\fB-i\fR
XIf the \fB-i\fR flag is present or if the shell input and output are attached
Xto a terminal, this shell is \fIinteractive\fR.  In this case, the
X\s-1TERMINATE\s+1 signal is ignored and the \s-1INTERRUPT\s+1 signal is caught
Xand ignored.  In all cases, the \s-1QUIT\s+1 signal is ignored by the shell.
X.TP
X\fB-r\fR
XIf the \fB-r\fR flag is present, the shell is a restricted shell.
X.TP
X\fB-0\fR(zero)
XIf the \fB-0\fR(zero) flag is present, this has the same effect as starting the
Xshell with the first character of argument zero as a \fB-\fR (see above).
X.PD
X.PP
XThe remaining flags and arguments are described under the \fBset\fR command
Xabove.
X.SS Rsh Only
X\fIRsh\fR is used to set up login names and execution environments whose
Xcapabilities are more controlled than those of the standard shell.  The
Xactions of \fIrsh\fR are identical to those of \fIsh\fR, except that the
Xfollowing are disallowed:
X.RS
X.PD 0
X.PP
Xchanging directory (see \fIcd\fR(1)),
X.br
Xsetting the value of \fB$PATH\fR
X.br
Xspecifying path or command names containing \fB/\fR,
X.br
Xredirecting output (\fB>\fR and \fB>>\fR).
X.PD
X.RE
X.PP
XThe restrictions above are enforced after \fBprofile.sh\fR is interpreted.
X.PP
XWhen a command to be executed is found to be a shell procedure, \fIrsh\fR
Xinvokes \fIsh\fR to execute it.  Thus, it is possible to provide to the
Xend-user shell procedures that have access to the full power of the standard
Xshell, while imposing a limited menu of commands; this scheme assumes that the
Xend-user does not have write and execute permissions in the same directory.
X.PP
XThe net effect of these rules is that the writer of the \fBprofile.sh\fR has
Xcomplete control over user actions, by performing guaranteed setup actions
Xand leaving the user in an appropriate directory (probably \fInot\fR the login
Xdirectory).
X.PP
XThe system administrator often sets up a directory of commands (i.e.,
X\fB/usr/rbin\fR) that can be safely invoked by \fIrsh\fR.  Some systems also
Xprovide a restricted editor \fIred\fR.
X.SH EXIT STATUS
XErrors detected by the shell, such as syntax errors, cause the shell to return
Xa non-zero exit status.  If the shell is being used non-interactively execution
Xof the shell file is abandoned.  Otherwise, the shell returns the exit status of
Xthe last command executed (see also the \fBexit\fR command above).
X.SH FILES
X/etc/profile.sh
X.br
X\s-1$HOME\s+1/profile.sh
X.br
X\s-1$TMP\s+1/sh\(**
X.SH LIMIITATIONS
XAny TSR (Terminate Stay Resident) programs must be loaded before loading
X\fISh\fR as the shell will overwrite the TSR when it reloads itself after
Xswapping out.
X.SH SEE ALSO
Xcd(1),
Xenv(1),
Xtest(1),
Xumask(1).
X.br
Xdup(2),
Xexec(2),
Xpipe(2),
Xsignal(2),
Xumask(2),
Xwait(2),
Xprofile(4),
Xenviron(5) in the
X\fI\s-1UNIX\s+1 System Programmer Reference Manual\fR.
SHAR_EOF
chmod 0644 sh.1 || echo "restore of sh.1 fails"
set `wc -c sh.1`;Sum=$1
if test "$Sum" != "42496"
then echo original size 42496, current size $Sum;fi
echo "x - extracting include/Changes (Text)"
sed 's/^X//' << 'SHAR_EOF' > include/Changes &&
XAdd to fcntl.h the following 2 lines
X
Xextern int _CDECL	open	(char *, int, ...);
Xextern int _CDECL	creat	(char *, int);
X
XAdd to limits.h the following 2 lines
X
X#define PATH_MAX	130		/* Maximum path length		*/
X#define NAME_MAX	14		/* Maximum file name length	*/
X
XAdd to stdio.h the following 2 lines
X
Xextern FILE * _CDECL	popen(char *, char *);
Xextern int _CDECL	pclose(FILE *);
X
XAdd to stdlib.h the following 8 lines
X
Xextern int _CDECL		optind;
Xextern int _CDECL		opterr;
Xextern int _CDECL		optind;
Xextern int _CDECL		optopt;
Xextern int _CDECL		optvar;
Xextern char * _CDECL		optarg;
Xextern int _CDECL		getopt	(int, char **, char *);
Xextern int _CDECL		pnmatch	(char *, char *, int);
X
XAdd to sys/stat.h the following 10 lines
X
X/* Tests for file types */
X
X#define	S_IFBLK		0060000		/* block special		*/
X
X#define S_ISDIR(m)	((((m) & S_IFMT) == S_IFDIR))
X#define S_ISCHR(m)	((((m) & S_IFMT) == S_IFCHR))
X#define S_ISREG(m)	((((m) & S_IFMT) == S_IFREG))
X#define S_ISBLK(m)	((((m) & S_IFMT) == S_IFBLK))
Xextern int CDECL	chmod	(char *, int);
Xextern int CDECL	umask	(int);
X
XAdd to sys/types.h the following 32 lines
X
X#ifndef _USHORT_T_DEFINED
Xtypedef unsigned short	ushort;
X#define _USHORT_T_DEFINED
X#endif
X
X#ifndef _MODE_T_DEFINED
Xtypedef unsigned short	mode_t;
X#define _MODE_T_DEFINED
X#endif
X
X#ifndef _PID_T_DEFINED
Xtypedef int		pid_t;
X#define _PID_T_DEFINED
X#endif
X
X#ifndef _GID_T_DEFINED
Xtypedef int		gid_t;
X#define _GID_T_DEFINED
X#endif
X
X#ifndef _UID_T_DEFINED
Xtypedef int		uid_t;
X#define _UID_T_DEFINED
X#endif
X
X#ifndef _BOOL_T_DEFINED
Xtypedef char		bool;	/* Boolean: 0 = false, 1 = true		*/
X#define FALSE	((bool)0)	/* Boolean 'false'			*/
X#define TRUE	((bool)1)	/* Boolean 'true'			*/
X#define _BOOL_T_DEFINED
X#endif
X
SHAR_EOF
chmod 0644 include/Changes || echo "restore of include/Changes fails"
set `wc -c include/Changes`;Sum=$1
if test "$Sum" != "1716"
then echo original size 1716, current size $Sum;fi
echo "x - extracting include/sys/dirent.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > include/sys/dirent.h &&
X/* <sys/dirent.h> -- file system independent directory entry (SVR3) */
X#ifndef _SYS_DIRENT_H
X#define _SYS_DIRENT_H
X
X#ifndef MSDOS
X#define	MAXNAMLEN	512	/* maximum filename length		*/
X#else
X#define	MAXNAMLEN	13	/* maximum filename length		*/
X#endif
X
X#ifndef NAME_MAX
X#define	NAME_MAX	(MAXNAMLEN - 1)
X#endif
X
Xstruct dirent			/* data from getdents()/readdir()	*/
X{
X    ino_t	d_ino;		/* inode number of entry		*/
X    off_t	d_off;		/* offset of disk directory entry	*/
X    ushort	d_reclen;	/* length of this record		*/
X#ifndef MSDOS
X    char	d_name[1];	/* name of file				*/
X#else
X    char	d_name[MAXNAMLEN + 1];
X#endif
X};
X
X#ifdef BSD_SYSV			/* (e.g., when compiling getdents.c)	*/
Xextern struct dirent	__dirent;	/* (not actually used) */
X
X				/* The following is portable, although	*/
X				/* rather silly.			*/
X#define	DIRENTBASESIZ		(__dirent.d_name - (char *)&__dirent.d_ino)
X
X#else
X
X/* The following nonportable ugliness could have been avoided by defining
X * DIRENTSIZ and DIRENTBASESIZ to also have (struct dirent *) arguments.
X * There shouldn't be any problem if you avoid using the DIRENTSIZ() macro.
X */
X
X#define	DIRENTBASESIZ		(((struct dirent *)0)->d_name \
X				- (char *)&((struct dirent *)0)->d_ino)
X#endif
X
X#define	DIRENTSIZ(namlen)	((DIRENTBASESIZ + sizeof(long) + (namlen)) \
X				/ sizeof(long) * sizeof(long))
X
X#endif
SHAR_EOF
chmod 0644 include/sys/dirent.h || echo "restore of include/sys/dirent.h fails"
set `wc -c include/sys/dirent.h`;Sum=$1
if test "$Sum" != "1331"
then echo original size 1331, current size $Sum;fi
echo "x - extracting include/sys/proto.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > include/sys/proto.h &&
X/*
X * Prototype definitions for Standard and Non-standard compilers
X */
X
X#undef _PROTO
X#undef _CDECL
X#undef _NEAR
X
X#ifdef MSDOS
X#  ifndef NO_EXT_KEYS				/* extensions enabled */
X#    define _CDECL	cdecl
X#    define _NEAR	near
X#  else 
X#    define _CDECL
X#    define _NEAR
X#  endif 
X#else
X#    define _CDECL
X#endif
X
X#ifdef __STDC__
X#  define _PROTO(p)	p
X#else
X#  define _PROTO(p)	()
X#  undef  const
X#endif
SHAR_EOF
chmod 0644 include/sys/proto.h || echo "restore of include/sys/proto.h fails"
set `wc -c include/sys/proto.h`;Sum=$1
if test "$Sum" != "405"
then echo original size 405, current size $Sum;fi
echo "x - extracting include/dirent.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > include/dirent.h &&
X/* <dirent.h> -- definitions for SVR3 directory access routines */
X#ifndef _DIRENT_H
X#define _DIRENT_H
X
X#include <sys/types.h>
X#include <limits.h>
X#include <sys/dirent.h>
X#include <sys/proto.h>
X
X#ifndef NULL
X#  ifdef MSDOS
X#    if (defined(M_I86SM) || defined(M_I86MM))
X#      define NULL	0
X#    else
X#      if (defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM))
X#        define NULL	0L
X#      endif
X#    endif
X#  else
X#    define NULL	0
X#  endif
X#endif
X
X#define	DIRBUF	8192		/* buffer size for fs-indep. dirs	*/
X				/* must in general be larger than the	*/
X				/* filesystem buffer size		*/
X
X#ifndef MSDOS
Xtypedef struct
X{
X    int		dd_fd;		/* file descriptor			*/
X    int		dd_loc;		/* offset in block			*/
X    int		dd_size;	/* amount of valid data			*/
X    char	*dd_buf;	/* -> directory block			*/
X} DIR;				/* stream data from opendir()		*/
X
X#else
X
X/* MSDOS versions */
X
Xstruct _dircontents {
X    char		*_d_entry;
X    struct _dircontents	*_d_next;
X};
X
Xtypedef struct _dirdesc {
X    int			dd_id;	/* uniquely identify each open directory */
X    long		dd_loc;	/* where we are in directory entry is this */
X    struct _dircontents	*dd_contents;	/* pointer to contents of dir	*/
X    struct _dircontents	*dd_cp;		/* pointer to current position	*/
X} DIR;
X#endif
X
X/* Functions */
X
Xextern DIR * _CDECL		opendir		_PROTO ((char *));
Xextern struct dirent * _CDECL	readdir		_PROTO ((DIR *));
Xextern void _CDECL		rewinddir	_PROTO ((DIR *));
Xextern int _CDECL		closedir	_PROTO ((DIR *));
Xextern void _CDECL		seekdir		_PROTO ((DIR *, off_t));
Xextern off_t _CDECL		telldir		_PROTO ((DIR *));
X
Xextern int _CDECL		chdir		_PROTO ((char *));
Xextern char * _CDECL		getcwd		_PROTO ((char *, int));
X#ifdef MSDOS
Xextern int _CDECL		mkdir		_PROTO ((char *));
X#else
Xextern int _CDECL		mkdir		_PROTO ((char *, mode_t));
X#endif
Xextern int _CDECL		rmdir		_PROTO ((char *));
Xextern int _CDECL		scandir		_PROTO ((char *, struct dirent ***, int (_CDECL *)(const void *, const void *), int (_CDECL *)(const void *, const void *)));
X#endif
SHAR_EOF
chmod 0644 include/dirent.h || echo "restore of include/dirent.h fails"
set `wc -c include/dirent.h`;Sum=$1
if test "$Sum" != "2014"
then echo original size 2014, current size $Sum;fi
echo "x - extracting include/unistd.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > include/unistd.h &&
X#ifndef _UNISTD_H
X#define _UNISTD_H
X
X/*  unistd.h  */
X
X#include <sys/types.h>
X#include <sys/proto.h>
X
X/* Definition for NULL pointer */
X
X#ifndef NULL
X#  ifdef MSDOS
X#    if (defined(M_I86SM) || defined(M_I86MM))
X#      define NULL	0
X#    else
X#      if (defined(M_I86CM) || defined(M_I86LM) || defined(M_I86HM))
X#        define NULL	0L
X#      endif
X#    endif
X#  else
X#    define NULL	0
X#  endif
X#endif
X
X/*  for access(2)  */
X
X#define R_OK     	4
X#define W_OK     	2
X#define X_OK     	1
X#define F_OK     	0
X
X/*  for lockf()  */
X
X#define F_ULOCK		0
X#define F_LOCK		1
X#define F_TLOCK		2
X#define F_TEST		3
X
X/*  for lseek(2)  */
X
X#ifndef SEEK_SET
X#define SEEK_SET	0
X#endif
X
X#ifndef SEEK_CUR
X#define SEEK_CUR	1
X#endif
X
X#ifndef SEEK_END
X#define SEEK_END	2
X#endif
X
X/* STDIO definitions */
X
X#define	STDIN_FILENO	0
X#define	STDOUT_FILENO	1
X#define	STDERR_FILENO	2
X
X/* Standard paths */
X
X#define GF_PATH		"/etc/group"
X#define PF_PATH		"/etc/passwd"
X#define IF_PATH		"/usr/include"
X#define SF_PATH		"/etc/shadow"
X
X/* POSIX definitions */
X
X#define _POSIX_VERSION		198803L
X#undef	_POSIX_CHOWN_RESTRICTED
X#undef	_POSIX_JOB_CONTROL
X#define	_POSIX_NO_TRUNC		1
X#define _POSIX_SAVED_IDS	1
X#undef	_POSIX_VDISABLE
X/* #define _XOPEN_VERSION		*/
X
X/* sysconf values */
X
X#define _SC_ARG_MAX		0
X#define _SC_CHILD_MAX		1
X#define _SC_CLK_TCK		2
X#define _SC_NGROUPS_MAX		3
X#define _SC_OPEN_MAX		4
X#define _SC_JOB_CONTROL		5
X#define _SC_SAVED_IDS		6
X#define _SC_VERSION		7
X#define _SC_PASS_MAX		8
X#define _SC_XOPEN_VERSION	9
X
X/* pathconf values */
X
X#define _PC_LINK_MAX		0
X#define _PC_MAX_CANON		1
X#define _PC_MAX_INPUT		2
X#define _PC_NAME_MAX		3
X#define _PC_PATH_MAX		4
X#define _PC_PIPE_BUF		5
X#define _PC_CHOWN_RESTRICTED	6
X#define _PC_NO_TRUNC		7
X#define _PC_VDISABLE		8
X
X/* confstring values */
X
X#define _CS_PATH		1
X
X/* Function declarations */
X
Xextern size_t _CDECL	confstring	_PROTO ((int, char *, size_t));
Xextern void _CDECL	abort		_PROTO ((void));
X#ifdef MSDOS
Xextern int _CDECL	chsize		_PROTO ((int, off_t));
X#else
Xextern int _CDECL	chsize		_PROTO ((char *, off_t));
X#endif
Xextern void _CDECL	sync		_PROTO ((void));
X
X/* --- Process creation and execution --- */
Xextern pid_t _CDECL	fork		_PROTO ((void));
Xextern pid_t _CDECL	vfork		_PROTO ((void));
Xextern int _CDECL	execl		_PROTO ((char *, char *, ...));
Xextern int _CDECL	execle		_PROTO ((char *, char *, ...));
Xextern int _CDECL	execlp		_PROTO ((char *, char *, ...));
Xextern int _CDECL	execlpe		_PROTO ((char *, char *, ...));
Xextern int _CDECL	execv		_PROTO ((char *, char **));
Xextern int _CDECL	execve		_PROTO ((char *, char **, char **));
Xextern int _CDECL	execvp		_PROTO ((char *, char **));
Xextern int _CDECL	execvpe		_PROTO ((char *, char **, char **));
X
X/* --- Process termination --- */
Xextern void _CDECL	_exit		_PROTO ((int));
Xextern void _CDECL	exit		_PROTO ((int));
X
X/* --- Timer operations --- */
Xextern unsigned int _CDECL	alarm	_PROTO ((unsigned int));
Xextern int _CDECL		pause	_PROTO ((void));
Xextern unsigned int _CDECL	sleep	_PROTO ((unsigned int));
X
X/* --- Process identification --- */
Xextern pid_t _CDECL	getpid		_PROTO ((void));
Xextern pid_t _CDECL	getppid		_PROTO ((void));
X
X/* --- User identification --- */
Xextern uid_t _CDECL	getuid		_PROTO ((void));
Xextern uid_t _CDECL	geteuid		_PROTO ((void));
Xextern gid_t _CDECL	getgid		_PROTO ((void));
Xextern gid_t _CDECL	getegid		_PROTO ((void));
Xextern int _CDECL	setuid		_PROTO ((uid_t));
Xextern int _CDECL	setgid		_PROTO ((gid_t));
Xextern int _CDECL	getgroups	_PROTO ((int, gid_t *));
Xextern char * _CDECL	getlogin	_PROTO ((void));
Xextern char * _CDECL	cuserid		_PROTO ((char *));
X
X/* --- Process groups --- */
Xextern pid_t _CDECL	getpgrp		_PROTO ((void));
Xextern pid_t _CDECL	setsid		_PROTO ((void));
Xextern int _CDECL	setpgid		_PROTO ((pid_t, pid_t));
X
X/* --- Terminal identification --- */
Xextern char * _CDECL	ctermid	_PROTO ((char *));
Xextern char * _CDECL	ttyname	_PROTO ((int));
Xextern int _CDECL	isatty		_PROTO ((int));
X
X/* --- Configurable system variables --- */
Xextern long _CDECL	sysconf		_PROTO ((int));
X
X/* --- Working directory --- */
Xextern int _CDECL	chdir		_PROTO ((char *));
Xextern char * _CDECL	getcwd		_PROTO ((char *, int));
X
X/* --- General file creation --- */
Xextern int _CDECL	link		_PROTO ((char *, char *));
Xextern int _CDECL	rename		_PROTO ((const char *, const char *));
Xextern char * _CDECL	mktemp		_PROTO ((char *));
X
X/* --- File removal --- */
Xextern int _CDECL	unlink		_PROTO ((const char *));
Xextern int _CDECL	remove		_PROTO ((const char *));
Xextern int _CDECL	rmdir		_PROTO ((char *));
X
X/* --- File characteristics --- */
Xextern int _CDECL	access		_PROTO ((char *, int));
Xextern int _CDECL	chown		_PROTO ((char *, uid_t, gid_t));
Xextern long _CDECL	tell 		_PROTO ((int));
X
X/* --- Configurable pathname variables --- */
Xextern long _CDECL	pathconf	_PROTO ((char *, int));
Xextern long _CDECL	fpathconf	_PROTO ((int, int));
X
X/* --- Pipes --- */
Xextern int _CDECL	pipe		_PROTO ((int[2]));
X
X/* --- File descriptor manipulation --- */
Xextern int _CDECL	dup		_PROTO ((int));
Xextern int _CDECL	dup2		_PROTO ((int, int));
X
X/* --- File descriptor deassignment --- */
Xextern int _CDECL	close		_PROTO ((int));
X
X/* --- Input and output --- */
Xextern int _CDECL	read		_PROTO ((int, char *, unsigned int));
Xextern int _CDECL	write		_PROTO ((int, char *, unsigned int));
X
X/* --- Control operations on files --- */
Xextern off_t _CDECL	lseek		_PROTO ((int, off_t, int));
X#endif
SHAR_EOF
chmod 0644 include/unistd.h || echo "restore of include/unistd.h fails"
set `wc -c include/unistd.h`;Sum=$1
if test "$Sum" != "5401"
then echo original size 5401, current size $Sum;fi
echo "x - extracting include/ms_dio.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > include/ms_dio.h &&
X/* ms_dio.h */
X#ifndef _MS_DIO_H
X#define _MS_DIO_H
X
X/*
X * This is only required under MSDOS
X */
X
X#ifdef MSDOS
X#include <sys/proto.h>
X
Xextern int _CDECL	dio_write	_PROTO ((int, char *, unsigned int));
Xextern int _CDECL	dio_read	_PROTO ((int, char *, unsigned int));
Xextern int _CDECL	dio_open	_PROTO ((char *, int, ...));
Xextern int _CDECL	dio_close	_PROTO ((int));
Xextern long _CDECL	dio_lseek	_PROTO ((int, long, int));
Xextern int _CDECL	dio_fstat	_PROTO ((int , struct stat *));
Xextern int _CDECL	dio_stat	_PROTO ((char *, struct stat *));
Xextern int _CDECL	dio_access	_PROTO ((char *, int));
Xextern int _CDECL	dio_chmod	_PROTO ((char *, int));
Xextern int _CDECL	dio_creat	_PROTO ((char *, int));
Xextern int _CDECL	dio_dup		_PROTO ((int));
Xextern int _CDECL	dio_isatty	_PROTO ((int));
Xextern long _CDECL	dio_tell	_PROTO ((int));
X
X#define open		dio_open
X#define close(a)	dio_close (a)
X#define read(a,b,c)	dio_read (a,b,c)
X#define write(a,b,c)	dio_write (a,b,c)
X#define lseek(a,b,c)	dio_lseek (a,b,c)
X#define fstat(a,b)	dio_fstat (a,b)
X#define stat(a,b)	dio_stat (a,b)
X#define access(a, b)	dio_access (a,b)
X#define chmod(a, b)	dio_chmod (a,b)
X#define creat(a, b)	dio_creat (a,b)
X#define dup(a)		dio_dup (a)
X#define isatty(a)	dio_isatty (a)
X#define tell(a)		dio_tell (a)
X#endif
X#endif
SHAR_EOF
chmod 0644 include/ms_dio.h || echo "restore of include/ms_dio.h fails"
set `wc -c include/ms_dio.h`;Sum=$1
if test "$Sum" != "1284"
then echo original size 1284, current size $Sum;fi
echo "x - extracting lib/ms_dio.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > lib/ms_dio.c &&
X/* MS-DOS Direct Disk I/O
X *
X * MS-DOS Direct Disk I/O - Copyright (c) 1989 Data Logic Limited.
X *
X * dio_read and dio_write based on original code copyrighted (c) 1989
X * Harold G. Walters.
X *
X * The rest of the code has been written from scatch to support multiple disk
X * access and provide a consistant interface from normal I/O operations.
X *
X * The devices supported are:
X *
X *	/dev/hdxy	- Hard disk drive x parition y (x = 0 to 9, y =
X *			  0 to 9, where 0 is the whole disk).
X *	/dev/fdx	- Floppy drive x (x = 0 to 9).
X *	/dev/kmem	- Memory driver
X *
X * It does its best to determine what type of disk you are reading.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice is duplicated in the
X * source form.
X */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <errno.h>
X#include <dos.h>
X#include <fcntl.h>
X#include <ctype.h>
X#include <unistd.h>
X#include <time.h>
X#include <ms_dio.h>
X
X#undef open
X#undef close
X#undef read
X#undef write
X#undef lseek
X#undef fstat
X#undef stat
X#undef access
X#undef chmod
X#undef creat
X#undef dup
X#undef isatty
X#undef tell
X
X#define SECSIZ		512
X#define	MS_MODIFIER	30000
X#define BIOS_READ	0x2
X#define BIOS_WRITE	0x3
X#define HD_FLAG		0x80		/* Hard disk flag		*/
X#define MEGABYTE	1048576L
X#define DRIVE_RAM	20
X
X#ifdef __STDC__
Xstatic int		dio_do (int, struct fs *, char *, long, unsigned int);
Xstatic struct fs	*dio_fpcheck (int);
Xstatic int		dio_fncheck (char *);
X#else
Xstatic int		dio_do ();
Xstatic struct fs	*dio_fpcheck ();
Xstatic int		dio_fncheck ();
X#endif
X
Xstatic struct fs {
X    int		mode;			/* Open mode			*/
X    int		drive;
X    int		partition;		/* Hard disk partition number	*/
X    off_t	location;		/* Current offset		*/
X    long	m_start;		/* Offset for partition		*/
X    long	m_cyl;			/* Max cylinders		*/
X    int		m_head;			/* Max heads			*/
X    int		m_sector;		/* Max sectors			*/
X    long	m_scount;		/* Total sectors per disk	*/
X} *MS_io_fs[_NFILE];
X
Xstruct partition {
X    long	f_type;			/* Type flags			*/
X    long	f_status;		/* Status flags			*/
X    long	offset;			/* Offset in sectors		*/
X    long	size;			/* Size in sectors		*/
X};
X
Xstatic int	fs_init = 0;
X
X/* Do the actual read/write to the disk.  This function is not used
X * for the RAM drive
X */
X
Xstatic int	dio_do (type, FP, buf, secnum, secknt)
Xint		type;
Xstruct fs	*FP;
Xchar		*buf;
Xlong		secnum;
Xunsigned int	secknt;
X{
X    int			i, j;
X    int			nsec, cyl;
X    long		asec;
X    union REGS		reg;
X#if defined(M_I86LM)
X    struct SREGS	sreg;
X#endif
X
X    for (j = 0; j < secknt; j += nsec, buf += (nsec * SECSIZ), secnum += nsec)
X    {
X
X/* Check for space - end of drive */
X
X	if (secnum > FP->m_scount)
X	{
X	    errno = ENOSPC;
X	    return j * SECSIZ;
X	}
X
X/* Calculate the number of sectors left on the track */
X
X	asec = FP->m_start + secnum;
X
X	if (((asec % FP->m_sector) + (secknt - j)) > FP->m_sector)
X	    nsec = (int)(FP->m_sector - (asec % FP->m_sector));
X
X	else
X	    nsec = secknt - j;
X
X/* Read/write it three times */
X
X	for (i = 0; i < 3; i++)
X	{
X	    reg.h.ah = (unsigned char)type;
X	    reg.h.al = (unsigned char)nsec;
X	    reg.h.dl = (unsigned char)FP->drive;
X
X	    cyl      = (int)(asec / (FP->m_head * FP->m_sector));
X	    reg.h.cl = (unsigned char)((((asec % FP->m_sector) + 1) & 0x03f) |
X			((cyl & 0x0300) >> 2));
X	    reg.h.ch = (unsigned char)(cyl & 0xff);
X	    reg.h.dh = (unsigned char)((asec % (FP->m_head * FP->m_sector)) / FP->m_sector);
X
X
X#if defined(M_I86LM)
X	    reg.x.bx = FP_OFF(buf);
X	    sreg.es = FP_SEG(buf);
X	    int86x (0x13, &reg, &reg, &sreg);
X#else
X	    reg.x.bx = (int) buf;
X	    int86 (0x13, &reg, &reg);
X#endif
X
X	    if (!reg.x.cflag)
X		break;
X	}
X
X/* Check for failure */
X
X	if (i == 3)
X	{
X	    errno = EIO;
X	    return -1;
X	}
X    }
X
X    return secknt * SECSIZ;
X}
X
X/* Write function */
X
Xint		dio_write (fp, from_buf, from_cnt)
Xint		fp;			/* File handler			*/
Xchar		*from_buf;		/* Output buffer		*/
Xunsigned int	from_cnt;		/* Number of bytes to write	*/
X{
X    unsigned int	amt = 0;
X    unsigned int	err = 0;
X    long		fquo;
X    unsigned int	frem;
X    unsigned int	cquo = 0;
X    unsigned int	crem = 0;
X    struct fs		*FP;
X    char		buffer[SECSIZ];
X
X/* Direct IO or normal */
X
X    if (fp < MS_MODIFIER)
X	return write (fp, from_buf, from_cnt);
X
X    if (((FP = dio_fpcheck (fp)) == (struct fs *)NULL) ||
X	((FP->mode & 0x03) == O_RDONLY))
X    {
X	errno = EBADF;
X	return -1;
X    }
X
X/* If RAM - just copy */
X
X    if (FP->drive == DRIVE_RAM)
X    {
X	char huge 	*cp = (char huge *)from_buf;
X	char huge 	*sp = (char huge *)(((FP->location & 0x0ffff0L) << 12L)
X						| (FP->location & 0x0fL));
X
X	amt = from_cnt;
X	while (amt--)
X	    *(sp++) = *(cp++);
X
X	return from_cnt;
X    }
X
X/* If the current location is not a sector boundary - read in the current
X * sector and write a bit at the end to move to the boundary
X */
X
X    fquo = FP->location / SECSIZ;
X    frem = (unsigned int) (FP->location % SECSIZ);
X
X    if (frem > 0)
X    {
X	if ((err = dio_do (BIOS_READ, FP, buffer, fquo, 1)) != SECSIZ)
X	    return err;
X
X	if ((amt = SECSIZ - frem) > from_cnt)
X	    amt = from_cnt;
X
X/* Update the buffer with the bit at the end */
X
X	memcpy (&buffer[frem], from_buf, amt);
X
X	if ((err = dio_do (BIOS_WRITE, FP, buffer, fquo, 1)) != SECSIZ)
X	    return err;
X
X/* Increment the location */
X
X	FP->location += amt;
X
X	if (SECSIZ - frem <= from_cnt)
X	    fquo++;
X
X	from_buf += amt;
X	from_cnt -= amt;
X    }
X
X/* Calculate the number of full sectors to process now we are on a sector
X * boundary
X */
X
X    cquo = from_cnt / SECSIZ;
X    crem = from_cnt % SECSIZ;
X
X    if (cquo > 0)
X    {
X	if ((err = dio_do (BIOS_WRITE, FP, from_buf, fquo, cquo)) !=
X	    (cquo * SECSIZ))
X	{
X	    if (err > 0)
X		FP->location += err;
X
X	    return err;
X	}
X
X	amt += (cquo * SECSIZ);
X	FP->location += (cquo * SECSIZ);
X	fquo += cquo;
X	from_buf += (cquo * SECSIZ);
X	from_cnt -= (cquo * SECSIZ);
X    }
X
X/* Is there still more - read in the next sector, update first half and
X * re-write
X */
X
X    if (crem > 0)
X    {
X	if ((err = dio_do (BIOS_READ, FP, buffer, fquo, 1)) != SECSIZ)
X	    return err;
X
X	memcpy (buffer, from_buf, crem);
X
X	if ((err = dio_do (BIOS_WRITE, FP, buffer, fquo, 1)) != SECSIZ)
X	    return err;
X
X	amt += crem;
X	FP->location += crem;
X    }
X
X    return amt;
X}
X
X/* Read function */
X
Xint		dio_read (fp, to_buf, to_cnt)
Xint		fp;			/* File handler			*/
Xchar		*to_buf;		/* Input buffer			*/
Xunsigned int	to_cnt;			/* Number of bytes to read	*/
X{
X    unsigned int	amt = 0;
X    unsigned int	err = 0;
X    long		fquo;
X    unsigned int	frem;
X    unsigned int	cquo = 0;
X    unsigned int	crem = 0;
X    struct fs		*FP;
X    char		buffer[SECSIZ];
X
X/* Direct IO or normal */
X
X    if (fp < MS_MODIFIER)
X	return read (fp, to_buf, to_cnt);
X
X    if (((FP = dio_fpcheck (fp)) == (struct fs *)NULL) ||
X	((FP->mode & 0x03) == O_WRONLY))
X    {
X	errno = EBADF;
X	return -1;
X    }
X
X/* If RAM - just copy */
X
X    if (FP->drive == DRIVE_RAM)
X    {
X	char huge 	*cp = (char huge *)to_buf;
X	char huge 	*sp = (char huge *)(((FP->location & 0x0ffff0L) << 12L)
X						| (FP->location & 0x0f));
X
X
X	amt = to_cnt;
X	while (amt--)
X	    *(cp++) = *(sp++);
X
X	return to_cnt;
X    }
X
X    fquo = FP->location / SECSIZ;
X    frem = (unsigned int) (FP->location % SECSIZ);
X
X    if (frem > 0)
X    {
X	if ((err = dio_do (BIOS_READ, FP, buffer, fquo, 1)) != SECSIZ)
X	    return err;
X
X	if ((amt = SECSIZ - frem) > to_cnt)
X	    amt = to_cnt;
X
X	memcpy (to_buf, &buffer[frem], amt);
X
X	FP->location += amt;
X	if (SECSIZ - frem <= to_cnt)
X	    fquo++;
X
X	to_buf += amt;
X	to_cnt -= amt;
X    }
X
X    cquo = to_cnt / SECSIZ;
X    crem = to_cnt % SECSIZ;
X
X    if (cquo > 0)
X    {
X	if ((err = dio_do (BIOS_READ, FP, to_buf, fquo, cquo)) !=
X	    (cquo * SECSIZ))
X	{
X	    if (err > 0)
X		FP->location += err;
X
X	    return err;
X	}
X
X	amt += (cquo * SECSIZ);
X	FP->location += (cquo * SECSIZ);
X	fquo += cquo;
X	to_buf += (cquo * SECSIZ);
X	to_cnt -= (cquo * SECSIZ);
X    }
X
X/* Do we still need a partial sector ? */
X
X    if (crem > 0)
X    {
X	if ((err = dio_do (BIOS_READ, FP, buffer, fquo, 1)) != SECSIZ)
X	    return err;
X
X	memcpy (to_buf, buffer, crem);
X	amt += crem;
X	FP->location += crem;
X    }
X
X    return (amt);
X}
X
Xint	dio_open (name, mode, permissions)
Xchar	*name;
Xint	mode;
Xmode_t	permissions;
X{
X    struct fs	*FP;
X    int		fp, i, j;
X    int		drive, ndrive;
X    union REGS	iregs;
X    char	buf[SECSIZ];
X
X/* Check for initialisation */
X
X    if (!(fs_init++))
X	memset (MS_io_fs, 0, sizeof (struct fs *) * _NFILE);
X
X/* Direct I/o file name */
X
X    if ((drive = dio_fncheck (name)) != -1)
X    {
X	for (fp = 0; (fp < _NFILE) && (MS_io_fs[fp] != (struct fs *)NULL); fp++)
X	    ;
X
X/* Check for available entry and space */
X
X	if ((fp == _NFILE) ||
X	    ((FP = (struct fs *)malloc (sizeof (struct fs))) == (struct fs *)NULL))
X	{
X	    errno = ENFILE;
X	    return -1;
X	}
X
X	FP->location = 0L;
X	FP->mode = mode;
X
X/* RAM access ? */
X
X	if (drive == DRIVE_RAM)
X	{
X	    FP->drive    = drive;
X	    MS_io_fs[fp] = FP;
X	    return fp + MS_MODIFIER;
X	}
X
X	if (drive & HD_FLAG)
X	{
X	    ndrive	  = (drive & (~HD_FLAG));
X	    FP->partition = ndrive % 10;
X	    ndrive	  /= 10;
X	    FP->drive     = ndrive | HD_FLAG;
X	    FP->m_start   = 0L;		/* Offset for partition		*/
X	}
X
X	else
X	{
X	    FP->drive     = drive;
X	    ndrive        = drive;
X	    FP->partition = 0;
X	    FP->m_start   = 0L;		/* Offset for partition		*/
X	}
X
X
X/* Reset the drive */
X
X	iregs.h.ah = 0;
X	iregs.h.dl = (unsigned char)FP->drive;
X	int86 (0x13, &iregs, &iregs);
X
X/* Get the drive parameters */
X
X	iregs.h.ah = 0x08;
X	iregs.h.dl = (unsigned char)FP->drive;
X	int86 (0x13, &iregs, &iregs);
X
X/* Check for hard disk */
SHAR_EOF
echo "End of part 1"
echo "File lib/ms_dio.c is continued in part 2"
echo "2" > s2_seq_.tmp
exit 0

-- 
Regards,

Ian Stewartson
Data Logic Ltd.