[comp.sources.misc] v16i078: MSDOS Shell

istewart@datlog.co.uk (Ian Stewartson) (01/17/91)

Submitted-by: istewart@datlog.co.uk (Ian Stewartson)
Posting-number: Volume 16, Issue 78
Archive-name: ms_sh-1.6/patch01
Patch-To: ms_sh-1.6: Volume 12, Issue 19-26

1.6.4 of the MSDOS Shell.  Unfortunately, I'm tied up with real work
at the moment, so this is likely to be the last upgrade for a couple
of months.

It fixes one or two bugs and provides some new feature from the
Korn/POSIX shell (see release notes).

Regards,

Ian Stewartson
Data Logic

-------
#!/bin/sh
# This is a shell archive (shar 3.46)
# made 12/24/1990 18:01 UTC by istewart@dlvax2
# Source directory /usr/proj1/ssd/istewart/src/shell
#
# existing files will NOT be overwritten unless -c is specified
#
# This is part 1 of a multipart archive                                    
# do not concatenate these parts, unpack them in order with /bin/sh        
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#  63614 -rw-r--r-- Patch1.6.4
#
if test -r _shar_seq_.tmp; then
	echo 'Must unpack archives in sequence!'
	echo Please unpack part `cat _shar_seq_.tmp` next
	exit 1
fi
# ============= Patch1.6.4 ==============
if test -f 'Patch1.6.4' -a X"$1" != X"-c"; then
	echo 'x - skipping Patch1.6.4 (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting Patch1.6.4 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Patch1.6.4' &&
Index: Notes1.6
*** ../sh16.3/Notes1.6	Fri Aug 17 21:29:59 1990
--- Notes1.6	Tue Nov  6 20:47:31 1990
***************
*** 1,4 ****
! Version 1.6.3 Release Notes:
X  
X  Note: Release 1.6.1 did occur to comp.ibm.pc.binaries.  However, the
X  transmission was corrupt and by the time I was notified (the moderator having
--- 1,4 ----
! Version 1.6.4 Release Notes:
X  
X  Note: Release 1.6.1 did occur to comp.ibm.pc.binaries.  However, the
X  transmission was corrupt and by the time I was notified (the moderator having
***************
*** 41,47 ****
X  	The code has been fixed to cope with DOS 4.
X    21.	A bug in the processing of functions has been fixed which caused
X  	the shell to crash or hang has been fixed.
! 
X  The following enhancements have been made:
X  
X     1.   /dev/tty and /dev/null are mapped to /dev/con and /dev/nul internally
--- 41,48 ----
X  	The code has been fixed to cope with DOS 4.
X    21.	A bug in the processing of functions has been fixed which caused
X  	the shell to crash or hang has been fixed.
!   22.	A bug in the function code that caused case functions to hang
! 	has been fixed.
X  The following enhancements have been made:
X  
X     1.   /dev/tty and /dev/null are mapped to /dev/con and /dev/nul internally
***************
*** 78,83 ****
--- 79,87 ----
X     20.  The POSIX variable substitution command ${#name} to give the
X  	string length has been implemented.
X     21.  The POSIX I/O option <> has been implemented.
+    22.  The POSIX I/O options ${#*%} and ~ have been implemented.
+    23.  The builtin command command has been implemented.
+    24.  The source for stdargv.c has been modified to work under OS/2
X  
X  The following enhancements/bugs remain outstanding:
X  
***************
*** 93,98 ****
--- 97,108 ----
X  	processing of escape characters.  The shell uses the 8-bit to
X  	mark escaped characters (Release 1.7).
X      
+     3.  Interrupting a disk swap at the wrong time may cause the shell to
+ 	hang.  I've tried disabling Control-Break during disk read/writes
+ 	but this only causes the shell to hang on re-load every time in
+ 	some environments.  In the next release, I'm going to put in some
+ 	checks and issue re-read/writes when necessary.
+     
X  Thanks are due to
X  
X      Greg Yachuk 
***************
*** 101,106 ****
--- 111,117 ----
X      John B Thiel 
X      Harry McGavran 
X      Bill Davidsen
+     Richard J Reiner
X  
X  for their comments, fixes, tolerance etc in testing release 1.6
X  
Index: lib/stdargv.c
*** ../sh16.3/lib/stdargv.c	Fri Mar  2 11:34:58 1990
--- lib/stdargv.c	Tue Nov  6 20:52:05 1990
***************
*** 18,25 ****
X   *			This function replaces the standard MS-DOS command
X   *			line processing function (_setargv in stdargv.obj).
X   *
!  *  CALLING SEQUENCE:	The following calling sequences are used:
X   *
X   *			void	_setargv ();
X   *
X   *  ERROR MESSAGES:	Out of memory
--- 18,27 ----
X   *			This function replaces the standard MS-DOS command
X   *			line processing function (_setargv in stdargv.obj).
X   *
!  *			Support for OS2 added.  Compile with -DOS2
X   *
+  *  CALLING SEQUENCE:	The following calling sequences are used:
+  *
X   *			void	_setargv ();
X   *
X   *  ERROR MESSAGES:	Out of memory
***************
*** 32,45 ****
X  #include <stdio.h>			/* Standard I/O delarations         */
X  #include <stdlib.h>			/* Standard library functions       */
X  #include <errno.h>			/* Error number declarations        */
X  #include <dos.h>			/* DOS functions declarations       */
X  #include <bios.h>			/* BIOS functions declarations      */
X  #include <ctype.h>			/* Character type declarations      */
X  #include <string.h>			/* String library functions         */
X  #include <limits.h>			/* String library functions         */
X  #include <fcntl.h>			/* File Control Declarations        */
- #include <io.h>				/* Input/Output Declarations        */
X  #include <dirent.h>			/* Direction I/O functions	    */
X  
X  /*
X   *  DATA DEFINITIONS:
--- 34,51 ----
X  #include <stdio.h>			/* Standard I/O delarations         */
X  #include <stdlib.h>			/* Standard library functions       */
X  #include <errno.h>			/* Error number declarations        */
+ #ifdef OS2
+ #include <os2.h>			/* OS2 functions declarations       */
+ #else
X  #include <dos.h>			/* DOS functions declarations       */
X  #include <bios.h>			/* BIOS functions declarations      */
+ #endif
X  #include <ctype.h>			/* Character type declarations      */
X  #include <string.h>			/* String library functions         */
X  #include <limits.h>			/* String library functions         */
X  #include <fcntl.h>			/* File Control Declarations        */
X  #include <dirent.h>			/* Direction I/O functions	    */
+ #include <unistd.h>
X  
X  /*
X   *  DATA DEFINITIONS:
***************
*** 65,76 ****
--- 71,90 ----
X  static void	ex_fatal (int, char *, char *);	/* Fatal error processing*/
X  static char	*ex_environment (char *);	/* Process environment	*/
X  static char	*_ex_multi_drive (char *);	/* Check for multidrive	*/
+ static int	N_floppy_disks (void);
X  static char	*ex_nomem = "%s: %s\n";
X  
X  extern char far	*_pgmptr; 		/* Program name			*/
X  extern char	**__argv; 		/* Current argument address	*/
X  extern int	__argc; 		/* Current argument count	*/
X  
+ #ifdef OS2
+ static void	 _dos_setdrive (unsigned int, unsigned int *);
+ static void	 _dos_getdrive (unsigned int *);
+ extern ushort	_aenvseg;		/* Environment seg		*/
+ extern ushort	_acmdln;		/* Command line offset		*/
+ #endif
+ 
X  /*
X   *  MODULE ABSTRACT: _setargv
X   *
***************
*** 79,92 ****
X  
X  void	_setargv ()
X  {
X  					/* Set up pointer to command line */
X      char far		*argvp = (char far *)((((long)_psp) << 16) + 0x081L);
X      unsigned int	envs = *(int far *)((((long)_psp) << 16) + 0x02cL);
X      char far		*s; 		/* Temporary string pointer    	*/
! #ifndef M_I86LM
X      char		buf[MAX_LINE];	/* Temporary space		*/
X      char		*cp;
! #endif
X  
X  /* Command line can be null or 0x0d terminated - convert to null */
X  
--- 93,131 ----
X  
X  void	_setargv ()
X  {
+ #ifdef OS2
+     char far		*argvp = (char far *)((((long)_aenvseg) << 16));
+     ushort		off = _acmdln;
+ 
+     while (--off)
+     {
+ 	if (argvp[off - 1] == 0)
+  	    break;
+     }
+ 
+ /* Add program name */
+ 
+     _pgmptr =  &argvp[off];
+ 
+     if (argvp[_acmdln] == 0)
+ 	ex_add_arg (ex_tounix (_pgmptr));	/* Add the program name	*/
+ 
+     else
+     {
+ 	argvp += _acmdln;
+ 	ex_add_arg (ex_tounix (argvp));		/* Add the program name	*/
+ 	argvp += strlen (argvp) + 1;
+ 	exp_line (argvp);
+     }
+ #else
X  					/* Set up pointer to command line */
X      char far		*argvp = (char far *)((((long)_psp) << 16) + 0x081L);
X      unsigned int	envs = *(int far *)((((long)_psp) << 16) + 0x02cL);
X      char far		*s; 		/* Temporary string pointer    	*/
! #  ifndef M_I86LM
X      char		buf[MAX_LINE];	/* Temporary space		*/
X      char		*cp;
! #  endif
X  
X  /* Command line can be null or 0x0d terminated - convert to null */
X  
***************
*** 123,129 ****
X  
X      _pgmptr = s;
X  
! #ifndef M_I86LM
X      cp = buf;
X      while (*(cp++) = *(s++));
X  
--- 162,168 ----
X  
X      _pgmptr = s;
X  
! #  ifndef M_I86LM
X      cp = buf;
X      while (*(cp++) = *(s++));
X  
***************
*** 134,142 ****
X      while (*(cp++) = *(s++));
X  
X      exp_line (buf);
! #else
X      ex_add_arg (ex_tounix (s));		/* Add the program name		*/
X      exp_line (argvp);
X  #endif
X  
X      ex_add_arg ((char *)NULL);
--- 173,182 ----
X      while (*(cp++) = *(s++));
X  
X      exp_line (buf);
! #  else
X      ex_add_arg (ex_tounix (s));		/* Add the program name		*/
X      exp_line (argvp);
+ #  endif
X  #endif
X  
X      ex_add_arg ((char *)NULL);
***************
*** 262,268 ****
X  
X  /* Check to see if the second diskette drive is really there */
X  
! 	    if (((_bios_equiplist () & 0x00c0) == 0x0000) && (s_drive == 2))
X  		continue;
X  
X  /* If the drive exists and is in our list - process it */
--- 302,308 ----
X  
X  /* Check to see if the second diskette drive is really there */
X  
! 	    if ((N_floppy_disks () < 2) && (s_drive == 2))
X  		continue;
X  
X  /* If the drive exists and is in our list - process it */
***************
*** 619,623 ****
--- 659,703 ----
X      }
X  
X      return (*prefix && (*(prefix + 1) == ':')) ? prefix + 1 : (char *)NULL;
+ }
+ 
+ /* Some OS/2 functions to emulate the DOS functions */
+ 
+ #ifdef OS2
+ static void	 _dos_getdrive (cdp)
+ unsigned int	*cdp;
+ {
+     USHORT	cdr;
+     ULONG	ndr;
+ 
+     DosQCurDisk((PUSHORT)&cdr, (PULONG) &ndr);
+     *cdp = (unsigned int)cdr;
+ }
+ 
+ static void	 _dos_setdrive (cdr, ndp)
+ unsigned int	cdr;
+ unsigned int	*ndp;
+ {
+     USHORT	dummy;
+     ULONG	ndr;
+ 
+     DosQCurDisk((PUSHORT)&dummy, (PULONG) &ndr);
+     *ndp = (unsigned int)ndr;
+ 
+     DosSelectDisk ((USHORT)cdr);
+ }
+ #endif
+ 
+ /* Return the number of floppy disks */
+ 
+ static	int	N_floppy_disks ()
+ {
+ #ifdef OS2
+     BYTE	nflop = 1;
+     DosDevConfig (&nflop, 2, 0);
+     return nflop;
+ #else
+     return ((_bios_equiplist () & 0x00c0) >> 6) + 1;
+ #endif
X  }
X  #endif
Index: sh.1
Prereq: 1.11
*** ../sh16.3/sh.1	Fri Aug 17 21:31:41 1990
--- sh.1	Tue Nov  6 20:11:17 1990
***************
*** 14,22 ****
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  .\"
! .\"    $Header: C:/SRC/SHELL/RCS/sh.1 1.11 90/08/14 23:17:25 Ian_Stewartson Exp $
X  .\"
X  .\"    $Log:	sh.1 $
X  .\"	Revision 1.11  90/08/14  23:17:25  Ian_Stewartson
X  .\"	Add IO read/write open
X  .\"	
--- 14,26 ----
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  .\"
! .\"    $Header: D:/SRC/SHELL/RCS/sh.1 1.12 90/11/06 20:08:46 Ian_Stewartson Exp $
X  .\"
X  .\"    $Log:	sh.1 $
+ .\"	Revision 1.12  90/11/06  20:08:46  Ian_Stewartson
+ .\"	Add POSIX options {#%*} and ~
+ .\"	Add builtin command
+ .\"	
X  .\"	Revision 1.11  90/08/14  23:17:25  Ian_Stewartson
X  .\"	Add IO read/write open
X  .\"	
***************
*** 163,172 ****
X  .SS Comments
X  A word beginning with \fB#\fR causes that word and all the following
X  characters up to a new-line to be ignored.
X  .SS Command Substitution
! The standard output from a command enclosed in a pair of grave accents
! (\fB\(ga\(ga\fR) may be used as part or all of a word; trailing new-lines
! are removed.
X  .SS Parameter Substitution
X  The character \fB$\fR is used to introduce substitutable \fIparameters\fR.
X  There are two types of parameters, positional and keyword.  If \fIparameter\fR
--- 167,179 ----
X  .SS Comments
X  A word beginning with \fB#\fR causes that word and all the following
X  characters up to a new-line to be ignored.
+ .SS Tilde Substitution
+ Each word is checked to see if it begins with an unquoted\fB~\fR.  If it is,
+ the \fB~\fR is replaced by the value of the \fBHOME\fR parameter.	
X  .SS Command Substitution
! The standard output from a command enclosed in parenthesis preceded by a
! dollar sign (\fB$()\fR), or in a pair of grave accents (\fB\(ga\(ga\fR) may
! be used as part or all of a word; trailing new-lines are removed.
X  .SS Parameter Substitution
X  The character \fB$\fR is used to introduce substitutable \fIparameters\fR.
X  There are two types of parameters, positional and keyword.  If \fIparameter\fR
***************
*** 184,196 ****
X  .PD 0
X  .TP
X  \fB${\fIparameter\fB}\fR
! The value, if any, of the parameter is substituted.  The braces are required
! only when \fIparameter\fR is followed by a letter, digit, or underscore that
! is not to be interpreted as part of its name.  If \fIparameter\fR is
! \fB*\fR or \fB@\fR, all the positional parameters, starting with \fB$1\fR,
! are substituted (separated by spaces).  Parameter \fB$0\fR is set from argument
! zero when the shell is invoked.
X  .TP
X  \fB${\fIparameter\fB:-\fIword\fB}\fR
X  If \fIparameter\fR is set and is non-null, substitute its value; otherwise
X  substitute \fIword\fR.
--- 191,208 ----
X  .PD 0
X  .TP
X  \fB${\fIparameter\fB}\fR
! The value, if any, of the \fIparameter\fR is substituted.  The braces are
! required only when \fIparameter\fR is followed by a letter, digit, or
! underscore that is not to be interpreted as part of its name.  If
! \fIparameter\fR is \fB*\fR or \fB@\fR, all the positional parameters, starting
! with \fB$1\fR, are substituted (separated by spaces).  Parameter \fB$0\fR is
! set from argument zero when the shell is invoked.
X  .TP
+ \fB${#\fIparameter\fB}\fR
+ If \fIparameter\fR is \fB*\fR or \fB@\fR, the number of positional parameters
+ is substituted.  Otherwise, the length of the value of the \fIparameter\fR is
+ substituted.
+ .TP
X  \fB${\fIparameter\fB:-\fIword\fB}\fR
X  If \fIparameter\fR is set and is non-null, substitute its value; otherwise
X  substitute \fIword\fR.
***************
*** 208,213 ****
--- 220,242 ----
X  \fB${\fIparameter\fB:+\fIword\fB}\fR
X  If \fIparameter\fR is set and is non-null, substitute \fIword\fR; otherwise
X  substitute nothing.
+ .TP
+ \fB${\fIparameter\fB#\fIpattern\fB}\fR
+ \fB${\fIparameter\fB##\fIpattern\fB}\fR
+ If the Shell \fIpattern\fR matches the beginning of the value of
+ \fIparameter\fR, then the value of this substitution is the value of the
+ \fIparameter\fR with the matched portion deleted; otherwise the value of
+ this \fIparameter\fR is substituted.  In the first form the smallest matching
+ \fIpattern\fR is deleted and in the latter form the largest matching
+ \fIpattern\fR is deleted.
+ .TP
+ \fB${\fIparameter\fB%\fIpattern\fB}\fR
+ \fB${\fIparameter\fB%%\fIpattern\fB}\fR
+ If the Shell \fIpattern\fR matches the end of the value of \fIparameter\fR,
+ then the value of this substitution is the value of the \fIparameter\fR with
+ the matched portion deleted; otherwise the value of this \fIparameter\fR is
+ substituted.  In the first form the smallest matching \fIpattern\fR is deleted
+ and in the latter form the largest matching \fIpattern\fR is deleted.
X  .PD
X  .PP
X  In the above, \fIword\fR is not evaluated unless it is to be used as the
***************
*** 830,835 ****
--- 859,886 ----
X  Exit from the enclosing \fBfor\fR or \fBwhile\fR loop, if any.  If \fIn\fR is
X  specified, break \fIn\fR levels.
X  .TP
+ \fBbuiltin\fR \*(OK \fIargs\fR ... \*(CK
+ Force the selection of the \fBbuiltin\fR version of a command.  The builtin
+ shell command selected by the first \fIargs\fR value is executed with the
+ parameters defined by the remaining \fIargs\fRs.  If no arguments are given,
+ a list of all \fIbuiltin\fR commands is printed.
+ .sp
+ If the first argument is one of the following, the processing of the
+ builtin command in the following arguments are changed as indicated:
+ .RS
+ .TP
+ \fB-a\fR
+ Set the following builtin commands to use builtin version in preference to
+ any function or external versions.
+ .TP
+ \fB-d\fR
+ Set the following builtin commands to use the function or external version
+ in preference to the builtin version.
+ .TP
+ \fB-s\fR
+ Display the current status of the following builtin commands.
+ .RE
+ .TP
X  \fBcontinue\fR \*(OK \fIn\fR \*(CK
X  Resume 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.
***************
*** 986,992 ****
X  \fBmsdos\fR \*(OK \fIname\fR ... \*(CK
X  The given \fIname\fRs are marked \fImsdos\fR format and if the \fB-m\fR flag
X  is set, the values of the these \fIname\fRs are exported to child processes
! with any slashes in the value replaced by backslashes.
X  .TP
X  \fBpwd\fR
X  Print the current working directory.  
--- 1037,1044 ----
X  \fBmsdos\fR \*(OK \fIname\fR ... \*(CK
X  The given \fIname\fRs are marked \fImsdos\fR format and if the \fB-m\fR flag
X  is set, the values of the these \fIname\fRs are exported to child processes
! with any slashes in the value replaced by backslashes.  If no arguments are
! given, a list of all \fImsdos\fR names is printed.
X  .TP
X  \fBpwd\fR
X  Print the current working directory.  
Index: shell/sh.h
Prereq: 1.21
*** ../sh16.3/shell/sh.h	Fri Aug 17 21:33:20 1990
--- shell/sh.h	Tue Nov  6 19:18:37 1990
***************
*** 13,21 ****
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   *
!  *    $Header: C:/SRC/SHELL/RCS/sh.h 1.21 90/08/14 23:54:44 MS_user Exp $
X   *
X   *    $Log:	sh.h $
X   * Revision 1.21  90/08/14  23:54:44  MS_user
X   * Add addition value to env structure
X   * Add some new publics
--- 13,27 ----
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   *
!  *    $Header: D:/SRC/SHELL/RCS/sh.h 1.23 90/09/19 15:29:54 Ian_Stewartson Exp $
X   *
X   *    $Log:	sh.h $
+  * Revision 1.23  90/09/19  15:29:54  Ian_Stewartson
+  * Allow builtin commands to selected/de-selected
+  * 
+  * Revision 1.22  90/08/24  21:53:13  Ian_Stewartson
+  * Add support for POSIX macro command {x#y} and {x%y}
+  * 
X   * Revision 1.21  90/08/14  23:54:44  MS_user
X   * Add addition value to env structure
X   * Add some new publics
***************
*** 85,91 ****
X   * 
X   */
X  
! #define PATCHLEVEL	7
X  #define	LINE_MAX	1000	/* Command line length			*/
X  #define HISTORY_MAX	100	/* History array length			*/
X  				/* Space for full file name		*/
--- 91,97 ----
X   * 
X   */
X  
! #define PATCHLEVEL	8
X  #define	LINE_MAX	1000	/* Command line length			*/
X  #define HISTORY_MAX	100	/* History array length			*/
X  				/* Space for full file name		*/
***************
*** 168,179 ****
X  struct	builtin {
X      char	*command;
X      int		(*fn)(C_Op *);
X  };
X  
X  /*
!  * actions determining the environment of a process
X   */
X  
X  #define	FEXEC		0x0001	/* execute without forking		*/
X  
X  /* MSDOS Memory Control Block chain structure */
--- 174,193 ----
X  struct	builtin {
X      char	*command;
X      int		(*fn)(C_Op *);
+     int		mode;
X  };
X  
X  /*
!  * Valid values of mode
X   */
X  
+ #define BLT_ALWAYS	0x0001	/* Always use builtin version		*/
+ #define BLT_CURRENT	0x0002	/* Currently use builtin version	*/
+ 
+ /*
+  * actions determining the environment of a process
+  */
+ 
X  #define	FEXEC		0x0001	/* execute without forking		*/
X  
X  /* MSDOS Memory Control Block chain structure */
***************
*** 376,384 ****
X  					/* depth			*/
X  
X  /*
!  * Variable list
X   */
X  
X  typedef struct var {
X      char		*value;		/* Value			*/
X      char		*name;		/* Name				*/
--- 390,407 ----
X  					/* depth			*/
X  
X  /*
!  * Mode values for new gmatch 
X   */
X  
+ #define GM_ALL		0		/* Match full string		*/
+ #define GM_SHORTEST	1		/* Shortest prefix/suffix	*/
+ #define GM_LONGEST	2		/* Longest prefix/suffix	*/
+ 
+ /*
+ /*
+  * Variable list
+  */
+ 
X  typedef struct var {
X      char		*value;		/* Value			*/
X      char		*name;		/* Name				*/
***************
*** 531,537 ****
X  extern void	s_vstatus (Var_List *, int);
X  extern bool	isassign (char *);
X  extern bool	assign (char *, int);
! extern bool	gmatch (char *, char *, bool);
X  extern char	*getcell (unsigned int);
X  extern void	freecell (char *);
X  extern void	freearea (int);
--- 554,561 ----
X  extern void	s_vstatus (Var_List *, int);
X  extern bool	isassign (char *);
X  extern bool	assign (char *, int);
! extern bool	gmatch (char *, char *, bool, char **, int);
! extern bool	gmatch_suffix (char *, char *, bool, char **, int);
X  extern char	*getcell (unsigned int);
X  extern void	freecell (char *);
X  extern void	freearea (int);
***************
*** 574,580 ****
X  extern void	put_prompt (char *);
X  extern bool	eqname (char *, char *);
X  extern bool	any (char, char *);
! extern int	(*inbuilt (char *))();
X  extern char	*path_append (char *, char *, char *);
X  extern void	unset (char *, bool);
X  extern int	S_open (bool, char *, int, ...);
--- 598,604 ----
X  extern void	put_prompt (char *);
X  extern bool	eqname (char *, char *);
X  extern bool	any (char, char *);
! extern int	(*inbuilt (char *, bool *))();
X  extern char	*path_append (char *, char *, char *);
X  extern void	unset (char *, bool);
X  extern int	S_open (bool, char *, int, ...);
Index: shell/sh0.asm
Prereq: 1.10
*** ../sh16.3/shell/sh0.asm	Fri Aug 17 21:33:41 1990
--- shell/sh0.asm	Tue Nov  6 19:19:30 1990
***************
*** 16,22 ****
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  ;
! ;    $Header: C:/SRC/SHELL/RCS/sh0.asm 1.10 90/05/31 17:46:31 MS_user Exp $
X  ;
X  ;    $Log:	sh0.asm $
X  ;	Revision 1.10  90/05/31  17:46:31  MS_user
--- 16,22 ----
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  ;
! ;    $Header: D:/SRC/SHELL/RCS/sh0.asm 1.10 90/05/31 17:46:31 MS_user Exp $
X  ;
X  ;    $Log:	sh0.asm $
X  ;	Revision 1.10  90/05/31  17:46:31  MS_user
Index: shell/sh1.c
Prereq: 1.17
*** ../sh16.3/shell/sh1.c	Fri Aug 17 21:32:33 1990
--- shell/sh1.c	Tue Nov  6 19:20:30 1990
***************
*** 13,77 ****
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   *
!  *    $Header: C:/SRC/SHELL/RCS/sh1.c 1.17 90/08/14 23:32:53 MS_user Exp $
X   *
X   *    $Log:	sh1.c $
X   * Revision 1.17  90/08/14  23:32:53  MS_user
X   * Fix memory bugs - Add malloc checking functions for debug
X   * Make Convert_Backslashes public
!  * 
X   * Revision 1.16  90/05/31  09:48:06  MS_user
X   * Implement partial write when swapping to disk
X   * Add some signal lockouts to prevent corruption
!  * 
X   * Revision 1.15  90/05/15  21:08:59  MS_user
X   * Restore original directory on exit
!  * 
X   * Revision 1.14  90/04/25  22:33:28  MS_user
X   * Fix rsh check for PATH
!  * 
X   * Revision 1.13  90/04/25  09:18:12  MS_user
X   * Change version message processing
!  * 
X   * Revision 1.12  90/04/04  11:32:12  MS_user
X   * Change MAILPATH to use a semi-colon and not a colon for DOS
!  * 
X   * Revision 1.11  90/04/03  17:58:35  MS_user
X   * Stop shell exit from lowest level CLI
!  * 
X   * Revision 1.10  90/03/27  20:24:49  MS_user
X   * Fix problem with Interrupts not restoring std??? and clearing extended file
!  * 
X   * Revision 1.9  90/03/26  20:56:13  MS_user
X   * Change I/O restore so that "exec >filename" works
!  * 
X   * Revision 1.8  90/03/26  04:30:14  MS_user
X   * Remove original Interrupt 24 save address
!  * 
X   * Revision 1.7  90/03/12  20:16:22  MS_user
X   * Save program name for Initialisation file processing
!  * 
X   * Revision 1.6  90/03/09  16:05:33  MS_user
X   * Add build file name function and change the profile check to use it
!  * 
X   * Revision 1.5  90/03/06  16:49:14  MS_user
X   * Add disable history option
!  * 
X   * Revision 1.4  90/03/06  15:09:27  MS_user
X   * Add Unix PATH variable conversion
!  * 
X   * Revision 1.3  90/03/05  13:47:45  MS_user
X   * Get /etc/profile and profile order rigth
X   * Use $HOME/profile and not profile
X   * Check cursor position before outputing prompt
X   * Move some of processing in main to sub-routines
!  * 
X   * Revision 1.2  90/02/14  04:46:20  MS_user
X   * Add Interrupt 24 processing
!  * 
X   * Revision 1.1  90/01/25  13:40:39  MS_user
X   * Initial revision
!  * 
X   */
X  
X  #include <sys/types.h>
--- 13,83 ----
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   *
!  *    $Header: D:/SRC/SHELL/RCS/sh1.c 1.19 90/11/06 19:13:39 Ian_Stewartson Exp $
X   *
X   *    $Log:	sh1.c $
+  * Revision 1.19  90/11/06  19:13:39  Ian_Stewartson
+  * Add deletion of swap file on interrupt
+  * 
+  * Revision 1.18  90/08/24  21:54:05  Ian_Stewartson
+  * Add support for POSIX macro command {x#y} and {x%y}
+  * 
X   * Revision 1.17  90/08/14  23:32:53  MS_user
X   * Fix memory bugs - Add malloc checking functions for debug
X   * Make Convert_Backslashes public
!  *
X   * Revision 1.16  90/05/31  09:48:06  MS_user
X   * Implement partial write when swapping to disk
X   * Add some signal lockouts to prevent corruption
!  *
X   * Revision 1.15  90/05/15  21:08:59  MS_user
X   * Restore original directory on exit
!  *
X   * Revision 1.14  90/04/25  22:33:28  MS_user
X   * Fix rsh check for PATH
!  *
X   * Revision 1.13  90/04/25  09:18:12  MS_user
X   * Change version message processing
!  *
X   * Revision 1.12  90/04/04  11:32:12  MS_user
X   * Change MAILPATH to use a semi-colon and not a colon for DOS
!  *
X   * Revision 1.11  90/04/03  17:58:35  MS_user
X   * Stop shell exit from lowest level CLI
!  *
X   * Revision 1.10  90/03/27  20:24:49  MS_user
X   * Fix problem with Interrupts not restoring std??? and clearing extended file
!  *
X   * Revision 1.9  90/03/26  20:56:13  MS_user
X   * Change I/O restore so that "exec >filename" works
!  *
X   * Revision 1.8  90/03/26  04:30:14  MS_user
X   * Remove original Interrupt 24 save address
!  *
X   * Revision 1.7  90/03/12  20:16:22  MS_user
X   * Save program name for Initialisation file processing
!  *
X   * Revision 1.6  90/03/09  16:05:33  MS_user
X   * Add build file name function and change the profile check to use it
!  *
X   * Revision 1.5  90/03/06  16:49:14  MS_user
X   * Add disable history option
!  *
X   * Revision 1.4  90/03/06  15:09:27  MS_user
X   * Add Unix PATH variable conversion
!  *
X   * Revision 1.3  90/03/05  13:47:45  MS_user
X   * Get /etc/profile and profile order rigth
X   * Use $HOME/profile and not profile
X   * Check cursor position before outputing prompt
X   * Move some of processing in main to sub-routines
!  *
X   * Revision 1.2  90/02/14  04:46:20  MS_user
X   * Add Interrupt 24 processing
!  *
X   * Revision 1.1  90/01/25  13:40:39  MS_user
X   * Initial revision
!  *
X   */
X  
X  #include <sys/types.h>
***************
*** 528,534 ****
X  
X      Clear_Swap_File ();
X  
! /* If this is a command only - restore the directory because DOS doesn't 
X   * and the user might expect it
X   */
X  
--- 534,540 ----
X  
X      Clear_Swap_File ();
X  
! /* If this is a command only - restore the directory because DOS doesn't
X   * and the user might expect it
X   */
X  
***************
*** 713,720 ****
X      signal (SIGINT, onintr);
X      SW_intr = 1;
X  
! /* Are we talking to the user?  Yes - check in parser */
X  
X      if (talking)
X      {
X  	if (inparse)
--- 719,731 ----
X      signal (SIGINT, onintr);
X      SW_intr = 1;
X  
! /* Zap the swap file, just in case it got corrupted */
X  
+     S_close (SW_fp, TRUE);
+     Clear_Swap_File ();
+ 
+ /* Are we talking to the user?  Yes - check in parser */
+ 
X      if (talking)
X      {
X  	if (inparse)
***************
*** 775,782 ****
--- 786,800 ----
X  register int	i;
X  {
X      if (i == SIGINT)		/* Need this because swapper sets it	*/
+     {
X  	SW_intr = 0;
X  
+ /* Zap the swap file, just in case it got corrupted */
+ 
+ 	S_close (SW_fp, TRUE);
+ 	Clear_Swap_File ();
+     }
+ 
X      trapset = i;
X      signal (i, sig);
X  }
***************
*** 1185,1298 ****
X  }
X  
X  /*
!  * Match a pattern as in sh(1).
X   */
X  
! bool		gmatch (s, p, IgnoreCase)
! register char	*s, *p;
X  bool		IgnoreCase;
X  {
!     register int	sc, pc;
X  
!     if ((s == (char *)NULL) || (p == (char *)NULL))
X  	return FALSE;
X  
!     while ((pc = *(p++) & CMASK) != '\0')
X      {
! 	sc = *(s++) & QMASK;
X  
! 	switch (pc)
X  	{
X  	    case '[':			/* Class expression		*/
! 		if ((p = cclass (p, sc, IgnoreCase)) == (char *)NULL)
X  		    return FALSE;
X  
X  		break;
X  
X  	    case '?':			/* Match any character		*/
! 		if (sc == 0)
X  		    return FALSE;
X  
X  		break;
X  
X  	    case '*':			/* Match as many as possible	*/
! 		s--;
X  		do
X  		{
! 		    if (!*p || gmatch (s, p, IgnoreCase))
! 			return TRUE;
X  
! 		} while (*(s++));
X  
! 		return FALSE;
X  
X  	    default:
X  		if (IgnoreCase)
X  		{
! 		    sc = tolower (sc);
! 		    pc = tolower ((pc & ~QUOTE));
X  		}
X  
! 		if (sc != (pc & ~QUOTE))
X  		    return FALSE;
X  	}
X      }
X  
!     return (*s == 0) ? TRUE : FALSE;
! }
X  
X  /*
X   * Process a class expression - []
X   */
X  
! static char	*cclass (p, sub, IgnoreCase)
! register char	*p;
! register int	sub;
X  bool		IgnoreCase;
X  {
!     register int	c, d, not, found;
X  
X  /* Exclusive or inclusive class */
X  
!     if ((not = *p == NOT) != 0)
! 	p++;
X  
X      found = not;
X  
X      do
X      {
! 	if (!*p)
X  	    return (char *)NULL;
X  
X  /* Get the next character in class, converting to lower case if necessary */
X  
! 	c = IgnoreCase ? tolower ((*p & CMASK)) : (*p & CMASK);
X  
X  /* If this is a range, get the end of range character */
X  
! 	if ((*(p + 1) == '-') && (*(p + 2) != ']'))
X  	{
! 	    d = IgnoreCase ? tolower ((*(p + 2) & CMASK)) : (*(p + 2) & CMASK);
! 	    p++;
X  	}
X  
X  	else
! 	    d = c;
X  
X  /* Is the current character in the class? */
X  
! 	if ((c <= sub) && (sub <= d))
X  	    found = !not;
X  
!     } while (*(++p) != ']');
X  
!     return found ? p + 1 : (char *)NULL;
X  }
X  
X  /*
!  * Get a string in a malloced area
X   */
X  
X  char		*getcell (nbytes)
X  unsigned int	nbytes;
X  {
--- 1203,1381 ----
X  }
X  
X  /*
!  * Match a pattern as in sh(1).  Enhancement to handle prefix processing
!  *
!  * IgnoreCase - ignore case on comparisions.
!  * end - end of match in 'string'.
!  * mode - mode for match processing - see GM_ flags in sh.h
X   */
X  
! bool		gmatch (string, pattern, IgnoreCase, end, mode)
! register char	*string, *pattern;
X  bool		IgnoreCase;
+ char		**end;
+ int		mode;
X  {
!     register int	string_c, pattern_c;
!     char		*save_end;
X  
!     if ((string == (char *)NULL) || (pattern == (char *)NULL))
X  	return FALSE;
X  
!     while ((pattern_c = *(pattern++) & CMASK) != '\0')
X      {
! 	string_c = *(string++) & QMASK;
X  
! 	switch (pattern_c)
X  	{
X  	    case '[':			/* Class expression		*/
! 		if ((pattern = cclass (pattern, string_c, IgnoreCase)) == (char *)NULL)
X  		    return FALSE;
X  
X  		break;
X  
X  	    case '?':			/* Match any character		*/
! 		if (string_c == 0)
X  		    return FALSE;
X  
X  		break;
X  
X  	    case '*':			/* Match as many as possible	*/
! 		--string;
! 		save_end = (char *)NULL;
! 
X  		do
X  		{
! 		    if (!*pattern ||
! 			gmatch (string, pattern, IgnoreCase, end, mode))
! 		    {
! 			if (mode == GM_LONGEST)
! 			    save_end = *end;
X  
! 			else
! 			    return TRUE;
! 		    }
X  
! 		} while (*(string++));
X  
+ 		if (end != (char **)NULL)
+ 		    *end = save_end;
+ 
+ 		return (save_end == (char *)NULL) ? FALSE : TRUE;
+ 
X  	    default:
X  		if (IgnoreCase)
X  		{
! 		    string_c = tolower (string_c);
! 		    pattern_c = tolower ((pattern_c & ~QUOTE));
X  		}
X  
! 		if (string_c != (pattern_c & ~QUOTE))
X  		    return FALSE;
X  	}
X      }
X  
!     if (end != (char **)NULL)
!     {
! 	*end = string;
! 	return TRUE;
!     }
X  
+     return (*string == 0) ? TRUE : FALSE;
+ }
+ 
X  /*
X   * Process a class expression - []
X   */
X  
! static char	*cclass (pattern, string_c, IgnoreCase)
! register char	*pattern;
! register int	string_c;
X  bool		IgnoreCase;
X  {
!     register int	llimit_c, ulimit_c, not, found;
X  
X  /* Exclusive or inclusive class */
X  
!     if ((not = *pattern == NOT) != 0)
! 	pattern++;
X  
X      found = not;
X  
X      do
X      {
! 	if (!*pattern)
X  	    return (char *)NULL;
X  
X  /* Get the next character in class, converting to lower case if necessary */
X  
! 	llimit_c = IgnoreCase ? tolower ((*pattern & CMASK))
! 			      : (*pattern & CMASK);
X  
X  /* If this is a range, get the end of range character */
X  
! 	if ((*(pattern + 1) == '-') && (*(pattern + 2) != ']'))
X  	{
! 	    ulimit_c = IgnoreCase ? tolower ((*(pattern + 2) & CMASK))
! 				  : (*(pattern + 2) & CMASK);
! 	    pattern++;
X  	}
X  
X  	else
! 	    ulimit_c = llimit_c;
X  
X  /* Is the current character in the class? */
X  
! 	if ((llimit_c <= string_c) && (string_c <= ulimit_c))
X  	    found = !not;
X  
!     } while (*(++pattern) != ']');
X  
!     return found ? pattern + 1 : (char *)NULL;
X  }
X  
X  /*
!  * Suffix processing - find the longest/shortest suffix.
X   */
X  
+ bool		gmatch_suffix (string, pattern, IgnoreCase, start, mode)
+ register char	*string, *pattern;
+ bool		IgnoreCase;
+ char		**start;
+ int		mode;
+ {
+     char	*save_start = (char *)NULL;
+ 
+ /* Scan the string, looking for a match to the end */
+ 
+     while (*string)
+     {
+ 	if (gmatch (string, pattern, IgnoreCase, (char **)NULL, GM_ALL))
+ 	{
+ 
+ /* If longest, stop here */
+ 
+ 	    if (mode == GM_LONGEST)
+ 	    {
+ 		*start = string;
+ 		return TRUE;
+ 	    }
+ 
+ /* Save the start of the shortest string so far and continue */
+ 
+ 	    save_start = string;
+ 	}
+ 
+ 	++string;
+     }
+ 
+     return ((*start = save_start) == (char *)NULL) ? FALSE : TRUE;
+ }
+ 
+ /*
+  * Get a string in a malloced area
+  */
+ 
X  char		*getcell (nbytes)
X  unsigned int	nbytes;
X  {
***************
*** 1323,1329 ****
X  	print_warn ("Malloc access to bad segment\n");
X  	return (char *)NULL;
X      }
!     
X      np->magic1             = MAGIC1;
X      np->len    		   = nbytes;
X      rp	       	           = (char *)(np + 1);
--- 1406,1412 ----
X  	print_warn ("Malloc access to bad segment\n");
X  	return (char *)NULL;
X      }
! 
X      np->magic1             = MAGIC1;
X      np->len    		   = nbytes;
X      rp	       	           = (char *)(np + 1);
***************
*** 1362,1370 ****
X  /* Disable signals */
X  
X      save_signal = signal (SIGINT, SIG_IGN);
-     
- /* Find the string in the chain */
X  
X      if (s != (char *)NULL)
X      {
X  	while (cp != (s_region *)NULL)
--- 1445,1453 ----
X  /* Disable signals */
X  
X      save_signal = signal (SIGINT, SIG_IGN);
X  
+ /* Find the string in the chain */
+ 
X      if (s != (char *)NULL)
X      {
X  	while (cp != (s_region *)NULL)
***************
*** 2012,2018 ****
X  	str1++;
X  	str2++;
X      }
! 	
X      return rtn;
X  }
X  
--- 2095,2101 ----
X  	str1++;
X  	str2++;
X      }
! 
X      return rtn;
X  }
X  
***************
*** 2064,2074 ****
X  
X      while (--len >= 0)
X      {
! 	if ((*(str1++) = *(str2++)) == 0)    
X  	{
X  	    while (--len >= 0)
X  		*(str1++) = 0;
! 	    
X  	    break;
X  	}
X      }
--- 2147,2157 ----
X  
X      while (--len >= 0)
X      {
! 	if ((*(str1++) = *(str2++)) == 0)
X  	{
X  	    while (--len >= 0)
X  		*(str1++) = 0;
! 
X  	    break;
X  	}
X      }
Index: shell/sh3.c
Prereq: 1.24
*** ../sh16.3/shell/sh3.c	Fri Aug 17 21:34:34 1990
--- shell/sh3.c	Tue Nov  6 19:21:26 1990
***************
*** 13,21 ****
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   *
!  *    $Header: C:/SRC/SHELL/RCS/sh3.c 1.24 90/08/16 10:28:47 Ian_Stewartson Exp $
X   *
X   *    $Log:	sh3.c $
X   * Revision 1.24  90/08/16  10:28:47  Ian_Stewartson
X   * Find setting of switch character for DOS4 for batch files
X   * 
--- 13,32 ----
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   *
!  *    $Header: C:/SRC/SHELL/RCS/sh3.c 1.27 90/09/19 15:30:31 Ian_Stewartson Exp $
X   *
X   *    $Log:	sh3.c $
+  * Revision 1.27  90/09/19  15:30:31  Ian_Stewartson
+  * Allow builtin commands to selected/de-selected
+  * 
+  * Revision 1.26  90/09/11  20:06:11  Ian_Stewartson
+  * Add support for buitlin command, including the alway builtin functions
+  * Change search order to match POSIX
+  * 
+  * Revision 1.25  90/08/24  21:55:00  Ian_Stewartson
+  * Change processing order (function, external, internal) to conform to
+  * POSIX.  Update to gmatch for macro command changes
+  * 
X   * Revision 1.24  90/08/16  10:28:47  Ian_Stewartson
X   * Find setting of switch character for DOS4 for batch files
X   * 
***************
*** 144,149 ****
--- 155,161 ----
X  static char	*AE2big = "arg/env list too big";
X  static char	*EMS_emsg = "Warning: EMS Error (%x)\n";
X  static char	*XMS_emsg = "Warning: XMS Error (%x)\n";
+ static char	*EF_msg = "%s: %s\n";
X  			/* Extended Command line processing file name	*/
X  static char		*Extend_file = (char *)NULL;
X  static char		*Swap_File = (char *)NULL;	/* Swap file	*/
***************
*** 475,481 ****
--- 487,495 ----
X      void	(*sig_int)();
X      char	**owp = wp;
X      bool	spawn = FALSE;
+     bool	builtin = FALSE;
X      Fun_Ops	*fop;
+     int		i;
X  
X      if (t->type == TCOM)
X      {
***************
*** 510,522 ****
X  /* Check for built in commands */
X  
X  	else if (cp != (char *)NULL)
! 	    shcom = inbuilt (cp);
X      }
X  
X  /* Unix fork simulation? */
X  
X      t->words = wp;
!     if (shcom == NULL && (act & FEXEC) == 0)
X      {
X  	spawn = TRUE;
X  
--- 524,536 ----
X  /* Check for built in commands */
X  
X  	else if (cp != (char *)NULL)
! 	    shcom = inbuilt (cp, &builtin);
X      }
X  
X  /* Unix fork simulation? */
X  
X      t->words = wp;
!     if ((act & FEXEC) == 0)
X      {
X  	spawn = TRUE;
X  
***************
*** 534,540 ****
X  
X      while (((cp = *owp++) != (char *)NULL) && assign (cp, COPYV))
X      {
! 	if (shcom == NULL)
X  	    s_vstatus (lookup (cp, TRUE), EXPORT);
X      }
X  
--- 548,554 ----
X  
X      while (((cp = *owp++) != (char *)NULL) && assign (cp, COPYV))
X      {
! 	if (shcom == (int (*)())NULL) 
X  	    s_vstatus (lookup (cp, TRUE), EXPORT);
X      }
X  
***************
*** 565,572 ****
X  	}
X      }
X  
-     if (shcom)
- 	return restore_std (setstatus ((*shcom)(t)), TRUE);
X  
X  /* All fids above 10 are autoclosed in the exec file because we have used
X   * the O_NOINHERIT flag.  Note I patched open.obj to pass this flag to the
--- 579,584 ----
***************
*** 598,604 ****
X   * in some processing for return.
X   */
X  
!     if ((fop = Fun_Search (wp[0])) != (Fun_Ops *)NULL)
X      {
X  	char			**s_dolv = dolv;
X  	int			s_dolc   = dolc;
--- 610,616 ----
X   * in some processing for return.
X   */
X  
!     if (!builtin && (fop = Fun_Search (wp[0])) != (Fun_Ops *)NULL)
X      {
X  	char			**s_dolv = dolv;
X  	int			s_dolc   = dolc;
***************
*** 651,659 ****
X  
X  /* Ok - execute the program */
X  
!     return restore_std (rexecve (wp[0], wp, makenv (), spawn), TRUE);
! }
X  
X  /*
X   * Restore Local Environment
X   */
--- 663,685 ----
X  
X  /* Ok - execute the program */
X  
!     if (!builtin)
! 	rv = rexecve (wp[0], wp, makenv (), spawn);
X  
+ /* If we didn't find it, check for internal command */
+ 
+     if (builtin || ((rv == -1) && (errno == ENOENT)))
+     {
+ 	if (shcom != (int (*)())NULL) 
+ 	    rv =  setstatus ((*shcom)(t));
+ 
+ 	else
+ 	    print_warn (EF_msg, wp[0], "not found");
+     }
+ 
+     return restore_std (rv, TRUE);
+ }
+ 
X  /*
X   * Restore Local Environment
X   */
***************
*** 835,841 ****
X  
X      for (wp = t1->words; *wp != (char *)NULL;)
SHAR_EOF
true || echo 'restore of Patch1.6.4 failed'
fi
echo 'End of  part 1'
echo 'File Patch1.6.4 is continued in part 2'
echo 2 > _shar_seq_.tmp
exit 0

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.