//svarcom/trunk/cmd.c |
---|
202,7 → 202,7 |
} |
enum cmd_result cmd_process(struct rmod_props far *rmod, unsigned short env_seg, const char *cmdline, void *BUFFER, unsigned short BUFFERSZ, const struct redir_data *redir) { |
enum cmd_result cmd_process(struct rmod_props far *rmod, unsigned short env_seg, const char *cmdline, void *BUFFER, unsigned short BUFFERSZ, const struct redir_data *redir, unsigned char delstdin) { |
const struct CMD_ID *cmdptr; |
unsigned short argoffset; |
enum cmd_result cmdres; |
258,5 → 258,28 |
/* cancel redirections */ |
redir_revert(); |
/* delete stdin temporary file */ |
if (delstdin) { |
const char *fname = redir->stdinfile; |
unsigned short doserr = 0; |
_asm { |
push ax |
push dx |
mov ah, 0x41 /* delete a file */ |
mov dx, fname /* DS:DX - filename to delete */ |
int 0x21 |
jnc DONE |
mov doserr, ax |
DONE: |
pop dx |
pop ax |
} |
if (doserr) { |
output(fname); |
output(": "); |
nls_outputnl_doserr(doserr); |
} |
} |
return(cmdres); |
} |
//svarcom/trunk/cmd.h |
---|
1,7 → 1,7 |
/* This file is part of the SvarCOM project and is published under the terms |
* of the MIT license. |
* |
* Copyright (C) 2021 Mateusz Viste |
* Copyright (C) 2021-2022 Mateusz Viste |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
36,7 → 36,7 |
}; |
/* process internal commands */ |
enum cmd_result cmd_process(struct rmod_props far *rmod, unsigned short env_seg, const char *cmdline, void *BUFFER, unsigned short BUFFERSZ, const struct redir_data *r); |
enum cmd_result cmd_process(struct rmod_props far *rmod, unsigned short env_seg, const char *cmdline, void *BUFFER, unsigned short BUFFERSZ, const struct redir_data *r, unsigned char delstdin); |
/* explodes a command into an array of arguments where last arg is NULL. |
* if argvlist is not NULL, it will be filled with pointers that point to buff |
//svarcom/trunk/command.c |
---|
315,7 → 315,7 |
} |
static void run_as_external(char *buff, const char *cmdline, unsigned short envseg, struct rmod_props far *rmod, struct redir_data *redir) { |
static void run_as_external(char *buff, const char *cmdline, unsigned short envseg, struct rmod_props far *rmod, struct redir_data *redir, unsigned char delete_stdin_file) { |
char *cmdfile = buff + 512; |
const char far *pathptr; |
int lookup; |
451,7 → 451,13 |
/* copy stdin file if a redirection is needed */ |
if (redir->stdinfile) { |
char far *farptr = MK_FP(rmod->rmodseg, RMOD_OFFSET_STDINFILE); |
char far *delstdin = MK_FP(rmod->rmodseg, RMOD_OFFSET_STDIN_DEL); |
_fstrcpy(farptr, redir->stdinfile); |
if (delete_stdin_file) { |
*delstdin = redir->stdinfile[0]; |
} else { |
*delstdin = 0; |
} |
} |
/* same for stdout file */ |
734,6 → 740,7 |
static struct redir_data redirprops; |
static enum cmd_result cmdres; |
static unsigned short i; /* general-purpose variable for short-lived things */ |
static unsigned char delete_stdin_file; |
rmod = rmod_find(BUFFER_len); |
if (rmod == NULL) { |
794,9 → 801,6 |
SKIP_NEWLINE: |
/* cancel any redirections that may have been set up before */ |
redir_revert(); |
/* memory check */ |
memguard_check(rmod->rmodseg, cmdlinebuf); |
810,7 → 814,10 |
if (rmod->awaitingcmd[0] != 0) { |
_fstrcpy(cmdline, rmod->awaitingcmd); |
rmod->awaitingcmd[0] = 0; |
delete_stdin_file = 1; |
goto EXEC_CMDLINE; |
} else { |
delete_stdin_file = 0; |
} |
/* skip user input if I have a command to exec (/C or /K) */ |
872,7 → 879,7 |
} |
/* try matching (and executing) an internal command */ |
cmdres = cmd_process(rmod, *rmod_envseg, cmdline, BUFFER, sizeof(BUFFER), &redirprops); |
cmdres = cmd_process(rmod, *rmod_envseg, cmdline, BUFFER, sizeof(BUFFER), &redirprops, delete_stdin_file); |
if ((cmdres == CMD_OK) || (cmdres == CMD_FAIL)) { |
/* internal command executed */ |
continue; |
880,7 → 887,7 |
goto EXEC_CMDLINE; |
} else if (cmdres == CMD_NOTFOUND) { |
/* this was not an internal command, try matching an external command */ |
run_as_external(BUFFER, cmdline, *rmod_envseg, rmod, &redirprops); |
run_as_external(BUFFER, cmdline, *rmod_envseg, rmod, &redirprops, delete_stdin_file); |
/* perhaps this is a newly launched BAT file */ |
if ((rmod->batfile[0] != 0) && (rmod->batnextline == 0)) goto SKIP_NEWLINE; |
/* run_as_external() does not return on success, if I am still alive then |
//svarcom/trunk/internal.txt |
---|
41,6 → 41,26 |
the process. |
=== PIPING COMMANDS ========================================================== |
Piping a command means redirecting its standard output (stdout) to the |
standard input (stdin) of another command. While redirection of file handles |
is a concept well supported by the DOS kernels, piping is not, in part due to |
the mono-task nature of DOS. SvarCOM provides piping support through following |
logic: |
1. user-entered (or batch-acquired) command line is analyzed for any kind of |
redirections (incl. pipes) by redir_parsecmd(). If the command appears to |
be piped, then redir_parsecmd() enforces a stdout redirection to a |
temporary file and moves all the pipe chain to an RMOD-owned buffer named |
"awaitingcmd", appending an stdin redirection so the next command's stdin |
is fed from the temporary file. The command is then executed. |
2. before further execution, SvarCOM looks into its "awaitingcmd" buffer, and |
if it is non-empty, it runs its content. |
3. when loading commands from the awaitingcmd, SvarCOM sets a special |
"delete_stdin_file" flag and passes it to command-executing functions so |
these remember to delete the stdin-redirected file. |
=== GLOBAL EXECUTABLE LINKS ================================================== |
SvarCOM features special support for "global executable links". This allows to |
//svarcom/trunk/rmod.asm |
---|
52,17 → 52,21 |
REDIR_INFIL: times 128 db 0 ; +EAh |
REDIR_OUTFIL: times 128 db 0 ; +16Ah |
REDIR_OUTAPPEND: dw 0 ; +1EAh |
REDIR_DEL_STDIN: db 0 ; +1ECh indicates that the stdin file |
; should be deleted (pipes). This |
; MUST contain the 1st char of |
; REDIR_INFIL! |
; CTRL+BREAK (int 23h) handler |
; According to the TechHelp! Manual: "If you want to abort (exit to the parent |
; process), then set the carry flag and return via a FAR RET. This causes DOS |
; to perform normal cleanup and exit to the parent." (otherwise use iret) |
BREAK_HANDLER: ; +1ECh |
BREAK_HANDLER: ; +1EDh |
stc |
retf |
skipsig: ; +1EEh |
skipsig: ; +1EFh |
; set up CS=DS=SS and point SP to my private stack buffer |
mov ax, cs |
79,7 → 83,7 |
; revert stdin/stdout redirections (if any) to their initial state |
call REVERT_REDIR_IF_ANY |
; redirect stdout if required |
; redirect stdin and/or stdout if required |
call REDIR_INOUTFILE_IF_REQUIRED |
; should I executed command.com or a pre-set application? |
184,8 → 188,6 |
; ---------------------------------------------------------------------------- |
; revert stdin/stdout redirections (if any) to their initial state |
; all memory accesses are CS-prefixes because this code may be called at |
; times when DS is out of whack. |
REVERT_REDIR_IF_ANY: |
; is stdout redirected? |
mov bx, [OLD_STDOUT] |
213,6 → 215,19 |
mov ah, 0x3e |
int 0x21 |
mov [OLD_STDIN], word 0xffff ; mark stdin as "not redirected" |
; delete stdin file if required |
cmp [REDIR_DEL_STDIN], byte 0 |
je STDIN_DONE |
; revert the original file and delete it |
mov ah, [REDIR_DEL_STDIN] |
mov [REDIR_INFIL], ah |
mov ah, 0x41 ; DOS 2+ - delete file pointed at by DS:DX |
mov dx, REDIR_INFIL |
int 0x21 |
mov [REDIR_INFIL], byte 0 |
mov [REDIR_DEL_STDIN], byte 0 |
STDIN_DONE: |
ret |
//svarcom/trunk/rmodinit.h |
---|
53,8 → 53,9 |
#define RMOD_OFFSET_STDINFILE (0x100 + 0xEA) |
#define RMOD_OFFSET_STDOUTFILE (0x100 + 0x16A) |
#define RMOD_OFFSET_STDOUTAPP (0x100 + 0x1EA) |
#define RMOD_OFFSET_BRKHANDLER (0x100 + 0x1EC) |
#define RMOD_OFFSET_ROUTINE (0x100 + 0x1EE) |
#define RMOD_OFFSET_STDIN_DEL (0x100 + 0x1EC) |
#define RMOD_OFFSET_BRKHANDLER (0x100 + 0x1ED) |
#define RMOD_OFFSET_ROUTINE (0x100 + 0x1EF) |
struct rmod_props far *rmod_install(unsigned short envsize, unsigned char *rmodcore, unsigned short rmodcore_len); |
struct rmod_props far *rmod_find(unsigned short rmodcore_len); |
//svarcom/trunk/todo.txt |
---|
7,7 → 7,6 |
=== HIGH PRIORITY ============================================================ |
delete temporary files after pipe redirections |
write temporary pipe files to %TEMP% if defined |
int 24h handler (abort, retry, fail, ignore) |
advanced batch constructs: CALL, FOR, GOTO |