[comp.sources.misc] v10i058: MSDOS Shell

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

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

#!/bin/sh
# this is part 5 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file shell/sh0.asm continued
#
CurArch=5
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file shell/sh0.asm"
sed 's/^X//' << 'SHAR_EOF' >> shell/sh0.asm
X	call	$GDT_src_load
X
X;
X; Check for end of copy - BX contains the file handler for disk write
X;
X
X$Write_loop:
X	or	si, si
X	je	$Write_Complete
X
X; OK - Copy next 0x4000 bytes - switch on device
X
X	mov	ax, word ptr cs: _SW_Mode
X	dec	ax
X	jz	$Write_disk
X	dec	ax
X	jz	$W_extend
X	jmp	$W_expand
X
X; Write to disk
X
X$Write_disk:
X	mov	ax, 04000H		; Set up to write
X	mov	cx, ax			; Load count
X	xor	dx, dx			; Clear start address
X	push	bx			; Save FP
X	push	si			; Save count and Data Segment
X
X	int	021H			; Write the data
X
X	pop	si			; Restore Regs
X	pop	bx
X	jc	$Write_error		; NO - abort
X
X$Write_Incr:
X	dec	si			; Decrement block count
X	mov	ax, ds			; Increment offset
X	add	ax, 0400H
X	mov	ds, ax
X	jmp	$Write_loop
X
X; Write to extended memory
X
X$W_extend:
X	call	$Write_extend
X	jc	$Write_error		; NO - abort
X
X	dec	si			; Decrement block count
X	call	$Inc_Extend
X	jmp	$Write_loop
X
X; Write to expanded memory
X;	BX - handler
X;	SI - count
X;	DS - source segment
X;
X$W_expand:
X	call	$map_ems_page		; Map in the current EMS page
X	jnz	$Write_error
X
X	push	ds			; Save DS and SI
X	push	si
X	mov	es, word ptr cs:_SW_EMSFrame	; Set Dest Seg
X	xor	si, si			; Clear start
X	xor	di, di
X	mov	cx, 02000H		; move 16K
X	pushf				; Save direction flag
X	cld
X    rep movsw
X	popf				; Restore direction flag
X	pop	si			; And DS, SI
X	pop	ds
X	jmp	$Write_Incr		; Increment DS and dec SI
X
X;
X; Error - abort.  The error code is in AH.
X;
X
X$Write_error:
X	mov	ds, word ptr cs:S_ds	; Restore DS
X	mov	al, ah
X	xor	ah, ah
X	mov	word ptr ds:_errno, ax	; Save error code
X	mov	ax, 0FFFEH
X	jmp	$SA_spawn_Exit		; Exit
X
X;
X; Swap file is now written, set up environment
X;
X$Write_Complete:
X	mov	ds, word ptr cs:exec_env	; Load Env seg.
X	xor	si, si				; Clear start offset
X
X;
X; Copy into Env Seg
X;
X
X$Copy_Env:
X	les	bx, dword ptr ss:[bp + 6]	; Check for end of loop
X	mov	ax, word ptr es:[bx + 0]
X	or	ax, word ptr es:[bx + 2]
X	je	$Copy_End
X
X;
X; Save start address
X;
X	add	word ptr ss:[bp + 6], 4		; Increment environment by 4
X
X	mov	cx, word ptr es:[bx + 0]	; Load address of cur Env string
X	mov	ax, word ptr es:[bx + 2]	; into es:bx
X	mov	es, ax
X	mov	bx, cx
X
X;
X; Copy this value
X;
X
X$Copy_Val:
X	mov	al, byte ptr es:[bx]	; Copy across
X	mov	byte ptr ds:[si], al
X	inc	bx			; Increment pointers
X	inc	si
X	or	al, al
X	jne	$Copy_Val
X	jmp	$Copy_Env
X
X;
X; Set up exec parameter block	 - DS is on stack
X;
X$Copy_End:
X	xor	ax, ax
X	mov	word ptr ds:[si], ax	; Terminate environment
X	add	si, 2
X
X;
X; Set up new program length
X;
X	add	si, 16			; Round up paras
X	mov	dx, si			; Save end offset in DX
X	mov	bx, ds
X
X	mov	cl, 4
X	shr	si, cl			; # paras used by Env
X	add	si, bx			; End para number
X
X	mov	bx, word ptr cs:N_mcb	; Load our MCB address in BX
X	mov	ax, bx
X	inc	ax
X	sub	si, ax
X	mov	cx, si			; Save new max paras in CX
X
X;
X; Use interrupt 4a to shrink memory.  First release all memory above us.
X;
X	push	ax
X	push	cx			; Save Max paras and location
X	mov	ds, bx			; Set up the segement for MCB
X	mov	cx, word ptr ds:3	; Get the MCB length
X
X; Are we the only one in the chain?
X
X	cmp	byte ptr ds:0, 'Z'	; End of chain ?
X	jz	$Shrink_First
X
X;
X; Loop round releasing memory blocks
X;
X;	CX - original length of block;
X;	DS - segement of the previous block
X;
X$Shrink_Next:
X	mov	ax, ds			; Move to the next block
X	add	cx, ax
X	inc	cx
X	mov	ds, cx
X
X	cmp	byte ptr ds:0, 'Z'	; End of chain ?
X	jz	$Shrink_First
X
X	mov	cx, word ptr ds:3	; Save the length of this block
X
X	mov	ax, ds			; Advance to the block itself
X	inc	ax
X	mov	es, ax			; Set up Block address
X
X	mov	ah, 049H
X	int	021H
X	jmp	$Shrink_Next
X
X;
X;	Shrink the PSP segment
X;
X
X$Shrink_First:
X	pop	cx
X	pop	ax
X        mov	es, ax			; Set PSP address
X	mov	bx, cx			; Set max length
X	mov	ah, 04aH
X	int	021H
X
X;
X; Execute function
X;
X
X	mov	word ptr cs: S_sp, sp	; Save the current stack
X	mov	word ptr cs: S_ss, ss
X
X;
X; Move to the local stack so that it doesn't get overwritten.
X;
X	mov	ax, cs
X	cli
X	mov	sp, offset Local_Stack
X	mov	ss, ax
X	sti
X
X; Clear out Interrupts
X
X	mov	ah, 00bH		; Check Keyboard status
X	int	021H
X
X;
X;  Check for interrupt 23 detected
X;
X	mov	ax, word ptr cs:_SW_intr
X	xor	ax, ax
X	jz	$I23_Cf			; No - continue;
X
X;
X; Interrupt 23 detected - abort
X;
X	mov	ax, cs			; Set up for reload
X	cli
X	mov	sp, offset Local_Stack
X	mov	ss, ax
X	sti
X
X	mov	ds, word ptr cs:S_ds	; Restore DS
X	mov	word ptr ds:_errno, 4	; Set to EINTR
X	jmp	$Exec_Error
X
X;
X; No interrupts - continue
X;
X$I23_Cf:
X	mov	ax, cs			; Set up segments
X	mov	es, ax
X	mov	ds, ax
X
X	mov	ax, 04b00H		; Load and execute function
X	mov	dx, offset _path_line	; Load path
X	mov	bx, offset exec_parms	; Load the execute structure
X	mov	byte ptr cs:InShell, 1	; Set not In shell flag for Interrupt 23
X	int	021H
X	mov	byte ptr cs:InShell, 0	; Set In shell flag for Interrupt 23
X
X; Disable interrupts while we restore the stack to the local one
X
X	mov	ax, cs
X	cli
X	mov	sp, offset Local_Stack
X	mov	ss, ax
X	sti
X
X;
X; Did an error occur?
X;
X	jnc	$Exec_OK
X
X;
X; Error
X;
X	mov	ds, word ptr cs:S_ds	; Restore DS
X	mov	ah, al
X	call	far ptr __maperror	; Map the error
X
X$Exec_Error:
X	mov	ax, 0FFFFH
X	jmp	$Exec_Complete
X
X;
X; No - get the exit code and check for interrupts
X;
X
X$Exec_OK:
X	mov	ax, 04d00H
X	int	021H
X	dec	ah			; Interrupt termination ?
X	jnz	$Exec_OK1
X
X	inc	word ptr ds:_SW_intr	; Set Interrupt 23 detected.
X
X$Exec_OK1:
X	xor	ah, ah
X
X;
X; Save the result code
X;
X
X$Exec_Complete:
X	mov	word ptr cs:Result, ax		; Save response
X
X;
X; Very Dangerous - Restore Environment
X;
X;	 Seek to 0x4000 in file
X;
X	mov	bx, word ptr cs:_SW_fp		; Load File Handler
X	mov	ax, word ptr cs: _SW_Mode	; Skip if not disk
X	dec	ax
X	jnz	$Seek_OK
X
X; Seek in file to skip 16K
X
X	mov	dx, 04000H
X	call	$Seek_Disk
X
X;
X;	 Load from N_mcb:0x4000 to end of file.
X;
X
X$Seek_OK:
X	mov	si, word ptr cs:_SW_Blocks	; Load number of transfers
X	dec	si				; Skip first block
X
X;
X; set up ES register with start of load
X;
X	mov	ax, word ptr cs:N_mcb	; Load the start address
X	add	ax, 0400H
X	mov	ds, ax
X
X; load up extended memory GDT for destination
X
X	call	$GDT_reload
X	call	$Inc_Extend			; Increment addresses by 16K
X
X;
X; Check for end of copy	- BX - File Handler for disk
X;
X
X$Read_loop:
X	or	si, si
X	je	$Read_Complete
X
X; OK - Copy next 0x4000 bytes - switch on device
X
X	mov	ax, word ptr cs: _SW_Mode
X	dec	ax
X	jz	$R_disk
X	dec	ax
X	jz	$R_extend
X	jmp	$R_expand
X
X; Read from disk
X
X$R_disk:
X	call	$Read_disk
X	jmp	$Read_loop
X
X; Read from extended memory
X
X$R_extend:
X	call	$Read_extend
X	jmp	$Read_loop
X
X; Read from expanded memory
X
X$R_expand:
X	call	$Read_EMS
X	jmp	$Read_loop
X
X;
X; Re-load is now complete, Restore original stack which has just been
X; reloaded.  BX contains FP
X;
X
X$Read_Complete:
X	cli
X	mov	sp, word ptr cs: S_sp		; Save the current stack
X	mov	ss, word ptr cs: S_ss
X	sti
X
X;  Save exit code
X
X	push	word ptr cs:Result		; Save response
X
X;
X; Read in the first block - BX - File Handler
X;
X
X	mov	ax, word ptr cs: _SW_Mode	; Skip if not disk
X	dec	ax
X	jnz	$Seek1_OK
X
X; Seek to 0 in file
X
X	xor	dx, dx
X	call	$Seek_Disk
X
X;
X;	 Load one block at N_mcb:0x0000
X;
X$Seek1_OK:
X	mov	ds, word ptr cs:N_mcb		; Load the start address
X	call	$GDT_reload			; Load the GDT for extend mem
X
X	mov	ax, word ptr cs: _SW_Mode	; Skip if not disk
X	dec	ax
X	jz	$R1_Disk
X	dec	ax
X	jz	$R1_Extend
X	jmp	$R1_Expand
X
X$R1_Disk:
X	call	$Read_disk
X	jmp	$Read1_OK
X
X$R1_Extend:
X	call	$Read_extend
X	jmp	$Read1_OK
X
X$R1_Expand:
X	mov	si, word ptr cs:_SW_Blocks	; Read first block
X	call	$Read_EMS
X
X;
X; Complete - load error code and return
X;
X
X$Read1_OK:
X	pop	ax
X
X;
X; Exit function - Restore Control Interrupt handler
X;
X
X$SA_spawn_Exit:
X	push	ax				; Save exit code
X	mov	ax, 02523H			; Set Control C Interrupt
X	mov	ds, word ptr cs:_SW_I23_V_ES
X	mov	dx, word ptr cs:_SW_I23_V_BX
X	int	021H
X
X	mov	ax, 02523H			; Set Divide Zero Interrupt
X	mov	ds, word ptr cs:_SW_I0_V_ES
X	mov	dx, word ptr cs:_SW_I0_V_BX
X
X;
X
X	mov	di, word ptr cs:S_di		; Restore saved registers
X	mov	si, word ptr cs:S_si
X	mov	ds, word ptr cs:S_ds
X
X; If interrupt 23 detected - raise the flag
X
X	mov	ax, word ptr cs:_SW_intr	; Set Interrupt 23 detected.
X	or	ax, ax
X	jz	$SA_Exit1
X
X	mov	ax, 02H
X	push	ax				; Set SIGINT
X	call	_raise
X	add	sp, 2
X
X$SA_Exit1:
X	pop	ax				; Restore result
X	mov	sp,bp
X	pop	bp
X	ret
X
X_SA_spawn	endp
X
X;
X; READ DISK FUNCTION
X;
X;	BX - file handler
X;	SI - Block count
X;	DS - Output data segement
X;
X
X$Read_disk	proc	near
X
X	mov	ax, 03f00H		; Set up to read
X	mov	cx, 04000H		; Load count
X	xor	dx, dx			; Clear start address
X
X	int	021H			; Read the data
X
X	jnc	$Read_OK		; NO - abort
X	jmp	Load_Error		; Abort - swap file error
X
X;
X; Read OK - next block
X;
X
X$Read_OK:
X	dec	si			; Decrement block count
X	mov	ax, ds			; Increment offset
X	add	ax, 0400H
X	mov	ds, ax
X	ret
X
X$Read_disk	endp
X
X;
X; READ EMS FUNCTION
X;
X;	BX - file handler
X;	SI - Block count - counts from max
X;	DS - Output data segement
X;
X
X$Read_EMS	proc	near
X
X	call	$map_ems_page		; Map in the current EMS page
X	jnz	Load_Error
X
X	push	ds			; Save DS and SI
X	push	si
X	mov	ax, ds
X	mov	es, ax
X	mov	ds, word ptr cs:_SW_EMSFrame	; Set Dest Seg
X	xor	si, si			; Clear start
X	xor	di, di
X	mov	cx, 02000H		; move 16K
X	pushf				; Save direction flag
X	cld
X    rep movsw
X	popf				; Restore direction flag
X	pop	si			; And DS, SI
X	pop	ds
X	jmp	$Read_OK		; Increment DS and dec SI
X
X$Read_EMS	endp
X
X;
X; MAP IN THE CURRENT EMS PAGE
X;
X;	BX - file handler
X;	SI - Block count - counts from max
X;	DS - Output data segement
X;
X
X$map_ems_page	proc	near
X
X	push	bx			; Need to save BX
X	mov	ax, 04400h		; Map into physical page zero
X	mov	dx, bx			; Set up handler
X	mov	bx, word ptr cs: _SW_Blocks
X	sub	bx, si
X
X	int	067H
X	pop	bx
X
X	or	ah, ah
X	ret
X
X$map_ems_page	endp
X
X;
X; DISK SEEK FUNCTION
X;
X;	BX - file handler
X;	DX - offset
X;
X$Seek_Disk	proc	near
X
X	mov	ax, 04200H		; Set seek
X	xor	cx, cx
X	int	021H
X	jc	Load_Error		; Abort - swap file error
X	ret
X
X$Seek_Disk	endp
X
X;
X; PANIC - Abort
X;
X
XLoad_Error	proc	near
X
X	mov	ax, 00900H
X	mov	dx, offset Swap_PANIC
X	mov	bx, cs
X	mov	ds, bx
X	int	021H
X$Wait_L:
X	sti
X	hlt
X	jmp	$Wait_L
X
XLoad_Error	endp
X
X;
X;  WRITE EXTENDED MEMORY
X;
X;	SI - Block count
X;
X$Write_extend	proc	near
X
X	push	si			; Save SI (block counter)
X	mov	cx, 02000H		; Copy a 16K block
X	mov	ax, cs			; Set up GDT address
X	mov	es, ax
X	mov	si, offset GD_table
X
X	mov	ah, 087H		; EMS function
X	int	015H
X	pop	si
X	ret
X
X$Write_extend	endp
X
X;
X;  READ FROM EXTENDED MEMORY
X;
X;	SI - Block count
X;
X
X$Read_extend	proc	near
X
X	call	$Write_extend
X	jc	Load_Error		; NO - abort
X
X	dec	si			; Decrement block count
X
X$Read_extend	endp
X
X;
X; INCREMENT Extended MEMORY GDT
X;
X;	AX - used
X;
X$Inc_Extend	proc	near
X
X	mov	ax, 04000H		; Increment address by 16K
X	add	word ptr cs:GDT_dest_low, ax
X	adc	byte ptr cs:GDT_dest_high, 0
X	add	word ptr cs:GDT_src_low, ax
X	adc	byte ptr cs:GDT_src_high, 0
X	ret
X
X$Inc_Extend	endp
X
X;
X; LOAD SOURCE GDT ADDRESS
X;
X;	AX - low order
X;	DL - high order
X;
X$GDT_src_load	proc	near
X
X
X	mov	word ptr cs:GDT_src_low, ax
X	mov	byte ptr cs:GDT_src_high, dl
X	ret
X
X$GDT_src_load	endp
X
X;
X; LOAD DESTINATION GDT ADDRESS
X;
X;	AX - low order
X;	DL - high order
X;
X$GDT_dest_load	proc	near
X
X	mov	word ptr cs:GDT_dest_low, ax
X	mov	byte ptr cs:GDT_dest_high, dl
X	ret
X
X$GDT_dest_load	endp
X
X;
X; LOAD the GDT for reloading
X;
X
X$GDT_reload	proc	near
X	mov	ax, word ptr cs:_SW_EMstart 	; Load Full start address
X	mov	dl, byte ptr cs:_SW_EMstart + 2
X	call	$GDT_src_load
X
X	mov	ax, word ptr cs:SW_LMstart 	; Load Full start address
X	mov	dl, byte ptr cs:SW_LMstart + 2
X	call	$GDT_dest_load
X	ret
X$GDT_reload	endp
X
X;
X; CONTROL C INTERRUPT HANDLER - IGNORE
X;
X
XSA_IRET		proc	far
X	push	ax
X	push	bp			; Save the AX and DS registers
X	push	ds
X	mov	bp, seg SH0_TEXT	; Get my segment
X	mov	ds, bp
X	inc	word ptr ds:_SW_intr	; Set Interrupt 23 detected.
X	cmp	byte ptr ds:InShell, 0	; Are we in the shell ?
X	jz	$SA_Ins
X
X; In another program - move the stack around
X
X	mov	bp, sp
X	pop	ds			; Unstack values
X	pop	bp
X	pop	ax
X	stc
X	ret
X
X
X; In shell - ignore interrupt 23 for the moment
X
X$SA_Ins:
X	pop	ds			; Restore regs
X	pop	bp
X	pop	ax
X	iret
X
XSA_IRET		endp
X
X;
X; DIVIDE BY ZERO INTERRUPT HANDLER - Output message
X;
X
XSA_DZERO	proc	far
X
X	mov	ax, 00900H
X	mov	dx, offset Swap_DZERO
X	mov	bx, cs
X	mov	ds, bx
X	int	021H
X
X	mov	ax, 04CFFh		; Exit
X	int	021H
X
XSA_DZERO	endp
X
X;
X;  Start of overwrite area for environment.  Align on a paragraph
X;
X		ALIGN	16
XEnv_OWrite:
XSH0_TEXT	ends
X		end
SHAR_EOF
echo "File shell/sh0.asm is complete"
chmod 0644 shell/sh0.asm || echo "restore of shell/sh0.asm fails"
set `wc -c shell/sh0.asm`;Sum=$1
if test "$Sum" != "17894"
then echo original size 17894, current size $Sum;fi
echo "x - extracting shell/sh.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > shell/sh.h &&
X/* MS-DOS SHELL - Header File
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 sources
X *     (or parts of sources) cannot be sold under any circumstances.
X *
X *    $Header: sh.h 1.1 90/01/29 17:46:51 MS_user Exp $
X *
X *    $Log:	sh.h $
X * Revision 1.1  90/01/29  17:46:51  MS_user
X * Initial revision
X * 
X * 
X */
X
X#define	LINE_MAX	1000	/* Command line length			*/
X#define HISTORY_MAX	100	/* History array length			*/
X				/* Space for full file name		*/
X#define FFNAME_MAX	(PATH_MAX + NAME_MAX + 4)
X#define CMD_LINE_MAX	127	/* Max command line length		*/
X#define SSAVE_IO_SIZE	4	/* Save IO array malloc increment	*/
X
X#define	NPUSH		8	/* limit to input nesting		*/
X
X#define	NOFILE		20	/* Number of open files			*/
X#define	NUFILE		10	/* Number of user-accessible files	*/
X#define	FDBASE		10	/* First file usable by Shell		*/
X
X#define NL		'\n'
X#define SP		' '
X#define	NOT		'^'
X				/* Open in create mode			*/
X#define O_CMASK		(O_WRONLY | O_CREAT | O_TRUNC | O_TEXT)
X				/* Open in create mode for a pipe	*/
X#define O_PMASK		(O_RDWR | O_CREAT | O_TRUNC | O_TEXT)
X				/* Open in create mode for swap file	*/
X#define O_SMASK		(O_RDWR | O_CREAT | O_TRUNC | O_BINARY)
X#define O_RMASK		(O_RDONLY | O_NOINHERIT | O_TEXT)
X
X/*
X * shell components
X */
X
X#define	QUOTE		0200
X#define	CMASK		0377
X#define	QMASK		(CMASK & ~QUOTE)
X
X#define	NOBLOCK		((C_Op *)NULL)
X#define	NOWORD		((char *)NULL)
X#define	NOWORDS		((char **)NULL)
X#define	NOPIPE		(-1)
X
X/*
X * Description of a command or an operation on commands.
X * Might eventually use a union.
X */
X
Xtypedef struct op {
X    int			type;		/* operation type, see below	*/
X    char		**words;	/* arguments to a command	*/
X    struct ioword	**ioact;	/* IO actions (eg, < > >>)	*/
X    struct op		*left;
X    struct op		*right;
X    char		*str;		/* identifier for case and for	*/
X} C_Op;
X
X#define	TCOM		1	/* command				*/
X#define	TPAREN		2	/* (c-list)				*/
X#define	TPIPE		3	/* a | b				*/
X#define	TLIST		4	/* a [&;] b				*/
X#define	TOR		5	/* ||					*/
X#define	TAND		6	/* &&					*/
X#define	TFOR		7	/* FOR					*/
X#define	TDO		8	/* DO					*/
X#define	TCASE		9	/* CASE					*/
X#define	TIF		10	/* IF					*/
X#define	TWHILE		11	/* WHILE				*/
X#define	TUNTIL		12	/* UNTIL				*/
X#define	TELIF		13	/* ELSE IF				*/
X#define	TPAT		14	/* pattern in case			*/
X#define	TBRACE		15	/* {c-list}				*/
X#define	TASYNC		16	/* c &					*/
X#define	TFUNC		17	/* c () {c-list}			*/
X
X/* Built in Command list */
X
Xstruct	builtin {
X    char	*command;
X    int		(*fn)(C_Op *);
X};
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 */
X
X#pragma pack (1)
Xstruct MCB_list	{
X    char		MCB_type;	/* M or Z			*/
X    unsigned int	MCB_pid;	/* Process ID			*/
X    unsigned int	MCB_len;	/* MCB length			*/
X};
X#pragma pack ()
X
X#define MCB_CON		'M'		/* More MCB's			*/
X#define MCB_END		'Z'		/* Last MCB's			*/
X
X/* Externs for Swapper assembler function */
X
Xextern char		cmd_line[];	/* Command line			*/
Xextern char		path_line[];	/* Process path			*/
Xextern unsigned int	SW_intr;	/* interrupt pending		*/
Xextern unsigned int	SW_Blocks;	/* Number of blocks to read	*/
Xextern int		SW_fp;		/* File or EMS Handler		*/
Xextern unsigned int	SW_I0_V_BX;	/* Out interrupt Zero address	*/
Xextern unsigned int	SW_I0_V_ES;
Xextern unsigned int	SW_I23_V_ES;	/* Our Interrupt 23 address	*/
Xextern unsigned int	SW_I23_V_BX;
Xextern unsigned long	SW_EMstart;	/* Start addr of extend mem	*/
Xextern unsigned int	SW_Mode;	/* Type of swapping to do	*/
X					/* 1 - disk			*/
X					/* 2 - Extended	memory		*/
X					/* 3 - Expanded	memory		*/
Xextern unsigned int	SW_EMSFrame;	/* EMS Frame segment		*/
X
Xextern int		Swap_Mode;	/* Swapping mode		*/
X
X/* If you change these values, change sh7, swap_device as well */
X
X#define SWAP_OFF	0x0000		/* No swapping			*/
X#define SWAP_DISK	0x0001		/* Disk only			*/
X#define SWAP_EXTEND	0x0002		/* Extended memory		*/
X#define SWAP_EXPAND	0x0004		/* Expanded memory		*/
X
X/*
X * flags to control evaluation of words
X */
X
X#define	DOSUB		0x01	/* interpret $, `, and quotes		*/
X#define	DOBLANK		0x02	/* perform blank interpretation		*/
X#define	DOGLOB		0x04	/* interpret [?*			*/
X#define	DOKEY		0x08	/* move words with `=' to 2nd arg. list */
X#define	DOTRIM		0x01	/* trim resulting string		*/
X
X#define	DOALL		(DOSUB | DOBLANK | DOGLOB | DOKEY | DOTRIM)
X
Xextern char		*Copy_Right1;
Xextern char		*Copy_Right2;
Xextern char		**dolv;		/* $<numeric> values		*/
Xextern int		dolc;		/* $<numeric> count		*/
Xextern int		fn_area_number;	/* Next function area number	*/
Xextern int		exstat;
Xextern char		gflg;
Xextern int		talking;	/* interactive (talking-type	*/
Xextern int		execflg;
Xextern int		multiline;	/* \n changed to ;		*/
Xextern int		*failpt;
Xextern int		*errpt;
Xextern int		inparse;	/* In parser flag		*/
Xextern int		Current_Event;	/* Current history event	*/
X
X/*
X * Break/Continue (in for and while), Return and Exit handler
X */
X
Xtypedef struct brkcon {
X    jmp_buf		brkpt;
X    struct brkcon	*nextlev;
X} Break_C;
X				/* Values returned by longjmp		*/
X#define BC_LOAD		0	/* Load condition			*/
X#define BC_BREAK	1	/* Break condition			*/
X#define BC_CONTINUE	2	/* Continue condition			*/
X
Xextern Break_C	*Break_List;	/* Break list for FOR/WHILE		*/
Xextern Break_C	*Return_List;	/* Return list for RETURN		*/
Xextern Break_C	*SShell_List;	/* SubShell list for EXIT		*/
Xextern bool	level0;		/* Level zero (read profile)		*/
Xextern bool	r_flag;		/* Read only shell			*/
Xextern bool	History_Enabled;
X
X/*
X * Save Standard Input/Output/Error structure
X */
X
Xtypedef struct save_io {
X    int		depth;			/* Execute recursive depth	*/
X    int		fp[STDERR_FILENO + 1];	/* File handlers		*/
X} Save_IO;
X
Xextern Save_IO	*SSave_IO;		/* Save IO array		*/
Xextern int	NSave_IO_E;		/* Number of entries		*/
Xextern int	MSave_IO_E;		/* Max Number of entries	*/
X
X/*
X * Function tree processing
X */
X
Xtypedef struct fun_op {
X    struct fun_op	*next;		/* Link				*/
X    C_Op		*tree;		/* The tree itself		*/
X} Fun_Ops;
X
Xextern Fun_Ops	*fun_list;		/* List header			*/
X
X/*
X * redirection
X */
X
Xtypedef struct ioword {
X    short	io_unit;	/* unit affected			*/
X    short	io_flag;	/* action (below)			*/
X    char	*io_name;	/* file name				*/
X} IO_Actions;
X
X#define	IOREAD		1	/* <					*/
X#define	IOHERE		2	/* << (here file)			*/
X#define	IOWRITE		4	/* >					*/
X#define	IOCAT		8	/* >>					*/
X#define	IOXHERE		16	/* ${}, ` in <<				*/
X#define	IODUP		32	/* >&digit				*/
X#define	IOCLOSE		64	/* >&-					*/
X
X#define	IODEFAULT	(-1)	/* token for default IO unit		*/
X
X/*
X * parsing & execution environment
X */
X
Xtypedef struct env {
X    char	*cline;			/* Current line buffer		*/
X    char	*linep;			/* Current pointer in line	*/
X    char	*eline;			/* End of line pointer		*/
X    struct io	*iobase;
X    struct io	*iop;
X    int		*errpt;
X    int		iofd;
X    struct env	*oenv;			/* Previous environment		*/
X} Environ;
X
Xextern Environ		e;
X
X/*
X * here documents
X */
X
Xtypedef struct here {
X    char		*h_tag;
X    int			h_dosub;
X    IO_Actions		*h_iop;
X    struct here		*h_next;
X} Here_D;
X
X/*
X * flags:
X *
X * -a: Set all environment variables to exported
X * -e: Quit on error
X * -f: Disable file name expansion
X * -k: Look for name=value everywhere on command line
X * -n: No execution
X * -t: exit after reading and executing one command
X * -u: Abort if environment variable is not set
X * -v: Echo as read
X * -x: Trace
X */
X
X#define FL_TEST(x)	(flags & (1L << ((x) - 'a')))
X#define FL_SET(x)	flags |= (1L << ((x) - 'a'))
X#define FL_CLEAR(x)	flags &= (~(1L << ((x) - 'a')))
X
Xextern long	flags;
Xextern char	*null;		/* null value for variable		*/
Xextern long	ourtrap;	/* Signal processing required		*/
Xextern int	trapset;	/* trap pending				*/
Xextern int	yynerrs;	/* yacc					*/
Xextern int	Execute_stack_depth;	/* execute function recursion	*/
X					/* depth			*/
X
X/*
X * Variable list
X */
X
Xtypedef struct var {
X    char		*value;		/* Value			*/
X    char		*name;		/* Name				*/
X    struct var		*next;		/* Link				*/
X    char		status;		/* Type, see below		*/
X} Var_List;
X
X#define	COPYV		1	/* flag to setval, suggesting copy	*/
X#define	RONLY		0x01	/* variable is read-only		*/
X#define	EXPORT		0x02	/* variable is to be exported		*/
X#define	GETCELL		0x04	/* name & value space was got with getcell */
X#define PONLY		0x08	/* PATH Value - no unset		*/
X#define C_MSDOS		0x10	/* Convert to MSDOS format		*/
X
Xextern Var_List	*vlist;		/* dictionary				*/
Xextern Var_List **S_UL;		/* Start address update location	*/
Xextern Var_List	*path;		/* search path for commands		*/
Xextern Var_List	*ps1;		/* Prompt 1				*/
Xextern Var_List	*ps2;		/* Prompt 2				*/
Xextern Var_List	*ifs;		/* Interfield separators		*/
Xextern Var_List	*C_dir;		/* Current directory			*/
Xextern char	*last_prompt;	/* Last prompt output			*/
Xextern char	*home;		/* Home string				*/
Xextern char	*shell;		/* Shell string				*/
Xextern char	*hsymbol;	/* Hash string				*/
Xextern char	*msymbol;	/* Minus string				*/
Xextern char	*spcl2;
Xextern char	*history_file;
X
X/*
X * SubShell Save Structure
X */
X
Xtypedef struct subshell {
X    int		depth;			/* Sub_Shell Depth		*/
X    Var_List	*header;		/* Header start			*/
X} S_SubShell;
X
Xextern S_SubShell	*SubShells;	/* Save Vars array		*/
Xextern int		NSubShells;	/* Number of entries		*/
Xextern int		MSubShells;	/* Max Number of entries	*/
X
X/* io buffer */
X
Xtypedef struct iobuf {
X    unsigned int	id;		/* buffer id			*/
X    char		buf[512];	/* buffer			*/
X    char		*bufp;		/* pointer into buffer		*/
X    char		*ebufp;		/* pointer to end of buffer	*/
X} IO_Buf;
X
X/* possible arguments to an IO function */
X
Xtypedef struct ioarg {
X    char		*aword;
X    char		**awordlist;
X    int			afile;		/* file descriptor		*/
X    unsigned int	afid;		/* buffer id			*/
X    long		afpos;		/* file position		*/
X    IO_Buf		*afbuf;		/* buffer for this file		*/
X} IO_Args;
X
X#define AFID_NOBUF	(~0)
X#define AFID_ID		0
X
Xextern IO_Args	ioargstack[NPUSH];	/* IO argument stack		*/
X
X/* an input generator's state */
X
Xtypedef struct io {
X    int			(*iofn)(struct io *);
X    IO_Args		*argp;
X    int			peekc;
X    char		prev;		/* previous character read by readc() */
X    char		nlcount;	/* for `'s			*/
X    char		xchar;		/* for `'s			*/
X    char		task;		/* reason for pushed IO		*/
X    char		dflag;		/* Special processing flag	*/
X} IO_State;
X
X#define DSA_NULL	0x00		/* No special processing req	*/
X#define DSA_STAR	0x01		/* Special processing for "$*"	*/
X#define DSA_AMP		0x02		/* Special processing for "$@"	*/
X#define DSA_MODE	0x03		/* Mode flag			*/
X#define DSA_END		0x04		/* Last word processing		*/
X#define DSA_START	0x08		/* First word processed?	*/
X#define DSA_START1	0x10		/* Subsequent word processed	*/
X#define DSA_END1	0x20		/* End processing for word	*/
X
Xextern IO_State		iostack[NPUSH];	/* IO Stack			*/
X
X#define	XOTHER		0	/* none of the below			*/
X#define	XDOLL		1	/* expanding ${}			*/
X#define	XGRAVE		2	/* expanding `'s			*/
X#define	XIO		3	/* file IO				*/
X
X/* in substitution */
X
X#define	INSUB()			(e.iop->task == XGRAVE || e.iop->task == XDOLL)
X
X/*
X * IO control
X */
X
Xextern IO_Args		temparg;	/* temporary for PUSHIO */
X#define	PUSHIO(what,arg,gen)	((temparg.what = (arg)), pushio(&temparg,(gen)))
X#define	RUN(what,arg,gen)	((temparg.what = (arg)), run(&temparg,(gen)))
X
Xtypedef struct wdblock {
X    short	w_bsize;
X    short	w_nword;
X    char	*w_words[1];
X} Word_B;
X
Xextern Word_B	*wdlist;
Xextern Word_B	*iolist;
X
X/*
X * storage allocation
X */
X
Xextern int		areanum;	/* current allocation area */
X
X#define	NEW(type)	(type *)getcell (sizeof (type))
X#define	DELETE(obj)	freecell ((char *)obj)
X
X/* Functions */
X
Xextern void	main (int, char **);
Xextern void	setdash (void);
Xextern void	fail (void);
Xextern void	leave (void);
Xextern void	print_warn (char *, ...);
Xextern void	print_error (char *, ...);
Xextern bool	newenv (int);
Xextern void	quitenv (void);
Xextern char	*putn (int);
Xextern void	next (int);
Xextern void	onintr (int);
Xextern char	*space (int);
Xextern char	*strsave (char *, int);
Xextern void	sig (int);
Xextern void	runtrap (int);
Xextern Var_List	*lookup (char *, bool);
Xextern void	setval (Var_List *, char *);
Xextern void	s_vstatus (Var_List *, int);
Xextern bool	isassign (char *);
Xextern bool	assign (char *, int);
Xextern bool	gmatch (char *, char *, bool);
Xextern char	*getcell (unsigned int);
Xextern void	freecell (char *);
Xextern void	freearea (int);
Xextern void	setarea (char *, int);
Xextern int	getarea (char *);
Xextern C_Op	*yyparse (void);
Xextern int	execute (C_Op *, int, int, int);
Xextern int	run (IO_Args *, int (*)(IO_State *));
Xextern int	Getc (int);
Xextern void	unget (int);
Xextern int	eofc (void);
Xextern int	readc (void);
Xextern void	pushio (IO_Args *, int (*)(IO_State *));
Xextern int	nlchar (IO_State *);
Xextern int	wdchar (IO_State *);
Xextern int	dol_char (IO_State *);
Xextern int	strchar (IO_State *);
Xextern int	qstrchar (IO_State *);
Xextern int	filechar (IO_State *);
Xextern int	gravechar (IO_State *);
Xextern int	qgravechar (IO_State *);
Xextern int	linechar (IO_State *);
Xextern void	closeall (void);
Xextern int	remap (int);
Xextern int	openpipe (void);
Xextern void	closepipe (int);
Xextern void	markhere (char *, IO_Actions *);
Xextern void	gethere (void);
Xextern int	herein (char *, int);
Xextern void	scraphere (void);
Xextern void	freehere (int);
X
Xextern char	**eval (char **, int);
Xextern char	**makenv (void);
Xextern char	*evalstr (char *, int);
Xextern int	subgetc (char, int);
Xextern Word_B	*addword (char *, Word_B *);
Xextern char	**getwords (Word_B *);
Xextern void	put_prompt (char *);
Xextern bool	eqname (char *, char *);
Xextern bool	any (char, char *);
Xextern int	(*inbuilt (char *))();
Xextern char	*path_append (char *, char *, char *);
Xextern void	unset (char *, bool);
Xextern int	S_open (bool, char *, int, ...);
Xextern int	S_close (int, bool);
Xextern int	S_dup (int);
Xextern int	S_dup2 (int, int);
Xextern void	S_Remap (int, int);
Xextern void	S_Delete (int);
Xextern void	Getcwd (void);
Xextern char	*g_tempname (void);
Xextern void	S_puts (char *);
Xextern void	S_putc (int);
Xextern bool	check_rsh (char *);
Xextern int	O_for_execute (char *);
Xextern int	SA_spawn (char **);
Xextern char	*findeq (char *);
Xextern int	restore_std (int);
Xextern void	Load_History (void);
Xextern void	Dump_History (void);
Xextern void	Display_History (void);
Xextern void	Clear_History (void);
Xextern void	v1_puts (char *);
Xextern void	v1a_puts (char *);
Xextern void	v1_putc (char);
Xextern void	v1printf (char *, ...);
Xextern int	Get_stdin (IO_Args *);
Xextern int	Process_Escape (char **);
Xextern void	Add_History (bool);
Xextern void	Convert_Slashes (char *);
Xextern void	Print_ExTree (C_Op *);
Xextern Fun_Ops	*Fun_Search (char *);
Xextern void	Save_Function (C_Op *, bool);
Xextern int	getn (char *);
Xextern int	Create_NG_VL (void);
Xextern void	Delete_G_VL (void);
Xextern void	Restore_Dir (void);
Xextern void	Restore_Environment (int, int);
Xextern int	sort_compare (char **, char **);
Xextern int	Check_Script (char *);
SHAR_EOF
chmod 0644 shell/sh.h || echo "restore of shell/sh.h fails"
set `wc -c shell/sh.h`;Sum=$1
if test "$Sum" != "15317"
then echo original size 15317, current size $Sum;fi
rm -f s2_seq_.tmp
echo "You have unpacked the last part"
exit 0

-- 
Regards,

Ian Stewartson
Data Logic Ltd.