Subversion Repositories SvarDOS

Compare Revisions

Ignore whitespace Rev 349 → Rev 350

/svarcom/command.c
48,6 → 48,7
#include <i86.h>
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include <process.h>
57,16 → 58,41
struct config {
int locate;
int install;
int envsiz;
} cfg;
 
 
#define RMOD_OFFSET_ENVSEG 0x08
#define RMOD_OFFSET_INPBUFF 0x0A
#define RMOD_OFFSET_ROUTINE 0x8C
 
/* returns segment where rmod is installed */
unsigned short install_routine(void) {
char far *ptr, far *mcb;
unsigned short rmod_install(unsigned short envsize) {
char far *myptr, far *mcb;
unsigned short far *owner;
unsigned int memseg = 0xffff;
unsigned int rmodseg = 0xffff;
unsigned int envseg = 0;
 
/* read my current env segment from PSP */
_asm {
push ax
push bx
mov bx, 0x2c
mov ax, [bx]
mov envseg, ax
pop bx
pop ax
}
 
printf("original (PSP) env buffer at %04X\r\n", envseg);
/* if custom envsize requested, convert it to number of paragraphs */
if (envsize != 0) {
envsize += 15;
envsize /= 16;
}
 
 
_asm {
/* link in the UMB memory chain for enabling high-memory allocation (and save initial status on stack) */
mov ax, 0x5802 /* GET UMB LINK STATE */
int 0x21
84,12 → 110,21
mov ax, 0x5801
mov bx, 0x0082
int 0x21
/* ask for a memory block and save the given segment to memseg */
/* ask for a memory block and save the given segment to rmodseg */
mov ah, 0x48
mov bx, (rmod_len + 15) / 16
int 0x21
jc ALLOC_FAIL
mov memseg, ax
mov rmodseg, ax
/* ask for a memory block for the environment and save it to envseg (only if custom size requested) */
mov bx, envsize
test bx, bx
jz ALLOC_FAIL
mov ah, 0x48
int 0x21
jc ALLOC_FAIL
mov envseg, ax
 
ALLOC_FAIL:
/* restore initial allocation strategy */
mov ax, 0x5801
101,15 → 136,35
int 0x21
}
 
if (memseg == 0xffff) {
if (rmodseg == 0xffff) {
puts("malloc error");
return(0xffff);
}
ptr = MK_FP(memseg, 0);
mcb = MK_FP(memseg - 1, 0);
 
/* copy rmod to its destination */
myptr = MK_FP(rmodseg, 0);
_fmemcpy(myptr, rmod, rmod_len);
 
/* mark rmod memory as "self owned" */
mcb = MK_FP(rmodseg - 1, 0);
owner = (void far *)(mcb + 1);
_fmemcpy(ptr, rmod, rmod_len);
*owner = rmodseg;
_fmemcpy(mcb + 8, "SVARCOM", 8);
 
/* mark env memory as "self owned" (only if allocated by me) */
if (envsize != 0) {
printf("envseg allocated at %04X:0000 with %u paragraphs\r\n", envseg, envsize);
mcb = MK_FP(envseg - 1, 0);
owner = (void far *)(mcb + 1);
*owner = rmodseg;
_fmemcpy(mcb + 8, "SVARENV", 8);
}
 
/* write env segment to rmod buffer */
owner = MK_FP(rmodseg, RMOD_OFFSET_ENVSEG);
*owner = envseg;
 
/*
printf("MCB sig: %c\r\nMCB owner: 0x%04X\r\n", mcb[0], *owner);
{
int i;
125,28 → 180,41
}
}
printf("\r\n");
}
}*/
 
/* mark memory as "self owned" */
*owner = memseg;
_fmemcpy(mcb + 8, "COMMAND", 8);
return(memseg);
return(rmodseg);
}
 
 
/* returns zero if s1 starts with s2 */
static int strstartswith(const char *s1, const char *s2) {
while (*s2 != 0) {
if (*s1 != *s2) return(-1);
s1++;
s2++;
}
return(0);
}
 
 
static void parse_argv(struct config *cfg, int argc, char **argv) {
int i;
memset(cfg, 0, sizeof(*cfg));
 
for (i = 1; i < argc; i++) {
if (strcmp(argv[i], "/locate") == 0) {
cfg->locate = 1;
}
if (strstartswith(argv[i], "/e:") == 0) {
cfg->envsiz = atoi(argv[i]+3);
if (cfg->envsiz < 64) cfg->envsiz = 0;
}
}
}
 
 
/* scan memory for my shared buffer, return segment of buffer */
static unsigned short find_shm(void) {
static unsigned short rmod_find(void) {
unsigned short i;
unsigned short far *pattern;
 
153,10 → 221,10
/* iterate over all paragraphs, looking for my signature */
for (i = 0; i != 65535; i++) {
pattern = MK_FP(i, 0);
if (pattern[1] != 0x1983) continue;
if (pattern[2] != 0x1985) continue;
if (pattern[3] != 0x2017) continue;
if (pattern[4] != 0x2019) continue;
if (pattern[0] != 0x1983) continue;
if (pattern[1] != 0x1985) continue;
if (pattern[2] != 0x2017) continue;
if (pattern[3] != 0x2019) continue;
return(i);
}
return(0xffff);
206,16 → 274,16
 
int main(int argc, char **argv) {
struct config cfg;
unsigned short env_seg = 0, rmod_seg, rmod_buff = 0;
void far *rmod_func;
unsigned short rmod_seg;
unsigned short far *rmod_envseg;
 
parse_argv(&cfg, argc, argv);
 
rmod_seg = find_shm();
rmod_seg = rmod_find();
if (rmod_seg == 0xffff) {
rmod_seg = install_routine();
rmod_seg = rmod_install(cfg.envsiz);
if (rmod_seg == 0xffff) {
puts("ERROR: install_rmod() failed");
puts("ERROR: rmod_install() failed");
return(1);
} else {
printf("rmod installed at seg 0x%04X\r\n", rmod_seg);
224,15 → 292,16
printf("rmod found at seg 0x%04x\r\n", rmod_seg);
}
 
rmod_func = MK_FP(rmod_seg, 0x0A);
/* fetch offset of buffer (result in AX) */
_asm {
call dword ptr [rmod_func]
mov rmod_buff, ax
rmod_envseg = MK_FP(rmod_seg, RMOD_OFFSET_ENVSEG);
 
{
unsigned short envsiz;
unsigned short far *sizptr = MK_FP(*rmod_envseg - 1, 3);
envsiz = *sizptr;
envsiz *= 16;
printf("rmod_inpbuff at %04X:%04X, env_seg at %04X:0000 (env_size = %u bytes)\r\n", rmod_seg, RMOD_OFFSET_INPBUFF, *rmod_envseg, envsiz);
}
 
printf("rmod_buff at %04X:%04X\r\n", rmod_seg, rmod_buff);
 
_asm {
/* set the int22 handler in my PSP to rmod so DOS jumps to rmod after I terminate */
mov bx, 0x0a
240,17 → 309,11
mov [bx], ax
mov ax, rmod_seg
mov [bx+2], ax
/* get the segment of my environment */
mov bx, 0x2c
mov ax, [bx]
mov env_seg, ax
}
 
printf("env_seg at %04X\r\n", env_seg);
 
for (;;) {
int i, argcount;
char far *cmdline = MK_FP(rmod_seg, rmod_buff + 2);
char far *cmdline = MK_FP(rmod_seg, RMOD_OFFSET_INPBUFF + 2);
char path[256] = "C:\\>$";
char const *argvlist[256];
union REGS r;
273,7 → 336,7
mov ax, rmod_seg
push ax
pop ds
mov dx, rmod_buff
mov dx, RMOD_OFFSET_INPBUFF
 
/* execute either DOS input or DOSKEY */
test bl, bl /* zf set if no DOSKEY present */
310,7 → 373,7
 
/* TODO is it an internal command? */
if (strcmp(argvlist[0], "set") == 0) {
cmd_set(argcount, argvlist, env_seg);
cmd_set(argcount, argvlist, *rmod_envseg);
continue;
}
 
/svarcom/rmod.asm
13,23 → 13,23
 
section .text ; all goes into code segment
 
jmp short skipsig
; offset
SIG1 dw 0x1983 ; +0
SIG2 dw 0x1985 ; +2
SIG3 dw 0x2017 ; +4
SIG4 dw 0x2019 ; +6
 
SIG1 dw 0x1983
SIG2 dw 0x1985
SIG3 dw 0x2017
SIG4 dw 0x2019
; environment segment - this is updated by SvarCOM at init time
ENVSEG dw 0 ; +8
 
; service routine: used by the transient part of svarcom, returns:
; AX = offset of input buffer history block
; BX = offset where environment's segment is stored (patched at install time)
inputroutine:
mov ax, BUF000
mov bx, ENVSEG
retf
; input buffer used for the "previous command" history
BUF000 db 128, 0 ; +0Ah
BUF064 db "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
BUF128 db "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
 
skipsig:
 
skipsig: ; +8Ch
 
; set up CS=DS=SS and point SP to my private stack buffer
mov ax, cs
mov ds, ax
38,7 → 38,8
mov sp, STACKPTR
 
; prepare the exec param block
;mov [EXEC_PARAM_REC], word 0
mov ax, [ENVSEG]
mov [EXEC_PARAM_REC], ax
mov ax, COMSPEC
mov [EXEC_PARAM_REC+2], ax
mov [EXEC_PARAM_REC+4], ds
83,15 → 84,7
COMSPEC db "C:\SVN\SVARDOS\SVARCOM\COMMAND.COM"
COMSPCZ db 0
 
; input buffer used for the "previous command" history
BUF000 db 128, 0
BUF064 db "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
BUF128 db "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
 
; FreeDOS int 21h functions that I use require at least 32 bytes of stack,
; here I allocate 64 bytes to be sure
STACKBUF db "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
STACKPTR db "xx"
 
; environment segment - this is updated by SvarCOM at init time
ENVSEG dw 0
/svarcom/rmod.h
1,25 → 1,25
const char rmod[] = {
235, 15,131, 25,133, 25, 23, 32, 25, 32,184,169, 0,187,109, 1,
203,140,200,142,216,142,192,142,208,188,107, 1,184,134, 0,163,
81, 0,140, 30, 83, 0,184, 0, 75,186,134, 0,187, 79, 0,205,
33,115,222, 4, 48,162, 97, 0,180, 9,186, 93, 0,198, 6,168,
0, 36,205, 33,198, 6,168, 0, 0,180, 8,205, 33,235,194, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 82, 82,
32,120, 44, 32, 70, 65, 73, 76, 69, 68, 32, 84, 79, 32, 76, 79,
65, 68, 32, 67, 79, 77, 77, 65, 78, 68, 46, 67, 79, 77, 32, 70,
82, 79, 77, 58, 13, 10, 67, 58, 92, 83, 86, 78, 92, 83, 86, 65,
82, 68, 79, 83, 92, 83, 86, 65, 82, 67, 79, 77, 92, 67, 79, 77,
77, 65, 78, 68, 46, 67, 79, 77, 0,128, 0, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70,120,120, 0, 0};
#define rmod_len 367
131, 25,133, 25, 23, 32, 25, 32, 0, 0,128, 0, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70,140,200,142,216,
142,192,142,208,188,106, 1,161, 8, 0,163,208, 0,184, 7, 1,
163,210, 0,140, 30,212, 0,184, 0, 75,186, 7, 1,187,208, 0,
205, 33,115,216, 4, 48,162,226, 0,180, 9,186,222, 0,198, 6,
41, 1, 36,205, 33,198, 6, 41, 1, 0,180, 8,205, 33,235,188,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 82,
82, 32,120, 44, 32, 70, 65, 73, 76, 69, 68, 32, 84, 79, 32, 76,
79, 65, 68, 32, 67, 79, 77, 77, 65, 78, 68, 46, 67, 79, 77, 32,
70, 82, 79, 77, 58, 13, 10, 67, 58, 92, 83, 86, 78, 92, 83, 86,
65, 82, 68, 79, 83, 92, 83, 86, 65, 82, 67, 79, 77, 92, 67, 79,
77, 77, 65, 78, 68, 46, 67, 79, 77, 0, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 65, 66, 67, 68, 69, 70,120,120};
#define rmod_len 364