/* 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 */ /* History:87,1 */ #include #include #include #include #include #include #include #include #include "build.h" #include "types.h" #include "gdt.h" #include "idt.h" #include "tss.h" #include "valloc.h" #include "utils.h" #include "syms.h" #include "graphics.h" #include "mono.h" #include "vcpi.h" extern transfer_buffer[]; extern word32 transfer_linear; TSS *tss_ptr; int debug_mode = 0; int self_contained; long header_offset = 0; int use_ansi=0; int use_mono=0; int redir_1_mono=0; int redir_2_mono=0; int redir_2_1=0; int redir_1_2=0; static int old_video_mode; static int globbing=1; int16 ems_handle=0; /* Get EMS Handle */ word16 vcpi_installed = 0; /* VCPI Installed Flag */ extern near go32(); extern near go_real_mode(); extern void vcpi_flush(); /* VCPI Memory All Cleared */ extern int was_exception; extern far ivec0(), ivec1(); extern near ivec7(), ivec75(); extern near interrupt_common(), page_fault(); extern near v74_handler(), v78_handler(), v79_handler(); extern short new_pic; extern word32 far *pd; short _openfd[255] = { 0x6001,0x7002,0x6002,0xa004,0xa002,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff, 0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff }; bump_file_limit() { if (((((int)_osmajor)<<8)|_osminor) < 0x0303) return; _AH = 0x67; _BX = 255; geninterrupt(0x21); } initialize_printer() { _BX=4; _AH=0x44; _AL=0x01; _DX=0xa0; geninterrupt(0x21); setmode(4, O_BINARY); } 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 = limit & 0xffff; g->lim1 = (limit>>16) & 0x0f; g->base0 = base & 0xffff; g->base1 = (base>>16) & 0xff; g->base2 = (base>>24) & 0xff; g->stype = type; g->lim1 |= G * 0x40; } word32 ptr2linear(void far *ptr) { return (word32)FP_SEG(ptr) * 16L + (word32)FP_OFF(ptr); } setup_tss(TSS *t, int (*eip)()) { memset(t, 0, sizeof(TSS)); t->tss_cs = g_rcode*8; t->tss_eip = (long)FP_OFF(eip); t->tss_ss = g_rdata*8; t->tss_esp = (long)FP_OFF(t->tss_stack); t->tss_ds = g_rdata*8; t->tss_es = g_rdata*8; t->tss_fs = g_rdata*8; t->tss_gs = g_rdata*8; t->tss_eflags = 0x0200; t->tss_iomap = 0xffff; /* no map */ } exit_func() { int i; 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 } int ctrl_c_flag = 0; ctrlbrk_func() { #if DEBUGGER ctrl_c_flag = 1; #else exit(3); #endif } usage(char *s) { use_mono = 0; fprintf(stderr, "Usage: %s [program [options . . . ]]\n", s); _exit(1); } int have_80387; int use_xms=0; static word32 push32(void *ptr, int len); setup_idt_task(int which, int tss) { idt[which].selector = tss*8; idt[which].stype = 0x8500; idt[which].offset0 = 0; idt[which].offset1 = 0; } static getlongargs(int *ac, char ***av) { char *_argcs = getenv("_argc"); int _argc, i; char tmp[10]; char **_argv; if (_argcs == 0) return; if (*ac > 1) return; _argc = atoi(_argcs); _argv = (char **)malloc((_argc+1)*sizeof(char*)); for (i = 1; i<_argc; i++) { sprintf(tmp, "_argv%d", i); _argv[i] = getenv(tmp); } _argv[0] = (*av)[0]; _argv[i] = 0; *av = _argv; *ac = _argc; putenv("_argc="); } main(int argc, char **argv, char **envp) { int i, n, set_brk=0, emu_installed=0; struct stat stbuf; char *cp, *path, *argv0, *emu_fn=0; unsigned short header[3]; fprintf(stderr, ""); fflush(stderr); fprintf(stdout, ""); fflush(stdout); bump_file_limit(); if (xms_installed()) use_xms = 1; old_video_mode = peekb(0x40, 0x49); if (strcmp(argv[1], "!proxy") == 0) { 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; itss_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 } #if 0 gdtprint(i) { printf("0x%02x: base=%02x%02x%04x lim=%02x%04x G=%d type=%02x\n", i*8, gdt[i].base2, gdt[i].base1, gdt[i].base0, gdt[i].lim1&0x0f, gdt[i].lim0, gdt[i].lim1>>6, gdt[i].stype); } #endif static word32 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 int fscan_q(FILE *f, char *buf) { char *ibuf = buf; int c, quote=-1, gotsome=0, addquote=0; while ((c = fgetc(f)) != EOF) { if (c == '\\') { char c2 = fgetc(f); if (! strchr("\"'`\\ \t\n\r", c2)) *buf++ = c; *buf++ = c2; addquote = 0; } else if (c == quote) { quote = -1; if (c == '\'') addquote = 1; } else if (isspace(c) && (quote==-1)) { if (gotsome) { if (addquote) *buf++ = '\''; *buf = 0; return 1; } addquote = 0; } else { if ((quote == -1) && ((c == '"') || (c == '\''))) { quote = c; gotsome=1; if ((c == '\'') && (buf == ibuf)) *buf++ = c; } else { *buf++ = c; gotsome=1; } addquote = 0; } } return 0; } static glob(char *buf, int (*func)()) { if (globbing && strpbrk(buf, "*?")) { char *dire, *cp; struct ffblk ff; int done, upcase=0; done = findfirst(buf, &ff, FA_RDONLY|FA_DIREC|FA_ARCH); if (done) func(buf); else { char nbuf[80]; strcpy(nbuf, buf); for (dire=cp=nbuf; *cp; cp++) { if (strchr("/\\:", *cp)) dire = cp + 1; if (isupper(*cp)) upcase = 1; } while (!done) { strcpy(dire, ff.ff_name); if (!upcase) strlwr(dire); func(nbuf); done = findnext(&ff); } } } else func(buf); } static foreach_arg(char **argv, int (*func)()) { int i; char firstc; FILE *f; char buf[80]; for (i=0; argv[i]; i++) { if (argv[i][0] == '@') { f = fopen(argv[i]+1, "rt"); while (fscan_q(f, buf) == 1) { if (!strcmp(buf, "\032")) continue; glob(buf, func); } fclose(f); } else glob(argv[i], func); } } static int num_actual_args; static just_incr() { num_actual_args++; } static word32 *a; pusharg(char *ar) { int s = strlen(ar); if ((ar[0] == '\'') && (ar[s-1] == '\'')) { ar[s-1] = '\0'; ar++; } a[num_actual_args] = push32(ar, s+1); num_actual_args++; } 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 == 0) { fprintf(stderr, "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 == 0) { fprintf(stderr, "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)); }