/svarcom/trunk/cmd/echo.c |
---|
29,7 → 29,7 |
static int cmd_echo(struct cmd_funcparam *p) { |
unsigned short offs = FP_OFF(p->cmdline) + 5; |
unsigned short segm = FP_SEG(p->cmdline); |
unsigned char far *echostatus = MK_FP(p->rmod_seg, RMOD_OFFSET_ECHOFLAG); |
unsigned char far *echostatus = MK_FP(p->rmod->rmodseg, RMOD_OFFSET_ECHOFLAG); |
/* display help only if /? is the only argument */ |
if ((p->argc == 1) && (imatch(p->argv[0], "/?"))) { |
/svarcom/trunk/cmd/exit.c |
---|
34,7 → 34,7 |
outputnl("EXIT\r\n"); |
outputnl("Quits the COMMAND.COM program (command interpreter)"); |
} else { |
sayonara(p->rmod_seg); |
sayonara(p->rmod); |
} |
return(-1); |
} |
/svarcom/trunk/cmd.c |
---|
45,7 → 45,7 |
int argc; /* number of arguments */ |
const char *argv[256]; /* pointers to each argument */ |
unsigned short env_seg; /* segment of environment block */ |
unsigned short rmod_seg; /* segment of the resident module */ |
struct rmod_props far *rmod; /* rmod settings */ |
unsigned short argoffset; /* offset of cmdline where first argument starts */ |
const char far *cmdline; /* original cmdline (terminated by a NULL) */ |
char BUFFER[BUFFER_SIZE]; /* a buffer for whatever is needed */ |
189,7 → 189,7 |
} |
int cmd_process(unsigned short rmod_seg, unsigned short env_seg, const char far *cmdline, char *BUFFER) { |
int cmd_process(struct rmod_props far *rmod, unsigned short env_seg, const char far *cmdline, char *BUFFER) { |
const struct CMD_ID *cmdptr; |
unsigned short argoffset; |
struct cmd_funcparam *p = (void *)BUFFER; |
230,7 → 230,7 |
/* prepare function parameters and feed it to the cmd handling function */ |
p->argc = cmd_explode(BUFFER + sizeof(*p), cmdline + argoffset, p->argv); |
p->env_seg = env_seg; |
p->rmod_seg = rmod_seg; |
p->rmod = rmod; |
p->argoffset = argoffset; |
p->cmdline = cmdline; |
/svarcom/trunk/cmd.h |
---|
25,8 → 25,10 |
#ifndef CMD_H |
#define CMD_H |
#include "rmodinit.h" |
/* process internal commands */ |
int cmd_process(unsigned short env_rmod, unsigned short env_seg, const char far *cmdline, char *BUFFER); |
int cmd_process(struct rmod_props far *rmod, unsigned short env_seg, const char far *cmdline, char *BUFFER); |
/* explodes a command into an array of arguments where last arg is NULL |
* returns number of args */ |
/svarcom/trunk/command.c |
---|
79,10 → 79,9 |
#include "rmodinit.h" |
#include "sayonara.h" |
#define FLAG_EXEC_AND_QUIT 1 |
struct config { |
unsigned char flags; |
unsigned char flags; /* command.com flags, as defined in rmodinit.h */ |
char *execcmd; |
unsigned short envsiz; |
}; |
131,6 → 130,11 |
if (cfg->envsiz < 64) cfg->envsiz = 0; |
break; |
case 'p': /* permanent shell (can't exit) */ |
case 'P': |
cfg->flags |= FLAG_PERMANENT; |
break; |
case '?': |
outputnl("Starts the SvarCOM command interpreter"); |
outputnl(""); |
137,6 → 141,7 |
outputnl("COMMAND /E:nnn [/[C|K] command]"); |
outputnl(""); |
outputnl("/E:nnn Sets the environment size to nnn bytes"); |
outputnl("/P Makes the new command interpreter permanent (can't exit)"); |
outputnl("/C Executes the specified command and returns"); |
outputnl("/K Executes the specified command and continues running"); |
exit(1); |
324,21 → 329,25 |
static unsigned short far *rmod_envseg; |
static unsigned short far *lastexitcode; |
static unsigned char BUFFER[4096]; |
static struct rmod_props far *rmod; |
parse_argv(&cfg); |
rmod_seg = rmod_find(); |
if (rmod_seg == 0xffff) { |
rmod_seg = rmod_install(cfg.envsiz); |
if (rmod_seg == 0xffff) { |
rmod = rmod_find(); |
if (rmod == NULL) { |
rmod = rmod_install(cfg.envsiz); |
if (rmod == NULL) { |
outputnl("ERROR: rmod_install() failed"); |
return(1); |
} |
/* copy flags to rmod's storage */ |
rmod->flags = cfg.flags; |
/* printf("rmod installed at seg 0x%04X\r\n", rmod_seg); */ |
} else { |
/* printf("rmod found at seg 0x%04x\r\n", rmod_seg); */ |
} |
rmod_seg = rmod->rmodseg; |
rmod_envseg = MK_FP(rmod_seg, RMOD_OFFSET_ENVSEG); |
lastexitcode = MK_FP(rmod_seg, RMOD_OFFSET_LEXITCODE); |
459,7 → 468,7 |
} |
/* try matching (and executing) an internal command */ |
if (cmd_process(rmod_seg, *rmod_envseg, cmdline, BUFFER) >= -1) { |
if (cmd_process(rmod, *rmod_envseg, cmdline, BUFFER) >= -1) { |
/* internal command executed */ |
redir_revert(); /* revert stdout (in case it was redirected) */ |
continue; |
475,8 → 484,8 |
if I am still alive then external command failed to execute */ |
outputnl("Bad command or file name"); |
} while ((cfg.flags & FLAG_EXEC_AND_QUIT) == 0); |
} while ((rmod->flags & FLAG_EXEC_AND_QUIT) == 0); |
sayonara(rmod_seg); |
sayonara(rmod); |
return(0); |
} |
/svarcom/trunk/rmodinit.c |
---|
33,12 → 33,14 |
#include "rmodinit.h" |
/* returns segment where rmod is installed */ |
unsigned short rmod_install(unsigned short envsize) { |
/* returns far pointer to rmod's settings block on success */ |
struct rmod_props far *rmod_install(unsigned short envsize) { |
char far *myptr, far *mcb; |
unsigned short far *owner; |
const unsigned short sizeof_rmodandprops_paras = rmod_len + sizeof(struct rmod_props) + 15 / 16; |
unsigned int rmodseg = 0xffff; |
unsigned int envseg = 0; |
struct rmod_props far *res = NULL; |
/* read my current env segment from PSP */ |
_asm { |
52,6 → 54,10 |
} |
/* printf("original (PSP) env buffer at %04X\r\n", envseg); */ |
/* if envseg is zero, then enforce our own one (MSDOS 5 does not provide a default env) */ |
if ((envseg == 0) && (envsize == 0)) envsize = 256; |
/* if custom envsize requested, convert it to number of paragraphs */ |
if (envsize != 0) { |
envsize += 15; |
79,7 → 85,7 |
int 0x21 |
/* ask for a memory block and save the given segment to rmodseg */ |
mov ah, 0x48 |
mov bx, (rmod_len + 15) / 16 |
mov bx, sizeof_rmodandprops_paras |
int 0x21 |
jc ALLOC_FAIL |
mov rmodseg, ax |
105,7 → 111,7 |
if (rmodseg == 0xffff) { |
outputnl("malloc error"); |
return(0xffff); |
return(NULL); |
} |
/* copy rmod to its destination */ |
124,6 → 130,18 |
*owner = rmodseg; |
_fmemcpy(mcb + 8, "SVARENV", 8); |
/* if env block is newly allocated, fill it with a few NULLs */ |
if (envsize != 0) { |
owner = MK_FP(envseg, 0); |
owner[0] = 0; |
owner[1] = 0; |
} |
/* prepare result (rmod props) */ |
res = MK_FP(rmodseg, rmod_len); |
_fmemset(res, 0, sizeof(*res)); |
res->rmodseg = rmodseg; |
/* write env segment to rmod buffer */ |
owner = MK_FP(rmodseg, RMOD_OFFSET_ENVSEG); |
*owner = envseg; |
179,13 → 197,13 |
pop ax |
} |
return(rmodseg); |
return(res); |
} |
/* look up my parent: if it's rmod then return its segment, |
* otherwise return 0xffff */ |
unsigned short rmod_find(void) { |
/* look up my parent: if it's rmod then return a ptr to its props struct, |
* otherwise return NULL */ |
struct rmod_props far *rmod_find(void) { |
unsigned short *parent = (void *)0x0C; /* parent's seg in PSP[Ch] ("prev. int22 handler") */ |
unsigned short far *ptr; |
const unsigned short sig[] = {0x1983, 0x1985, 0x2017, 0x2019}; |
192,9 → 210,9 |
unsigned char i; |
/* is it rmod? */ |
ptr = MK_FP(*parent, 0); |
for (i = 0; i < 4; i++) if (ptr[i] != sig[i]) return(0xffff); |
for (i = 0; i < 4; i++) if (ptr[i] != sig[i]) return(NULL); |
/* match successfull (rmod is my parent) */ |
return(*parent); |
return(MK_FP(*parent, rmod_len)); |
} |
/svarcom/trunk/rmodinit.h |
---|
25,6 → 25,14 |
#ifndef RMODINIT_H |
#define RMODINIT_H |
#define FLAG_EXEC_AND_QUIT 1 |
#define FLAG_PERMANENT 2 |
struct rmod_props { |
unsigned short rmodseg; |
unsigned char flags; |
}; |
#define RMOD_OFFSET_ENVSEG 0x08 |
#define RMOD_OFFSET_LEXITCODE 0x0A |
#define RMOD_OFFSET_INPBUFF 0x0C |
35,8 → 43,8 |
#define RMOD_OFFSET_ORIGPARENT 0xA2 |
#define RMOD_OFFSET_ROUTINE 0xA6 |
unsigned short rmod_install(unsigned short envsize); |
unsigned short rmod_find(void); |
struct rmod_props far *rmod_install(unsigned short envsize); |
struct rmod_props far *rmod_find(void); |
void rmod_updatecomspecptr(unsigned short rmod_seg, unsigned short env_seg); |
#endif |
/svarcom/trunk/sayonara.c |
---|
31,14 → 31,18 |
/* rewires my parent pointer, uninstalls rmod let DOS terminate me, UNLESS |
* my parent is unknown */ |
void sayonara(unsigned short rmodseg) { |
void sayonara(struct rmod_props far *rmod) { |
unsigned short rmodseg = rmod->rmodseg; |
unsigned long far *orgparent = MK_FP(rmodseg, RMOD_OFFSET_ORIGPARENT); |
unsigned long *myparent = (void *)0x0A; |
unsigned short far *rmodenv_ptr = MK_FP(rmodseg, RMOD_OFFSET_ENVSEG); |
unsigned short rmodenv = *rmodenv_ptr; |
/* set my parent back to original value (if 0 = shell is permanent) */ |
if (*orgparent == 0) return; |
/* detect "I am the origin shell" situations */ |
if (*orgparent == 0xffff) return; /* original parent set to 0xffff (DOS-C / FreeDOS) */ |
if (rmod->flags & FLAG_PERMANENT) return; /* COMMAND.COM /P */ |
/* set my parent back to original value */ |
*myparent = *orgparent; |
_asm { |
/svarcom/trunk/sayonara.h |
---|
25,8 → 25,10 |
#ifndef SAYONARA_H |
#define SAYONARA_H |
#include "rmodinit.h" |
/* rewires my parent pointer, uninstalls rmod let DOS terminate me, UNLESS |
* my parent is unknown */ |
void sayonara(unsigned short rmodseg); |
void sayonara(struct rmod_props far *rmod); |
#endif |
/svarcom/trunk/todo.txt |
---|
13,7 → 13,7 |
pipes redirections |
basic BAT support (without workflow controls, FOR loops etc) |
merge adjacent assembly blocks in rmod_install() |
/P switch for permanent copy |
investigate why COMSPEC is not set properly |
AT SOME LATER TIME: |