Subversion Repositories SvarDOS

Compare Revisions

Ignore whitespace Rev 542 → Rev 543

/svarcom/trunk/command.c
731,6 → 731,7
static char *cmdline;
static struct redir_data redirprops;
static enum cmd_result cmdres;
static unsigned short i; /* general-purpose variable for short-lived things */
 
rmod = rmod_find(BUFFER_len);
if (rmod == NULL) {
793,6 → 794,13
/* (re)load translation strings if needed */
nls_langreload(BUFFER, *rmod_envseg);
 
/* load awaiting command, if any (used to run piped commands) */
if (rmod->awaitingcmd[0] != 0) {
_fstrcpy(cmdline, rmod->awaitingcmd);
rmod->awaitingcmd[0] = 0;
goto EXEC_CMDLINE;
}
 
/* skip user input if I have a command to exec (/C or /K) */
if (cfg.execcmd != NULL) {
cmdline = cfg.execcmd;
844,7 → 852,12
rmod_updatecomspecptr(rmod->rmodseg, *rmod_envseg);
 
/* handle redirections (if any) */
redir_parsecmd(&redirprops, cmdline);
i = redir_parsecmd(&redirprops, cmdline, rmod->awaitingcmd);
if (i != 0) {
nls_outputnl_doserr(i);
rmod->awaitingcmd[0] = 0;
continue;
}
 
/* try matching (and executing) an internal command */
cmdres = cmd_process(rmod, *rmod_envseg, cmdline, BUFFER, sizeof(BUFFER), &redirprops);
/svarcom/trunk/history.txt
6,6 → 6,7
=== ver 2021.1 (xx.xx.2021) ==================================================
 
- prompt fixed when current drive becomes invalid (eg. empty diskette drive)
- piping support (like dir/b | sort)
- DIR: fixed /P pagination in wide mode
- DIR: implemented /A
- implemented IF command (IF EXIST, IF ERRORLEVEL, IF str==str)
/svarcom/trunk/redir.c
24,6 → 24,7
 
#include <string.h> /* memset() */
 
#include "env.h"
#include "helpers.h"
#include "rmodinit.h"
 
32,13 → 33,44
static unsigned short oldstdout = 0xffff;
 
 
/* compute a filename to be used for pipes */
static unsigned short gentmpfile(char *s) {
unsigned short err = 0;
/* do I have a %temp% path? */
/* TODO */
 
/* if fails, then use truename(\) */
if (file_truename(".\\", s) != 0) *s = 0;
 
/* create file */
_asm {
mov ah, 0x5a
mov dx, s
xor cx, cx /* file attributes */
int 0x21
jnc CLOSEFILE
mov err, ax
jmp DONE
/* close file handle */
CLOSEFILE:
mov ah, 0x3e
mov bx, ax
int 0x21
DONE:
}
return(err);
}
 
#include <stdio.h>
/* parse commandline and performs necessary redirections. cmdline is
* modified so all redirections are cut out. */
void redir_parsecmd(struct redir_data *d, char *cmdline) {
* modified so all redirections are cut out.
* piped commands are move to awaitingcmd for later execution
* returns 0 on success, DOS err on failure */
unsigned short redir_parsecmd(struct redir_data *d, char *cmdline, char far *awaitingcmd) {
unsigned short i;
unsigned short pipescount = 0;
 
/* NOTE:
/* NOTES:
*
* 1. while it is possible to type a command with multiple
* redirections, MSDOS executes only the last redirection.
47,6 → 79,7
* not seem to matter for MSDOS. piped commands are executed first (in
* the order they appear) and the result of the last one is redirected to
* whenever the last > points at.
* stdin redirection (<) is (obviously) applied to the first command only
*/
 
/* preset oldstdout to 0xffff in case no redirection is required */
55,6 → 88,8
/* clear out the redir_data struct */
memset(d, 0, sizeof(*d));
 
*awaitingcmd = 0;
 
/* parse the command line and fill struct with pointers */
for (i = 0;; i++) {
if (cmdline[i] == '>') {
81,15 → 116,42
break;
}
}
 
/* if pipes present, write them to awaitingcmd (and stdout redirection too) */
if (pipescount != 0) {
static char tmpfile[130];
for (i = 0; i < pipescount; i++) {
if (i != 0) _fstrcat(awaitingcmd, "|");
_fstrcat(awaitingcmd, d->pipes[i]);
}
/* append stdout redirection so I don't forget about it for the last command of the pipe queue */
if (d->stdoutfile != NULL) {
if (d->stdout_openflag == 0x11) {
_fstrcat(awaitingcmd, ">>");
} else {
_fstrcat(awaitingcmd, ">");
}
d->stdoutfile = NULL;
}
/* redirect stdin of next command from a temp file (that is used as my output) */
_fstrcat(awaitingcmd, "<");
i = gentmpfile(tmpfile);
if (i != 0) return(i);
_fstrcat(awaitingcmd, tmpfile);
/* same file is used as my stdout */
d->stdoutfile = tmpfile;
d->stdout_openflag = 0x12;
/* TODO I need to remember that the tmp file must be removed... */
/* outputnl("awaitingcmd:");
for (i = 0; awaitingcmd[i] != 0; i++) printf("%c", awaitingcmd[i]);
printf("\r\n");*/
}
return(0);
}
 
 
/* apply stdin/stdout redirections defined in redir_data, returns 0 on success */
/* apply stdout redirections defined in redir_data, returns 0 on success */
int redir_apply(const struct redir_data *d) {
if (d->stdinfile != NULL) {
outputnl("ERROR: stdin redirection is not supported yet");
return(-1);
}
 
if (d->stdoutfile != NULL) {
unsigned short openflag = d->stdout_openflag;
156,7 → 218,7
}
 
 
/* restores previous stdout/stdin handlers if they have been redirected */
/* restores previous stdout handle if is has been redirected */
void redir_revert(void) {
_asm {
/* if oldstdout is 0xffff then not redirected */
/svarcom/trunk/redir.h
35,8 → 35,10
};
 
/* parse commandline and performs necessary redirections. cmdline is
* modified so all redirections are cut out. */
void redir_parsecmd(struct redir_data *r, char *cmdline);
* modified so all redirections are cut out.
* piped commands are move to awaitingcmd for later execution
* returns 0 on success, DOS err on failure */
unsigned short redir_parsecmd(struct redir_data *d, char *cmdline, char far *awaitingcmd);
 
/* apply stdin/stdout redirections defined in redir_data, returns 0 on success */
int redir_apply(const struct redir_data *d);
/svarcom/trunk/rmod.asm
81,7 → 81,7
call REVERT_REDIR_IF_ANY
 
; redirect stdout if required
call REDIR_OUTFILE_IF_REQUIRED
call REDIR_INOUTFILE_IF_REQUIRED
 
; should I executed command.com or a pre-set application?
or [EXECPROG], byte 0
201,6 → 201,21
int 0x21
mov [OLD_STDOUT], word 0xffff ; mark stdout as "not redirected"
STDOUT_DONE:
 
; is stdin redirected?
mov bx, [OLD_STDIN]
cmp bx, 0xffff
je STDIN_DONE
; revert the stdout handle (dst in BX already)
xor cx, cx ; src handle (0=stdin)
mov ah, 0x46 ; redirect a handle
int 0x21
; close the old handle (still in bx)
mov ah, 0x3e
int 0x21
mov [OLD_STDIN], word 0xffff ; mark stdin as "not redirected"
STDIN_DONE:
 
ret
; ----------------------------------------------------------------------------
 
207,7 → 222,7
 
; ----------------------------------------------------------------------------
; redirect stdout if REDIR_OUTFIL points to something
REDIR_OUTFILE_IF_REQUIRED:
REDIR_INOUTFILE_IF_REQUIRED:
mov si, [REDIR_OUTFIL]
cmp si, 0xffff
je NO_STDOUT_REDIR
248,5 → 263,33
mov ah, 0x3e ; close a file handle (handle in BX)
int 0x21
NO_STDOUT_REDIR:
 
; *** redirect stdin if REDIR_INFIL points to something ***
mov dx, [REDIR_INFIL]
cmp dx, 0xffff
je NO_STDIN_REDIR
add dx, EXECPROG ; ds:dx=file
mov ax, 0x3d00 ; open file for read
int 0x21 ; ax=handle on success (CF clear)
mov [REDIR_INFIL], word 0xffff
jc NO_STDIN_REDIR ; TODO: abort with an error message instead
 
; duplicate current stdin so I can revert it later
push ax ; save my file handle in stack
mov ah, 0x45 ; duplicate file handle BX
xor bx, bx ; 0=stdin
int 0x21 ; ax=new (duplicated) file handle
mov [OLD_STDIN], ax ; save the old handle in memory
 
; redirect stdout to my file
pop bx ; dst handle
xor cx, cx ; src handle (0=stdin)
mov ah, 0x46 ; "redirect a handle"
int 0x21
 
; close the original file handle, I no longer need it
mov ah, 0x3e ; close a file handle (handle in BX)
int 0x21
NO_STDIN_REDIR:
ret
; ----------------------------------------------------------------------------
/svarcom/trunk/rmodinit.h
41,6 → 41,7
char batfile[130]; /* truename of batch file being processed */
char batargv[130]; /* args of the batch call (0-separated) */
unsigned long batnextline; /* offset in file of next bat line to process */
char awaitingcmd[130]; /* command to exec next time (if any) */
};
 
#define RMOD_OFFSET_ENVSEG 0x2C /* stored in rmod's PSP */
/svarcom/trunk/svarcom.txt
11,16 → 11,13
Why replacing FreeCOM, you ask? See FREECOM.TXT for details.
 
SvarCOM is a work-in-progress effort. As such, it still lacks a few things:
- pipes (cmd.exe | more) and stdin redirections (cmd.exe < file)
- advanced batch constructs (conditionals, errorlevels...)
- a few internal commands missing: CALL, CTTY, GOTO, IF, LH
- DIR misses a few switches (/S, /O, /A)
- ... (see TODO.TXT for more details)
- a few internal commands missing: CALL, CTTY, GOTO, LH
- DIR misses two switches: /S, /O
 
SvarCOM is minimalist and I'd like to keep it that way. It aims to be
functionaly equivalent to COMMAND.COM from MS-DOS 5.x/6.x. No LFN support.
 
As of version 2021.0, SvarCOM's resident footprint is under 2 KiB.
As of version 2021.1, SvarCOM's resident footprint is under 2 KiB.
 
Translation strings are stored in the file SVARCOM.LNG, which should be
placed in a directory pointed at by %NLSPATH% for SvarCOM to be able to output
46,6 → 43,7
DIR - displays a list of files and subdirectories in a directory
ECHO - displays messages, or turns command-echoing on or off
EXIT - quits the command.com program (command interpreter)
IF - performs conditional processing in batch programs
MD/MKDIR - creates a directory
PATH - displays or sets a search path for executable files
PAUSE - suspends processing of a batch program
/svarcom/trunk/todo.txt
7,7 → 7,9
 
=== HIGH PRIORITY ============================================================
 
pipes redirections
delete temporary files after pipe redirections
write temporary pipe files to %TEMP% if defined
test pipe redirections (multiple redirections, failure to create file, ...)
int 24h handler (abort, retry, fail, ignore)
advanced batch constructs: CALL, FOR, GOTO
IF EXIST on an empty drive should not lead to the 'Abort, Retry, Fail' prompt