Subversion Repositories SvarDOS

Compare Revisions

Ignore whitespace Rev 575 → Rev 576

/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