home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 October
/
VPR9710A.ISO
/
BENCH
/
DJ1SRC_K
/
105
/
CONTROL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-05-02
|
28KB
|
1,145 lines
/* This is file CONTROL.C */
/*
** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
**
** This file is distributed under the terms listed in the document
** "copying.dj", available from DJ Delorie at the address above.
** A copy of "copying.dj" should accompany this file; if not, a copy
** should be available from where this file was obtained. This file
** may not be distributed without a verbatim copy of "copying.dj".
**
** This file is distributed WITHOUT ANY WARRANTY; without even the implied
** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
/* 1997/05/01 modified by Kimio Itoh(kitoh@nn.iij4u.or.jp)
for reduce binary size and for dead code elimination.
and merged control.c and exphdlr.c
*/
/* History:87,1 */
#include "build.h"
TSS *tss_ptr;
int debug_mode = 0;
static int self_contained;
long header_offset = 0;
int use_ansi = 0;
int use_mono = 0;
static int redir_1_mono = 0;
static int redir_2_mono = 0;
static int redir_2_1 = 0;
static int redir_1_2 = 0;
static int old_video_mode;
static int16 ems_handle = 0; /* Get EMS Handle */
word16 vcpi_installed = 0; /* VCPI Installed Flag */
#if DEBUGGER
extern void debugger(void);
#else
extern void go_til_stop(void);
#endif
extern int cputype(void);
extern int detect_80387(void);
extern go_real_mode();
extern void vcpi_flush(void); /* VCPI Memory All Cleared */
extern ivec0(), ivec1(), ivec7(), ivec75();
extern interrupt_common(), page_fault();
extern word32 far *pd;
static void init_controllers(void);
static void uninit_controllers(void);
static void __pascal set_command_line(char **argv, char **envv);
static void __pascal fillgdt(int sel, word32 limit, word32 base, word8 type, int G)
{
GDT_S *g;
g = gdt + sel;
if (G & 2)
limit = limit >> 12;
g->lim0 = (word16) limit;
g->lim1 = (word8) (limit >> 16) & 0x0f;
g->base0 = (word16) base;
g->base1 = (word8) (base >> 16);
g->base2 = (word8) (base >> 24);
g->stype = type;
g->lim1 |= G * 0x40;
}
word32 __pascal ptr2linear(void far * ptr)
{
word32 linear = (word32) FP_SEG(ptr) * 16L + (word32) FP_OFF(ptr);
return linear;
}
static void __pascal setup_tss(TSS * t, int (*eip) ())
{
memset(t, 0, sizeof(TSS));
t->tss_eip = (long)FP_OFF(eip);
t->tss_esp = (long)FP_OFF(t->tss_stack);
t->tss_cs = g_rcode * 8;
t->tss_ss = t->tss_ds = t->tss_es = t->tss_fs = t->tss_gs = g_rdata * 8;
t->tss_eflags = 0x0200;
t->tss_iomap = 0xffff; /* no map */
}
static void exit_func(void)
{
#if TOPLINEINFO
int i;
#endif
dalloc_uninit();
uninit_controllers();
xms_free();
if ((ems_handle) && (ems_handle != -1))
ems_free(ems_handle); /* Deallocated EMS Page */
if (vcpi_installed)
vcpi_flush(); /* Deallocated VCPI Pages */
#if TOPLINEINFO
for (i = 0; i < 80; i++)
poke(screen_seg, i * 2, 0x0720);
#endif
}
static int ctrl_c_flag = 0;
static int ctrlbrk_func(void)
{
#if DEBUGGER
ctrl_c_flag = 1;
#else
exit(3);
#endif
return 0;
}
static void usage(char *s)
{
printf("Usage: %s [program [options . . . ]]\n", s);
_exit(1);
}
int have_80387;
int use_xms = 0;
static word32 __pascal push32(void *ptr, int len);
int main(int argc, char **argv, char **envp)
{
int i, n, set_brk, emu_installed;
struct stat stbuf;
char *cp, *path, *argv0, *emu_fn = 0;
unsigned short header[3];
set_brk = emu_installed = 0;
if (xms_installed())
use_xms = 1;
old_video_mode = peekb(0x40, 0x49);
if (!strcmp(argv[1], "!proxy")) {
int oseg, optr, i;
int far *oargv;
char far *oargve;
sscanf(argv[2], "%x", &argc);
sscanf(argv[3], "%x", &oseg);
sscanf(argv[4], "%x", &optr);
oargv = MK_FP(oseg, optr);
argv = (char **)malloc(sizeof(char *) * (argc + 1));
for (i = 0; i < argc + 1; i++) {
if (!oargv[i]) {
argv[i] = 0;
break;
}
oargve = MK_FP(oseg, oargv[i]);
for (optr = 0; oargve[optr]; optr++);
argv[i] = (char *)malloc(optr + 1);
for (optr = 0; oargve[optr]; optr++)
argv[i][optr] = oargve[optr];
argv[i][optr] = 0;
}
}
ems_handle = emm_present();
switch (cputype()) {
case 1:
if ((ems_handle) && (ems_handle != -1))
ems_free(ems_handle);
fprintf(stderr, "CPU must be a 386 to run this program.\n");
exit(1);
case 2:
if (ems_handle) {
vcpi_installed = vcpi_present();
if (vcpi_installed)
break;
else if (ems_handle != -1)
ems_free(ems_handle);
}
fprintf(stderr, "CPU must be in REAL mode (not V86 mode) to run this program.\n");
exit(1);
}
if (peekb(0x40, 0x49) == 7)
screen_seg = 0xb000;
_fmode = O_BINARY;
cp = getenv("GO32");
path = 0;
if (cp)
while (1) {
char sw[100];
char val[100];
if (sscanf(cp, "%s%n", sw, &i) < 1)
break;
cp += i;
if (!strcmp(sw, "ansi"))
use_ansi = 1;
else if (!strcmp(sw, "mono"))
use_mono = 1;
else if (!strcmp(sw, "2r1"))
redir_2_1 = 1;
else if (!strcmp(sw, "1r2"))
redir_1_2 = 1;
else if (!strcmp(sw, "2rm"))
redir_2_mono = 1;
else if (!strcmp(sw, "1rm"))
redir_1_mono = 1;
else {
val[0] = 0;
sscanf(cp, "%s%n", val, &i);
cp += i;
if (!val[0])
break;
}
if (!strcmp(sw, "driver")) {
if (path)
free(path);
path = strdup(val);
} else if (!strcmp(sw, "tw"))
gr_def_tw = atoi(val);
else if (!strcmp(sw, "th"))
gr_def_th = atoi(val);
else if (!strcmp(sw, "gw"))
gr_def_gw = atoi(val);
else if (!strcmp(sw, "gh"))
gr_def_gh = atoi(val);
else if (!strcmp(sw, "emu")) {
if (emu_fn)
free(emu_fn);
emu_fn = strdup(val);
}
}
#if ! DEBUGGER
use_mono = 0;
#endif
setup_graphics_driver(path);
if (path)
free(path);
#if DEBUGGER
if (use_mono) {
use_ansi = 0;
screen_seg = 0xb000;
}
#endif
setbuf(stdin, 0);
atexit((atexit_t) exit_func);
ctrlbrk(ctrlbrk_func);
n = (int)ivec1 - (int)ivec0;
for (i = 0; i < 256; i++) {
idt[i].selector = g_rcode * 8;
idt[i].stype = 0x8e00;
idt[i].offset0 = FP_OFF((int)ivec0 + n * i);
idt[i].offset1 = 0;
}
idt[14].selector = g_ptss * 8;
idt[14].stype = 0x8500;
idt[14].offset0 = idt[14].offset1 = 0;
cp = getenv("387");
if (cp)
if (tolower(cp[0]) == 'n')
have_80387 = 0;
else if (tolower(cp[0]) == 'y')
have_80387 = 1;
else
have_80387 = detect_80387();
else
have_80387 = detect_80387();
if (have_80387) {
idt[7].offset0 = (int)ivec7;
idt[0x75].offset0 = (int)ivec75;
idt[7].offset1 = idt[0x75].offset1 = 0;
}
if (cp && (tolower(cp[0]) == 'q'))
if (have_80387)
printf("An 80387 has been detected.\n");
else
printf("No 80387 has been detected.\n");
fillgdt(g_zero, 0, 0, 0, 0);
fillgdt(g_gdt, sizeof(gdt), ptr2linear(gdt), 0x92, 0);
fillgdt(g_idt, sizeof(idt), ptr2linear(idt), 0x92, 0);
fillgdt(g_rcode, 0xffff, (word32) _CS * 16L, 0x9a, 0);
fillgdt(g_rdata, 0xffff, (word32) _DS * 16L, 0x92, 0);
fillgdt(g_core, 0xffffffffL, 0, 0x92, 3);
fillgdt(g_acode, 0xefffffffL, 0x10000000L, 0x9a, 3);
fillgdt(g_adata, 0xefffffffL, 0x10000000L, 0x92, 3);
fillgdt(g_ctss, sizeof(TSS), ptr2linear(&c_tss), 0x89, 1);
fillgdt(g_atss, sizeof(TSS), ptr2linear(&a_tss), 0x89, 1);
fillgdt(g_ptss, sizeof(TSS), ptr2linear(&p_tss), 0x89, 1);
fillgdt(g_itss, sizeof(TSS), ptr2linear(&i_tss), 0x89, 1);
fillgdt(g_rc32, 0xffff, (word32) _CS * 16L, 0x9a, 3);
fillgdt(g_grdr, 0xffff, (word32) gr_paging_segment * 16L, 0x9a, 0);
setup_tss(&c_tss, go_real_mode);
setup_tss(&a_tss, go_real_mode);
setup_tss(&o_tss, go_real_mode);
setup_tss(&f_tss, go_real_mode);
setup_tss(&i_tss, interrupt_common);
setup_tss(&p_tss, page_fault);
tss_ptr = &a_tss;
argv0 = argv[0];
for (i = 0; argv0[i]; i++) {
if (argv0[i] == '\\')
argv0[i] = '/';
argv0[i] = tolower(argv0[i]);
}
if (!strcmp(argv[1], "-nobrk")) {
set_brk = 1;
argv++;
argc--;
}
#if TOPLINEINFO
for (i = 0; i < 80; i++)
poke(screen_seg, i * 2, 0x0720);
#endif
self_contained = 0;
n = open(argv0, O_RDONLY | O_BINARY);
header[0] = 0;
read(n, header, sizeof(header));
if (header[0] == 0x5a4d) {
header_offset = (long)header[1] + ((long)header[2] - 1) * 512L;
lseek(n, header_offset, 0);
header[0] = 0;
read(n, header, sizeof(header));
if (header[0] == 0x010b)
self_contained = 1;
}
if (self_contained) {
#if DEBUGGER
debug_mode = 1;
#else
debug_mode = 0;
#endif
paging_set_file(argv0);
emu_installed = emu_install(emu_fn);
set_command_line(argv, envp);
#if DEBUGGER
syms_init(argv0);
#endif
} else {
header_offset = 0;
for (cp = argv0; *cp; cp++)
if (*cp == '.')
path = cp;
*path = 0;
if (stat(argv0, &stbuf)) { /* not found */
fprintf(stderr, "%s.exe Copyright (C) 1991 DJ Delorie\n", argv0);
debug_mode = 1;
if (!argv[1])
usage(argv0);
paging_set_file(argv[1]);
emu_installed = emu_install(emu_fn);
set_command_line(argv + 1, envp);
#if DEBUGGER
syms_init(argv[1]);
#endif
} else { /* found */
debug_mode = 0;
paging_set_file(argv0);
emu_installed = emu_install(emu_fn);
set_command_line(argv, envp);
#if DEBUGGER
syms_init(argv0);
#endif
}
}
if (set_brk)
paging_brk(0x8fffffffL);
dalloc_init();
init_controllers();
if (emu_installed) {
push32(&(a_tss.tss_eip), 4);
a_tss.tss_eip = 0xb0000020L;
}
#if DEBUGGER
debugger();
if (peekb(0x40, 0x49) != old_video_mode) {
_AX = old_video_mode;
geninterrupt(0x10);
}
return 0;
#else
go_til_stop();
if (tss_ptr->tss_irqn == 0x79)
fprintf(stderr, "Ctrl-C Hit! Stopped at address %lx\n", tss_ptr->tss_eip);
else
fprintf(stderr, "Exception %d at eip=%lx\n", tss_ptr->tss_irqn, tss_ptr->tss_eip);
return 1;
#endif
}
static word32 __pascal push32(void *ptr, int len)
{
if ((a_tss.tss_esp & ~0xFFF) != ((a_tss.tss_esp - len) & ~0xFFF)) {
a_tss.tss_cr2 = a_tss.tss_esp - len + ARENA;
page_in();
}
a_tss.tss_esp -= len;
a_tss.tss_esp = a_tss.tss_esp & (~3);
memput(a_tss.tss_esp + ARENA, ptr, len);
return a_tss.tss_esp;
}
static void __pascal foreach_arg(char **argv, void __fastcall(*func) (char *))
{
int i;
FILE *f;
char buf[80];
for (i = 0; argv[i]; i++) {
if (argv[i][0] == '@') {
f = fopen(argv[i] + 1, "rt");
while (fscanf(f, "%s", buf) == 1) {
if (strcmp(buf, "\032"))
func(buf);
}
fclose(f);
} else
func(argv[i]);
}
}
static int num_actual_args;
static void __fastcall just_incr(char *d)
{
num_actual_args++;
}
static word32 *a;
static void __fastcall pusharg(char *ar)
{
a[num_actual_args] = push32(ar, strlen(ar) + 1);
num_actual_args++;
}
static void __pascal set_command_line(char **argv, char **envv)
{
unsigned envc;
word32 *e, v, argp, envp;
a_tss.tss_cr2 = a_tss.tss_esp + ARENA;
page_in();
num_actual_args = 0;
foreach_arg(argv, just_incr);
for (envc = 0; envv[envc]; envc++);
e = (word32 *) malloc((envc + 1) * sizeof(word32));
if (!e) {
printf("Fatal! no memory to copy environment\n");
exit(1);
}
for (envc = 0; envv[envc]; envc++) {
v = push32(envv[envc], strlen(envv[envc]) + 1);
e[envc] = v;
}
e[envc] = 0;
a = (word32 *) malloc((num_actual_args + 1) * sizeof(word32));
if (!a) {
printf("Fatal! no memory to copy arguments\n");
exit(1);
}
num_actual_args = 0;
foreach_arg(argv, pusharg);
a[num_actual_args] = 0;
envp = push32(e, (envc + 1) * sizeof(word32));
argp = push32(a, (num_actual_args + 1) * sizeof(word32));
push32(&envp, sizeof(word32));
push32(&argp, sizeof(word32));
v = num_actual_args;
push32(&v, sizeof(word32));
}
/* This is file EXPHDLR.C */
#define SEGFAULT(p) { \
printf("Segmentation violation in pointer %#08lx\n", (p)); \
return 1; \
}
extern word32 far *graphics_pt;
static word16 master_pic = 0x08; /* Default IRQ0 Vector */
static char transfer_buffer[4096]; /* must be near ptr for small model */
static word32 user_dta;
static struct REGPACK r;
static int in_graphics_mode = 0;
static int generic_handler(void);
static int i_10(void);
static int i_21(void);
static int i_33(void);
static int turbo_assist(void);
static int i_21_44(void);
static void __fastcall tss2reg(struct REGPACK *r);
static void __fastcall reg2tss(struct REGPACK *r);
#define flmerge(rf,tf) (((tf) & ~0xcffL) | ((rf) & 0xcff))
static void __pascal set_controller(int v)
{
/* disable(); */
outportb(0x20, 0x11);
outportb(0x21, v);
outportb(0x21, 4);
outportb(0x21, 1);
/* enable(); */
}
static void init_controllers(void)
{
disable();
movedata(0, 0x08 * 4, 0, 0x78 * 4, 0x08 * 4);
if (vcpi_installed) {
master_pic = vcpi_get_pic();
vcpi_set_pic(0x78);
}
set_controller(0x78);
enable();
}
static void uninit_controllers(void)
{
disable();
if (vcpi_installed)
vcpi_set_pic(master_pic);
set_controller(master_pic);
enable();
}
int exception_handler(void)
{
int i;
#if TOPLINEINFO
char buf[20];
sprintf(buf, "%#08lx", tss_ptr->tss_eip);
for (i = 0; buf[i]; i++)
poke(screen_seg, i * 2 + 80, buf[i] | 0x0600);
#endif
i = tss_ptr->tss_irqn;
/* printf("i=%#02x, a0=%02x\n", i, inportb(0xa0)); */
if ((i >= 0x70) && (i < 0x7f) && (i != 0x75)) {
if (i < 0x78)
intr(i, &r);
else
intr(i - 0x70, &r);
if (i == 0x79) {
r.r_ax = 0x0100;
intr(0x16, &r);
if (!(r.r_flags & 0x40) && (r.r_ax == 0x2e03)) {
_AH = 0;
geninterrupt(0x16);
ctrl_c_flag = 1;
}
}
if (ctrl_c_flag) {
ctrl_c_flag = 0;
return 1;
}
return 0;
}
switch (i) {
case 8:
printf("double fault!\n");
exit(1);
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 9:
case 10:
case 11:
case 12:
case 13:
case 15:
return 1;
case 0x75:
return 1;
case 7:
printf("Fatal! Application attempted to use not-present 80387!\n"
"Floating point opcode at virtual address %#08lx\n", tss_ptr->tss_eip);
return 1;
case 14:
return page_in();
case 0x10:
return i_10();
case 0x11:
case 0x12:
case 0x14:
case 0x16:
case 0x17:
case 0x1a:
return generic_handler();
case 0x21:
return i_21();
case 0x33:
return i_33();
default:
return 1;
}
}
#if DEBUGGER
static char flset[] = "VMRF NT OFDNIETFMIZR AC PE CY";
static char floff[] = " UPID PLNZ PO NC";
static char fluse[] =
{1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1};
void __pascal tssprint(TSS * t)
{
int i;
printf("eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx\n"
"esi=%08lx edi=%08lx ebp=%08lx ",
t->tss_eax, t->tss_ebx, t->tss_ecx, t->tss_edx, t->tss_esi, t->tss_edi, t->tss_ebp);
for (i = 0; i < 18; i++)
if (fluse[i])
if (t->tss_eflags & (1L << (17 - i)))
printf(" %2.2s", flset + i * 2);
else
printf(" %2.2s", floff + i * 2);
printf("\nds=%04x es=%04x fs=%04x gs=%04x ss:esp=%04x:%08lx cs=%04x\n",
t->tss_ds, t->tss_es, t->tss_fs, t->tss_gs, t->tss_ss, t->tss_esp, t->tss_cs);
}
#endif /* DEBUGGER */
static int __pascal retrieve_string(word32 v, char *transfer_buffer, char tchar)
{
int i;
char c;
for (i = 0; i < 4096; i++) {
c = peek8(v);
v++;
transfer_buffer[i] = c;
if (c == tchar)
break;
}
return i + 1; /* number of characters placed in buffer */
}
static int generic_handler(void)
{
tss2reg(&r);
intr(tss_ptr->tss_irqn, &r);
reg2tss(&r);
return 0;
}
static int i_10(void)
{
if ((tss_ptr->tss_eax & 0xFF00) == 0xFF00) {
graphics_mode((unsigned)tss_ptr->tss_eax & 0xff);
in_graphics_mode = (peekb(0x40, 0x49) > 7);
return 0;
}
tss2reg(&r);
intr(0x10, &r);
reg2tss(&r);
tss_ptr->tss_ebp = r.r_es * 16L + r.r_bp + 0xe0000000L;
return 0;
}
static int i_33(void)
{
if (!*((unsigned far *)0x000000CEL))
return 0;
r.r_ax = (word16) tss_ptr->tss_eax;
r.r_bx = (word16) tss_ptr->tss_ebx;
r.r_cx = (word16) tss_ptr->tss_ecx;
r.r_dx = (word16) tss_ptr->tss_edx;
intr(0x33, &r);
tss_ptr->tss_eax = r.r_ax;
tss_ptr->tss_ebx = r.r_bx;
tss_ptr->tss_ecx = r.r_cx;
tss_ptr->tss_edx = r.r_dx;
return 0;
}
static TSS last_tss;
static int i_21(void)
{
word32 v, trans_total, countleft;
int i, c, ah, tchar, trans_count;
char *cp;
memcpy(&last_tss, tss_ptr, sizeof(TSS));
tss2reg(&r);
ah = (int)(tss_ptr->tss_eax >> 8) & 0xff;
switch (ah) {
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 0x0b:
case 0x0e:
case 0x19:
case 0x2a:
case 0x2b:
case 0x2c:
case 0x2d:
case 0x33:
case 0x42:
case 0x45:
case 0x46:
case 0x57:
case 0x68:
case 0x6a:
intr(0x21, &r);
reg2tss(&r);
return 0;
case 0x3e:
#if DEBUGGER
if (r.r_bx <= 2)
return 0;
#endif
if (r.r_bx == 1)
redir_1_mono = redir_1_2 = 0;
if (r.r_bx == 2)
redir_2_mono = redir_2_1 = 0;
intr(0x21, &r);
reg2tss(&r);
return 0;
case 9:
case 0x39:
case 0x3a:
case 0x3b:
case 0x41:
case 0x43:
tchar = (ah == 9) ? '$' : 0;
v = tss_ptr->tss_edx + ARENA;
if (!page_is_valid(v)) {
printf("Segmentation violation in pointer %#08lx\n", tss_ptr->tss_edx);
return 1;
}
retrieve_string(v, transfer_buffer, tchar);
r.r_dx = FP_OFF(transfer_buffer);
r.r_ds = _DS;
intr(0x21, &r);
reg2tss(&r);
return 0;
case 0x3c:
v = tss_ptr->tss_edx + ARENA;
if (!page_is_valid(v)) {
printf("Segmentation violation in pointer %#08lx\n", tss_ptr->tss_edx);
return 1;
}
retrieve_string(v, transfer_buffer, 0);
i = _rtl_creat(transfer_buffer, (int)(tss_ptr->tss_ecx));
if (i == -1) {
tss_ptr->tss_eax = errno;
tss_ptr->tss_eflags |= 1;
} else {
tss_ptr->tss_eax = i;
tss_ptr->tss_eflags &= ~1;
}
return 0;
case 0x3d:
v = tss_ptr->tss_edx + ARENA;
if (!page_is_valid(v)) {
printf("Segmentation violation in pointer %#08lx\n", tss_ptr->tss_edx);
return 1;
}
retrieve_string(v, transfer_buffer, 0);
i = (int)tss_ptr->tss_eax & 0xf0;
if (tss_ptr->tss_eax & O_WRONLY)
i &= 1;
if (tss_ptr->tss_eax & O_RDWR)
i &= 2;
i = _rtl_open(transfer_buffer, i);
if (i == -1) {
tss_ptr->tss_eax = errno;
tss_ptr->tss_eflags |= 1;
} else {
tss_ptr->tss_eax = i;
tss_ptr->tss_eflags &= ~1;
}
return 0;
case 0x1a:
user_dta = tss_ptr->tss_edx;
setdta((char far *)transfer_buffer);
return 0;
case 0x2f:
tss_ptr->tss_ebx = user_dta;
return 0;
case 0x30:
intr(0x21, &r);
reg2tss(&r);
return 0;
case 0x56:
v = tss_ptr->tss_edx + ARENA;
if (!page_is_valid(v)) {
printf("Segmentation violation in pointer %#08lx\n", tss_ptr->tss_edx);
return 1;
}
i = retrieve_string(v, transfer_buffer, 0);
r.r_dx = FP_OFF(transfer_buffer);
r.r_ds = _DS;
v = tss_ptr->tss_edi + ARENA;
retrieve_string(v, transfer_buffer + i, 0);
r.r_di = FP_OFF(transfer_buffer) + i;
r.r_es = _DS;
intr(0x21, &r);
tss_ptr->tss_eax = r.r_ax;
tss_ptr->tss_eflags = flmerge(r.r_flags, tss_ptr->tss_eflags);
return 0;
case 0x3f:
trans_total = 0;
countleft = tss_ptr->tss_ecx;
v = tss_ptr->tss_edx;
if (!page_is_valid(v + ARENA)) {
printf("Segmentation violation in pointer %#08lx\n", tss_ptr->tss_edx);
return 1;
}
while (countleft > 0) {
trans_count = (countleft <= 4096) ? (int)countleft : 4096;
i = read(r.r_bx, transfer_buffer, trans_count);
if (i < 0) {
tss_ptr->tss_eflags |= 1; /* carry */
tss_ptr->tss_eax = _doserrno;
return 0;
}
memput(v + ARENA, transfer_buffer, i);
trans_total += i;
v += i;
countleft -= i;
if (isatty(r.r_bx) && (i < trans_count))
break; /* they're line buffered */
if (!i)
break;
}
tss_ptr->tss_eax = trans_total;
tss_ptr->tss_eflags &= ~1;
return 0;
case 0x40:
trans_total = 0;
countleft = tss_ptr->tss_ecx;
if (!countleft) {
r.r_ax = 0x4000;
r.r_cx = 0;
intr(0x21, &r);
tss_ptr->tss_eax = 0;
tss_ptr->tss_eflags &= ~1;
return 0;
}
v = tss_ptr->tss_edx;
if (!page_is_valid(v + ARENA))
SEGFAULT(v);
r.r_dx = (int)transfer_buffer;
while (countleft > 0) {
trans_count = (countleft <= 4096) ? (int)countleft : 4096;
memget(v + ARENA, transfer_buffer, trans_count);
if ((r.r_bx == 1) && redir_1_mono)
i = mono_write(transfer_buffer, trans_count);
else if ((r.r_bx == 2) && redir_2_mono)
i = mono_write(transfer_buffer, trans_count);
else {
int fd = r.r_bx;
if ((r.r_bx == 2) && redir_2_1)
fd = 1;
else if ((r.r_bx == 1) && redir_1_2)
fd = 2;
i = write(fd, transfer_buffer, trans_count);
if (in_graphics_mode && (fd < 3)) {
word32 far *p = graphics_pt;
for (c = 0; c < 256; c++)
*p++ &= ~PT_P;
}
}
if (i < 0) { /* carry */
tss_ptr->tss_eflags |= 1; /* carry */
tss_ptr->tss_eax = _doserrno;
return 0;
}
trans_total += i;
v += i;
countleft -= i;
if (i < trans_count)
break;
}
tss_ptr->tss_eax = trans_total;
tss_ptr->tss_eflags &= ~1;
return 0;
case 0x44:
return i_21_44();
case 0x4e:
if (!page_is_valid(user_dta + ARENA))
SEGFAULT(user_dta);
v = tss_ptr->tss_edx + ARENA;
if (!page_is_valid(v))
SEGFAULT(v);
retrieve_string(v, transfer_buffer + 43, 0);
r.r_dx = FP_OFF(transfer_buffer + 43);
r.r_ds = _DS;
intr(0x21, &r);
reg2tss(&r);
for (i = 20; i >= 0; i--)
transfer_buffer[i + 28] = transfer_buffer[i + 26];
transfer_buffer[32 + 13] = 0; /* asciiz termination */
memput(user_dta + ARENA, transfer_buffer, 48);
return 0;
case 0x4f:
if (!page_is_valid(user_dta + ARENA))
SEGFAULT(user_dta);
memget(user_dta + ARENA, transfer_buffer, 48);
for (i = 0; i <= 20; i++)
transfer_buffer[i + 26] = transfer_buffer[i + 28];
intr(0x21, &r);
reg2tss(&r);
for (i = 20; i >= 0; i--)
transfer_buffer[i + 28] = transfer_buffer[i + 26];
transfer_buffer[32 + 13] = 0; /* asciiz termination */
memput(user_dta + ARENA, transfer_buffer, 48);
return 0;
case 0x47:
getcurdir((int)(tss_ptr->tss_edx & 0xff), transfer_buffer);
for (cp = transfer_buffer; *cp; cp++) {
if (*cp == '\\')
*cp = '/';
*cp = tolower(*cp);
}
memput(tss_ptr->tss_esi + ARENA, transfer_buffer, strlen(transfer_buffer));
tss_ptr->tss_eax = (unsigned)r.r_ax;
tss_ptr->tss_eflags &= ~1;
return 0;
case 0x4a:
tss_ptr->tss_eax = (tss_ptr->tss_eax & 0xff) ? paging_sbrk(tss_ptr->tss_ebx) : paging_brk(tss_ptr->tss_ebx);
return 0;
case 0x4c:
#if DEBUGGER
printf("Program exited normally, return code %d (%#x)\n",
(int)(tss_ptr->tss_eax & 0xff), (int)(tss_ptr->tss_eax & 0xff));
return 1;
#else
exit((int)tss_ptr->tss_eax & 0xff);
#endif
case 0xff:
return turbo_assist();
default:
return 1;
}
}
struct time32 {
word32 secs;
word32 usecs;
};
struct tz32 {
word32 offset;
word32 dst;
};
struct stat32 {
short st_dev;
short st_ino;
short st_mode;
short st_nlink;
short st_uid;
short st_gid;
short st_rdev;
short st_align_for_word32;
long st_size;
long st_atime;
long st_mtime;
long st_ctime;
long st_blksize;
};
static int dev_count = 1;
static int turbo_assist(void)
{
word32 p1, p2, r;
struct time32 time32;
struct tz32 tz32;
struct stat32 statbuf32;
struct stat statbuf;
int i;
char buf[128];
p1 = tss_ptr->tss_ebx;
p2 = tss_ptr->tss_ecx;
switch (tss_ptr->tss_eax & 0xff) {
case 1:
retrieve_string(p1 + ARENA, buf, 0);
r = creat(buf, S_IREAD | S_IWRITE);
break;
case 2:
retrieve_string(p1 + ARENA, buf, 0);
r = open(buf, (int)p2, S_IREAD | S_IWRITE);
break;
case 3:
memset(&statbuf, 0, sizeof(statbuf));
r = fstat((int)p1, &statbuf);
statbuf32.st_dev = dev_count++;
statbuf32.st_ino = statbuf.st_ino;
statbuf32.st_mode = statbuf.st_mode;
statbuf32.st_nlink = statbuf.st_nlink;
statbuf32.st_uid = statbuf.st_uid;
statbuf32.st_gid = statbuf.st_gid;
statbuf32.st_rdev = statbuf.st_rdev;
statbuf32.st_size = statbuf.st_size;
statbuf32.st_atime = statbuf.st_atime;
statbuf32.st_mtime = statbuf.st_mtime;
statbuf32.st_ctime = statbuf.st_ctime;
statbuf32.st_blksize = 512;
memput(p2 + ARENA, &statbuf32, sizeof(statbuf32));
break;
case 4:
if (p2) {
if (!page_is_valid(p2 + ARENA))
SEGFAULT(p2);
tz32.offset = timezone;
tz32.dst = daylight;
memput(p2 + ARENA, &tz32, sizeof(tz32));
}
if (p1) {
if (!page_is_valid(p1 + ARENA))
SEGFAULT(p1);
time((time_t *) & time32.secs);
_AH = 0x2c;
geninterrupt(0x21);
time32.usecs = _DL * 10000L;
memput(p1 + ARENA, &time32, sizeof(time32));
}
r = 0;
break;
case 5:
if (p2) {
if (!page_is_valid(p2 + ARENA))
SEGFAULT(p2);
memget(p2 + ARENA, &tz32, sizeof(tz32));
timezone = tz32.offset;
daylight = (int)tz32.dst;
}
if (p1) {
if (!page_is_valid(p1 + ARENA))
SEGFAULT(p1);
memget(p1 + ARENA, &time32, sizeof(time32));
stime((time_t *) & time32.secs);
}
r = 0;
break;
case 6:
memset(&statbuf, 0, sizeof(statbuf));
retrieve_string(p1 + ARENA, transfer_buffer, 0);
r = stat(transfer_buffer, &statbuf);
statbuf32.st_dev = dev_count++;
statbuf32.st_ino = statbuf.st_ino;
statbuf32.st_mode = statbuf.st_mode;
statbuf32.st_nlink = statbuf.st_nlink;
statbuf32.st_uid = statbuf.st_uid;
statbuf32.st_gid = statbuf.st_gid;
statbuf32.st_rdev = statbuf.st_rdev;
statbuf32.st_size = statbuf.st_size;
statbuf32.st_atime = statbuf.st_atime;
statbuf32.st_mtime = statbuf.st_mtime;
statbuf32.st_ctime = statbuf.st_ctime;
statbuf32.st_blksize = 512;
memput(p2 + ARENA, &statbuf32, sizeof(statbuf32));
break;
case 7:
retrieve_string(p1 + ARENA, transfer_buffer, 0);
page_out_everything();
uninit_controllers();
sscanf(transfer_buffer, "%s%n", buf, &i);
r = (strpbrk(transfer_buffer, "<>|") == NULL) ? spawnlp(P_WAIT, buf, buf, transfer_buffer + i, 0) : ULONG_MAX;
if (r & 0x80000000L)
r = system(transfer_buffer);
init_controllers();
page_in_everything();
break;
case 8:
r = setmode((int)p1, (int)p2);
break;
default:
return 1;
}
tss_ptr->tss_eflags &= ~1;
if (r == ULONG_MAX) {
tss_ptr->tss_eflags |= 1;
tss_ptr->tss_eax = errno;
return 0;
}
tss_ptr->tss_eax = r;
return 0;
}
static int i_21_44(void)
{
switch (tss_ptr->tss_eax & 0xff) {
case 0x00:
case 0x01:
case 0x06:
case 0x07:
intr(0x21, &r);
tss_ptr->tss_edx = r.r_dx;
tss_ptr->tss_eax = r.r_ax;
tss_ptr->tss_eflags = flmerge(r.r_flags, tss_ptr->tss_eflags);
return 0;
default:
return 1;
}
}
static void __fastcall tss2reg(struct REGPACK *r)
{
r->r_ax = (word16) tss_ptr->tss_eax;
r->r_bx = (word16) tss_ptr->tss_ebx;
r->r_cx = (word16) tss_ptr->tss_ecx;
r->r_dx = (word16) tss_ptr->tss_edx;
r->r_si = (word16) tss_ptr->tss_esi;
r->r_di = (word16) tss_ptr->tss_edi;
r->r_flags = (word16) tss_ptr->tss_eflags;
r->r_ds = r->r_es = _DS;
}
static void __fastcall reg2tss(struct REGPACK *r)
{
tss_ptr->tss_eax = r->r_ax;
tss_ptr->tss_ebx = r->r_bx;
tss_ptr->tss_ecx = r->r_cx;
tss_ptr->tss_edx = r->r_dx;
tss_ptr->tss_esi = r->r_si;
tss_ptr->tss_edi = r->r_di;
tss_ptr->tss_eflags = flmerge(r->r_flags, tss_ptr->tss_eflags);
}