[net.sources] system

dag@pyramid.UUCP (David Gewirtz) (06/21/84)

Would someone post an exec() or system() call for Lattice C.

goldberg@uiucdcs.UUCP (06/24/84)

#R:pyramid:-16600:uiucdcs:12600018:000:6001
uiucdcs!goldberg    Jun 23 17:06:00 1984

Here is one I scarfed a while back...  I haven't even had a chance to play
with it yet, however.

				Phil Goldberg
		  University of Illinois @ Urbana-Champaign
		  ...!{convex,ihnp4,pur-ee}!uiucdcs!goldberg
			   goldberg.uiuc@csnet.arpa

<--------------------------------------------------------------------------->
/**** uiuccsc:net.sources / ihlpf!dap1 /  4:16 am  Nov 16, 1983 ****/
This routine implements the UN*X system call (in spite of the fact that I
called it exec, the name in the DOS manual) under Lattice C although it
should be easy to adopt it to other languages.  One caution, it uses the
undocumented 037h DOS call to retrieve the switch character.  This is
clearly marked in the code and I will change it after DOS 2.0 so I'd rather
the DOS purists don't jump down my throat about this.  If you don't like it
the way it is, change it.

                                                    Darrell Plank
                                                    BTL-IH
-----------------
PAGE 55,132
;
; This function is modified from the macro by Brad Davis (b-davis@utah-cs)
; The prolog and epilog are modified from Jim Holtman's macros for Pascal.
;
; exec( cmd)
; char *cmd;
;
; This function accepts a string with the pathname of a command to be
; executed and executes it.  The returned value is one of the following:
;	 0:	Successful
;	-1:	Insufficient Memory
;	-2:	Access Denied
;	-3:	No such command
;	-4:	Invalid command format
;

PROLOG	MACRO
	PUSH	BP
	MOV	BP,SP
	ENDM

EPILOG	MACRO	NUM
	POP	BP
	RET
	ENDM

EXECVAL	EQU	0
OVLVAL	EQU	3
FNCINT	EQU	21H
SETBLK	EQU	4AH
EXECF	EQU	4BH
CR	EQU	0DH

PSP     STRUC
INTVECT DW      ?
TOM     DW      ?
RES1    DB      ?
DOSLONG DB      5 DUP (?)
TERMINA DD      ?
CTRLBRK DD      ?
CRITERR DD      ?
DOS1    DB      22 DUP (?)
ENVIRO  DW      ?
DOS2    DB      46 DUP (?)
FPA1    DB      16 DUP (?)
FPA2    DB      20 DUP (?)
UPA     DB      128 DUP (?)
PSP     ENDS

EXECDEF STRUC
NENVIRO DW
COMMND  DW      2 DUP (0)
FCB5CH  DW      2 DUP (0)
FCB6CH  DW      2 DUP (0)
EXECDEF ENDS

PGROUP	GROUP PROG
PROG	SEGMENT BYTE PUBLIC 'prog'
	ASSUME CS:PGROUP

PUBLIC	EXEC
EXEC	PROC NEAR
        PROLOG
        PUSH    DS
        PUSH    ES
;
; free up as much memory as we can
;
	MOV	AX,CS
	PUSH	ES		; Save ES for later
	MOV	ES,AX
	MOV	BX,SS
	SUB	BX,AX
	ADD	BX,1000H	; 64K for stack segment
	MOV	AH,SETBLK
	INT	FNCINT
	JNC	NEAR PTR LBL1
	MOV	AX,-1		; Insufficient memory
	JMP	NEAR PTR FINE
LBL1:	POP	ES		; Get ES's original value
;
; Save SS and SP registers
;
        MOV     CS:SPSAVE,SP
        MOV     CS:SSSAVE,SS
;
; set up the parameter block
;
        MOV     CS:EXECBLK.NENVIRO,0	; Inherit envir. from parent
	MOV	AX,3700H		; Undocumented call for SWITCHAR
;
; W A R N I N G:  The following function call is undocumented and is
; liable to disappear or change in future versions of DOS.
;
	INT	FNCINT
	MOV	CS:COMMAND[1],DL	; Switchar
	MOV	DX,4[BP]		; Address of the command 
	MOV	SI,DX
	MOV	DI,DX
	CLD
	XOR	AL,AL
	MOV	CX,100H			; Longest string can be 100h
	REPNE SCASB			; Find Null termination
	SUB	DX,DI
	NEG	DX
	MOV	CX,DX
	DEC	CX
	ADD	DX,2
	MOV	CS:COMMAND[0],DL	; Save command length
	LEA	DI,CS:COMMAND[4]
	MOV	AX,CS
	MOV	ES,AX
	REP MOVSB			; Copy command into our buffer
ASSUME	DS:PGROUP
	MOV	AX,CS
	MOV	DS,AX			; DS points at code segment
	MOV	BYTE PTR [DI],CR	; Put in Carriage Return
	LEA	DX,COMMAND
        MOV     EXECBLK.COMMND[0],DX
        MOV     EXECBLK.COMMND[2],DS
	MOV	BX,OFFSET EXECBLK
        XOR     SI,SI
	MOV	DS,[SI].ENVIRO		; Get environment address
ASSUME	DS:NOTHING
	LEA	SI,CS:COMSPEC		; Point SI at env. variable name
	PUSH	DS			; Swap
	PUSH	ES			; ES
	POP	DS			; and
	POP	ES			; DS
	CALL	GETENV
	PUSH	DS			; Swap
	PUSH	ES			; them
	POP	DS			; back
	POP	ES			; again
        MOV     AH,EXECF
	MOV	AL,EXECVAL		; OVLVAL here for overlay
        INT     FNCINT
	JC	NEAR PTR LBL2
	MOV	AX,0			; Successful exec
	JMP	NEAR PTR FINE
LBL2:	MOV	SI,AX
	MOV	AL,CS:ERRORS[SI]	; Get error code
	MOV	AH,0FFH			; Sign extension - Assume Negative
FINE:   MOV     SS,CS:SSSAVE
        MOV     SP,CS:SPSAVE
        POP     ES
        POP     DS
	EPILOG	1
EXECBLK EXECDEF <>
;
; first byte of command is length excluding the length byte and the
; trailing \r.  Second byte is switchar.
;
COMMAND	DB	2 DUP(?),"C ",254 DUP(?)
COMSPEC	DB	"COMSPEC",0
SPSAVE  DW
SSSAVE  DW
ERRORS	DB	?
	DB	?
	DB	-3	; No such command
	DB	?
	DB	?
	DB	-2	; Access denied
	DB	?
	DB	?
	DB	-1	; Insufficient memory
	DB	?
	DB	?
	DB	-4	; Invalid command format

EXEC	ENDP

;
; Getenv expects ES to have the environment paragraph and DS:SI to point
; to an ASCIIZ string with the desired environment variable in it.
; It returns the address of the proper string in ds:dx.
;

	PUBLIC GETENV
GETENV	PROC NEAR

	PROLOG
	PUSH	AX
	PUSH	CX
	PUSH	SI
	PUSH	DI
	MOV	CS:VARNAME,SI		; Save offset of env. name
	XOR	DI,DI
;
; At this point ds:si points to dummy variable environment name and
; es:di points to environment.
;
	CLD				;Forward string operations
TOP:
	LODSB				;Get a char. of env. name
	CMP	AL,0			;If we're at the end
	JNE	NEAR PTR LBL3
	CMP	BYTE PTR ES:[DI],'='	;Check for match
	JNE	NEAR PTR LBL4
;
; We matched
;
	INC	DI			;Move beyond '='
	MOV	DX,DI
	POP	DI
	POP	SI
	POP	CX
	POP	AX
	EPILOG	2
LBL4:
;
; At this point we found the end of the Env. variable name but it didn't
; match because the env. string was too long
;
	MOV	CX,-1
	REPNE SCASB			;Find the end of the env. string
	CMP	BYTE PTR ES:[DI],0
	JNE	LBL3
	MOV	AX,-1			;End of environment area
	POP	DI
	POP	SI
	POP	CX
	POP	AX
	EPILOG	2
LBL3:
;
; Check if the next character matches
;
	AND	AX,11011111b		;Capitalize the character in ax
	SCASB
	JE	TOP
;
; If we get here we don't have a match so move on
;
	MOV	SI,CS:VARNAME		;Go back to start of env. string
	XOR	AX,AX
	MOV	CX,-1
	REPNE SCASB			;Go to next env. variable
	CMP	BYTE PTR ES:[DI],0
	JNE	TOP
	MOV	AX,-1			;End of environment area
	POP	DI
	POP	SI
	POP	CX
	POP	AX
	EPILOG	2
 
VARNAME	DW	?

GETENV	ENDP

PROG	ENDS
	END
/* ---------- */