Subversion Repositories SvarDOS

Compare Revisions

Ignore whitespace Rev 516 → Rev 517

/svarcom/trunk/cmd.c
36,6 → 36,7
#include "doserr.h"
#include "env.h"
#include "helpers.h"
#include "redir.h"
#include "rmodinit.h"
#include "sayonara.h"
 
198,9 → 199,10
}
 
 
int cmd_process(struct rmod_props far *rmod, unsigned short env_seg, const char *cmdline, void *BUFFER, unsigned short BUFFERSZ) {
int cmd_process(struct rmod_props far *rmod, unsigned short env_seg, const char *cmdline, void *BUFFER, unsigned short BUFFERSZ, const struct redir_data *redir) {
const struct CMD_ID *cmdptr;
unsigned short argoffset;
int cmdres;
struct cmd_funcparam *p = (void *)BUFFER;
p->BUFFERSZ = BUFFERSZ - sizeof(*p);
 
237,6 → 239,9
 
/* printf("recognized internal command: '%s', tail of command at offset %u\r\n", cmdptr->cmd, argoffset); */
 
/* apply redirections (if any) */
if (redir_apply(redir) != 0) return(-1);
 
/* prepare function parameters and feed it to the cmd handling function */
p->argc = cmd_explode(p->argvbuf, cmdline + argoffset, p->argv);
p->env_seg = env_seg;
244,5 → 249,10
p->argoffset = argoffset;
p->cmdline = cmdline;
 
return((cmdptr->func_ptr)(p));
cmdres = (cmdptr->func_ptr)(p);
 
/* cancel redirections */
redir_revert();
 
return(cmdres);
}
/svarcom/trunk/cmd.h
28,7 → 28,7
#include "rmodinit.h"
 
/* process internal commands */
int cmd_process(struct rmod_props far *rmod, unsigned short env_seg, const char *cmdline, void *BUFFER, unsigned short BUFFERSZ);
int cmd_process(struct rmod_props far *rmod, unsigned short env_seg, const char *cmdline, void *BUFFER, unsigned short BUFFERSZ, const struct redir_data *r);
 
/* 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
350,7 → 350,7
}
 
 
static void run_as_external(char *buff, const char *cmdline, unsigned short envseg, struct rmod_props far *rmod) {
static void run_as_external(char *buff, const char *cmdline, unsigned short envseg, struct rmod_props far *rmod, struct redir_data *redir) {
char *cmdfile = buff + 512;
const char far *pathptr;
int lookup;
429,9 → 429,30
return;
}
 
/* copy full filename to execute */
/* copy full filename to execute, along with redirected files (if any) */
for (i = 0; cmdfile[i] != 0; i++) rmod_execprog[i] = cmdfile[i];
rmod_execprog[i] = 0;
rmod_execprog[i++] = 0;
if (redir->stdinfile) {
unsigned short far *farptr = MK_FP(rmod->rmodseg, RMOD_OFFSET_STDINFILE);
unsigned short t;
*farptr = i;
for (t = 0;; t++) {
rmod_execprog[i++] = redir->stdinfile[t];
if (redir->stdinfile[t] == 0) break;
}
}
if (redir->stdoutfile) {
unsigned short far *farptr = MK_FP(rmod->rmodseg, RMOD_OFFSET_STDOUTFILE);
unsigned short t;
*farptr = i;
for (t = 0;; t++) {
rmod_execprog[i++] = redir->stdoutfile[t];
if (redir->stdoutfile[t] == 0) break;
}
/* openflag */
farptr = MK_FP(rmod->rmodseg, RMOD_OFFSET_STDOUTAPP);
*farptr = redir->stdout_openflag;
}
 
/* copy cmdtail to rmod's PSP and compute its len */
for (i = 0; cmdtail[i] != 0; i++) rmod_cmdtail[i] = cmdtail[i];
701,6 → 722,7
static struct rmod_props far *rmod;
static char cmdlinebuf[CMDLINE_MAXLEN + 2]; /* 1 extra byte for 0-terminator and another for memguard */
static char *cmdline;
static struct redir_data redirprops;
 
rmod = rmod_find(BUFFER_len);
if (rmod == NULL) {
814,26 → 836,19
rmod_updatecomspecptr(rmod->rmodseg, *rmod_envseg);
 
/* handle redirections (if any) */
if (redir_parsecmd(cmdline, BUFFER) != 0) {
outputnl("");
continue;
}
redir_parsecmd(&redirprops, cmdline);
 
/* try matching (and executing) an internal command */
if (cmd_process(rmod, *rmod_envseg, cmdline, BUFFER, sizeof(BUFFER)) >= -1) {
if (cmd_process(rmod, *rmod_envseg, cmdline, BUFFER, sizeof(BUFFER), &redirprops) >= -1) {
/* internal command executed */
redir_revert(); /* revert stdout (in case it was redirected) */
continue;
}
 
/* if here, then this was not an internal command */
run_as_external(BUFFER, cmdline, *rmod_envseg, rmod);
run_as_external(BUFFER, cmdline, *rmod_envseg, rmod, &redirprops);
/* perhaps this is a newly launched BAT file */
if ((rmod->batfile[0] != 0) && (rmod->batnextline == 0)) goto SKIP_NEWLINE;
 
/* revert stdout (so the err msg is not redirected) */
redir_revert();
 
/* run_as_external() does not return on success, if I am still alive then
* external command failed to execute */
outputnl("Bad command or file name");
/svarcom/trunk/redir.c
22,21 → 22,21
* DEALINGS IN THE SOFTWARE.
*/
 
#include <string.h> /* memset() */
 
#include "doserr.h"
#include "helpers.h"
#include "rmodinit.h"
 
#include "redir.h"
 
static unsigned short oldstdout = 0xffff;
 
 
/* parse commandline and performs necessary redirections. cmdline is
* modified so all redirections are cut out.
* returns 0 on success, non-zero otherwise */
int redir_parsecmd(char *cmdline, char *BUFFER) {
* modified so all redirections are cut out. */
void redir_parsecmd(struct redir_data *d, char *cmdline) {
unsigned short i;
unsigned short rediroffset_stdin = 0;
unsigned short rediroffset_stdout = 0;
unsigned short pipesoffsets[16];
unsigned short pipescount = 0;
 
/* NOTE:
53,51 → 53,51
/* preset oldstdout to 0xffff in case no redirection is required */
oldstdout = 0xffff;
 
/* clear out the redir_data struct */
memset(d, 0, sizeof(*d));
 
/* parse the command line and fill struct with pointers */
for (i = 0;; i++) {
if (cmdline[i] == '>') {
cmdline[i] = 0;
rediroffset_stdout = i + 1;
if (cmdline[i + 1] == '>') {
i++;
d->stdout_openflag = 0x11; /* used during int 21h,AH=6C */
} else {
d->stdout_openflag = 0x12;
}
d->stdoutfile = cmdline + i + 1;
while (d->stdoutfile[0] == ' ') d->stdoutfile++;
} else if (cmdline[i] == '<') {
cmdline[i] = 0;
rediroffset_stdin = i + 1;
d->stdinfile = cmdline + i + 1;
while (d->stdinfile[0] == ' ') d->stdinfile++;
} else if (cmdline[i] == '|') {
cmdline[i] = 0;
pipesoffsets[pipescount++] = i + 1;
if (pipescount < REDIR_MAX_PIPES) {
d->pipes[pipescount++] = cmdline + i + 1;
while (d->pipes[pipescount][0] == ' ') d->pipes[pipescount]++;
}
} else if (cmdline[i] == 0) {
break;
}
}
}
 
if (rediroffset_stdin != 0) {
 
/* apply stdin/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 (pipescount != 0) {
outputnl("ERROR: pipe redirections are not supported yet");
return(-1);
}
 
if (rediroffset_stdout != 0) {
unsigned short openflag = 0x12; /* used during the int 21h,ah=6c call */
if (d->stdoutfile != NULL) {
unsigned short openflag = d->stdout_openflag;
unsigned short errcode = 0;
unsigned short handle = 0;
char *ptr;
/* append? */
if (cmdline[rediroffset_stdout] == '>') {
openflag = 0x11;
rediroffset_stdout++;
}
const char *myptr = d->stdoutfile;
 
/* copy dst file to BUFFER */
ptr = cmdline + rediroffset_stdout;
while (*ptr == ' ') ptr++; /* skip leading white spaces */
for (i = 0;; i++) {
BUFFER[i] = ptr[i];
if ((BUFFER[i] == ' ') || (BUFFER[i] == 0)) break;
}
BUFFER[i] = 0;
 
/* */
_asm {
push ax
109,7 → 109,7
mov bx, 1 /* access mode (0=read, 1=write, 2=r+w */
xor cx, cx /* attributes when(if) creating the file (0=normal) */
mov dx, [openflag] /* action if file exists (0x11=open, 0x12=truncate)*/
mov si, BUFFER /* ASCIIZ filename */
mov si, myptr /* ASCIIZ filename */
int 0x21 /* AX=handle on success (CF clear), otherwise dos err */
mov [handle], ax /* save the file handler */
jnc DUPSTDOUT
/svarcom/trunk/redir.h
25,11 → 25,22
#ifndef REDIR_H
#define REDIR_H
 
#define REDIR_MAX_PIPES 15
 
struct redir_data {
char *pipes[REDIR_MAX_PIPES + 1];
char *stdinfile;
char *stdoutfile;
unsigned short stdout_openflag; /* 0x11 or 0x12, used for the 'extended open' call */
};
 
/* parse commandline and performs necessary redirections. cmdline is
* modified so all redirections are cut out.
* returns 0 on success, non-zero otherwise */
int redir_parsecmd(char *cmdline, char *BUFFER);
* modified so all redirections are cut out. */
void redir_parsecmd(struct redir_data *r, char *cmdline);
 
/* apply stdin/stdout redirections defined in redir_data, returns 0 on success */
int redir_apply(const struct redir_data *d);
 
/* restores previous stdout/stdin handlers if they have been redirected */
void redir_revert(void);
 
/svarcom/trunk/rmod.asm
48,8 → 48,14
; Program to execute, preset by SvarCOM (128 bytes, ASCIIZ) ; +6Bh
EXECPROG dd 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 
skipsig: ; +EBh
; offset within EXECPROG for out and in filenames in case stdin or stdout
; needs to be redirected (0xffff=no redirection)
REDIR_OUTFIL dw 0xffff ; +EBh
REDIR_INFIL dw 0xffff ; +EDh
REDIR_OUTAPPEND dw 0 ; +EFh
 
skipsig: ; +F1h
 
; set up CS=DS=SS and point SP to my private stack buffer
mov ax, cs
mov ds, ax
57,6 → 63,12
mov ss, ax
mov sp, STACKPTR
 
; revert stdin/stdout redirections (if any) to their initial state
call REVERT_REDIR_IF_ANY
 
; redirect stdout if required
call REDIR_OUTFILE_IF_REQUIRED
 
; should I executed command.com or a pre-set application?
or [EXECPROG], byte 0
jz EXEC_COMMAND_COM
148,3 → 160,57
CMDTAIL db 0x01, 0x0A, 0x0D
 
ERRLOAD db "ERR x, FAILED TO LOAD COMMAND.COM", 13, 10, '$'
 
; variables used to revert stdin/stdout to their initial state
OLD_STDOUT dw 0xffff
OLD_STDIN dw 0xffff
 
 
; *** ROUTINES ***************************************************************
 
 
; 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]
cmp bx, 0xffff
je STDOUT_DONE
; revert the stdout handle (dst in BX alread)
mov cx, 1 ; src handle (1=stdout)
mov ah, 0x46 ; redirect a handle
int 0x21
mov [OLD_STDOUT], word 0xffff ; mark stdout as "not redirected"
STDOUT_DONE:
ret
 
 
; redirect stdout if REDIR_OUTFIL points to something
REDIR_OUTFILE_IF_REQUIRED:
mov si, [REDIR_OUTFIL]
cmp si, 0xffff
je NO_STDOUT_REDIR
add si, EXECPROG ; si=output file
mov ax, 0x6c00 ; Extended Open/Create
mov bx, 1 ; access mode (0=read, 1=write, 2=r+w)
xor cx, cx ; file attribs when(if) file is created (0=normal)
mov dx, [REDIR_OUTAPPEND] ; action if file exist (0x11=open, 0x12=truncate)
int 0x21 ; ax=handle on success (CF clear)
mov [REDIR_OUTFIL], word 0xffff
jc NO_STDOUT_REDIR ; TODO: abort with an error message instead
; duplicate current stdout so I can revert it later
push ax ; save my file handle in stack
mov ah, 0x45 ; duplicate file handle BX
mov bx, 1 ; 1=stdout
int 0x21 ; ax=new (duplicated) file handle
mov [OLD_STDOUT], ax ; save the old handle in memory
; redirect stdout to my file
pop bx ; dst handle
mov cx, 1 ; src handle (1=stdout)
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)
NO_STDOUT_REDIR:
ret
/svarcom/trunk/rmodinit.h
49,7 → 49,10
#define RMOD_OFFSET_BOOTDRIVE (0x100 + 0x4E)
#define RMOD_OFFSET_EXECPARAM (0x100 + 0x5D)
#define RMOD_OFFSET_EXECPROG (0x100 + 0x6B)
#define RMOD_OFFSET_ROUTINE (0x100 + 0xEB)
#define RMOD_OFFSET_STDOUTFILE (0x100 + 0xEB)
#define RMOD_OFFSET_STDINFILE (0x100 + 0xED)
#define RMOD_OFFSET_STDOUTAPP (0x100 + 0xEF)
#define RMOD_OFFSET_ROUTINE (0x100 + 0xF1)
 
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,12 → 7,16
 
=== HIGH PRIORITY ============================================================
 
redirections to be handled (applied) by RMOD
pipes redirections
DIR /A
ctrl+break handler
int 24h handler (abort, retry, fail, ignore)
advanced batch constructs: CALL, :labels, FOR, GOTO, IF EXIST/ERRORLEVEL
del review: sometimes says "file not found" while file xxx exists, or does
not complain when even though file does not exists... also it
probably does not work with deleting anything in non-current
directory
when reverting redirections I should probably close the old handle
 
 
=== MEDIUM PRIORITY ==========================================================