Subversion Repositories SvarDOS

Compare Revisions

Ignore whitespace Rev 350 → Rev 349

/svarcom/command.c
48,7 → 48,6
#include <i86.h>
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
#include <process.h>
58,41 → 57,16
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 rmod_install(unsigned short envsize) {
char far *myptr, far *mcb;
unsigned short install_routine(void) {
char far *ptr, far *mcb;
unsigned short far *owner;
unsigned int rmodseg = 0xffff;
unsigned int envseg = 0;
unsigned int memseg = 0xffff;
 
/* 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
110,21 → 84,12
mov ax, 0x5801
mov bx, 0x0082
int 0x21
/* ask for a memory block and save the given segment to rmodseg */
/* ask for a memory block and save the given segment to memseg */
mov ah, 0x48
mov bx, (rmod_len + 15) / 16
int 0x21
jc ALLOC_FAIL
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
 
mov memseg, ax
ALLOC_FAIL:
/* restore initial allocation strategy */
mov ax, 0x5801
136,35 → 101,15
int 0x21
}
 
if (rmodseg == 0xffff) {
if (memseg == 0xffff) {
puts("malloc error");
return(0xffff);
}
 
/* 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);
ptr = MK_FP(memseg, 0);
mcb = MK_FP(memseg - 1, 0);
owner = (void far *)(mcb + 1);
*owner = rmodseg;
_fmemcpy(mcb + 8, "SVARCOM", 8);
_fmemcpy(ptr, rmod, rmod_len);
 
/* 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;
180,41 → 125,28
}
}
printf("\r\n");
}*/
}
 
return(rmodseg);
/* mark memory as "self owned" */
*owner = memseg;
_fmemcpy(mcb + 8, "COMMAND", 8);
return(memseg);
}
 
 
/* 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 rmod_find(void) {
static unsigned short find_shm(void) {
unsigned short i;
unsigned short far *pattern;
 
221,10 → 153,10
/* iterate over all paragraphs, looking for my signature */
for (i = 0; i != 65535; i++) {
pattern = MK_FP(i, 0);
if (pattern[0] != 0x1983) continue;
if (pattern[1] != 0x1985) continue;
if (pattern[2] != 0x2017) continue;
if (pattern[3] != 0x2019) continue;
if (pattern[1] != 0x1983) continue;
if (pattern[2] != 0x1985) continue;
if (pattern[3] != 0x2017) continue;
if (pattern[4] != 0x2019) continue;
return(i);
}
return(0xffff);
274,16 → 206,16
 
int main(int argc, char **argv) {
struct config cfg;
unsigned short rmod_seg;
unsigned short far *rmod_envseg;
unsigned short env_seg = 0, rmod_seg, rmod_buff = 0;
void far *rmod_func;
 
parse_argv(&cfg, argc, argv);
 
rmod_seg = rmod_find();
rmod_seg = find_shm();
if (rmod_seg == 0xffff) {
rmod_seg = rmod_install(cfg.envsiz);
rmod_seg = install_routine();
if (rmod_seg == 0xffff) {
puts("ERROR: rmod_install() failed");
puts("ERROR: install_rmod() failed");
return(1);
} else {
printf("rmod installed at seg 0x%04X\r\n", rmod_seg);
292,16 → 224,15
printf("rmod found at seg 0x%04x\r\n", rmod_seg);
}
 
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);
rmod_func = MK_FP(rmod_seg, 0x0A);
/* fetch offset of buffer (result in AX) */
_asm {
call dword ptr [rmod_func]
mov rmod_buff, ax
}
 
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
309,11 → 240,17
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_OFFSET_INPBUFF + 2);
char far *cmdline = MK_FP(rmod_seg, rmod_buff + 2);
char path[256] = "C:\\>$";
char const *argvlist[256];
union REGS r;
336,7 → 273,7
mov ax, rmod_seg
push ax
pop ds
mov dx, RMOD_OFFSET_INPBUFF
mov dx, rmod_buff
 
/* execute either DOS input or DOSKEY */
test bl, bl /* zf set if no DOSKEY present */
373,7 → 310,7
 
/* TODO is it an internal command? */
if (strcmp(argvlist[0], "set") == 0) {
cmd_set(argcount, argvlist, *rmod_envseg);
cmd_set(argcount, argvlist, env_seg);
continue;
}
 
/svarcom/rmod.asm
13,23 → 13,23
 
section .text ; all goes into code segment
 
; offset
SIG1 dw 0x1983 ; +0
SIG2 dw 0x1985 ; +2
SIG3 dw 0x2017 ; +4
SIG4 dw 0x2019 ; +6
jmp short skipsig
 
; environment segment - this is updated by SvarCOM at init time
ENVSEG dw 0 ; +8
SIG1 dw 0x1983
SIG2 dw 0x1985
SIG3 dw 0x2017
SIG4 dw 0x2019
 
; input buffer used for the "previous command" history
BUF000 db 128, 0 ; +0Ah
BUF064 db "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
BUF128 db "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
; 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
 
skipsig:
 
skipsig: ; +8Ch
 
; set up CS=DS=SS and point SP to my private stack buffer
mov ax, cs
mov ds, ax
38,8 → 38,7
mov sp, STACKPTR
 
; prepare the exec param block
mov ax, [ENVSEG]
mov [EXEC_PARAM_REC], ax
;mov [EXEC_PARAM_REC], word 0
mov ax, COMSPEC
mov [EXEC_PARAM_REC+2], ax
mov [EXEC_PARAM_REC+4], ds
84,7 → 83,15
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[] = {
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
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