From decwrl!ucbvax!tut.cis.ohio-state.edu!pacific.mps.ohio-state.edu!zaphod.mps.ohio-state.edu!usc!cs.utexas.edu!uunet!allbery Sun Feb 18 00:49:05 PST 1990 Article 1329 of comp.sources.misc: Path: decwrl!ucbvax!tut.cis.ohio-state.edu!pacific.mps.ohio-state.edu!zaphod.mps.ohio-state.edu!usc!cs.utexas.edu!uunet!allbery From: istewart@datlog.co.uk (Ian Stewartson) Newsgroups: comp.sources.misc Subject: v10i058: MSDOS Shell (sh) Implementation - Part 05 of 05 Message-ID: <78917@uunet.UU.NET> Date: 14 Feb 90 01:57:00 GMT Sender: allbery@uunet.UU.NET Organization: ITM Sector, Data Logic Ltd. (A Raytheon Company) Lines: 1316 Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) 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; /* $ values */ Xextern int dolc; /* $ 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.