home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / c / djgpp / go32 / control.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-30  |  11.0 KB  |  491 lines

  1. /* This is file CONTROL.C */
  2. /*
  3. ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* History:87,1 */
  16. #include <dos.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <fcntl.h>
  20. #include <sys/stat.h>
  21. #include <string.h>
  22.  
  23. #include "build.h"
  24. #include "types.h"
  25. #include "gdt.h"
  26. #include "idt.h"
  27. #include "tss.h"
  28. #include "valloc.h"
  29. #include "utils.h"
  30. #include "syms.h"
  31. #include "graphics.h"
  32. #include "mono.h"
  33.  
  34. TSS *tss_ptr;
  35. int debug_mode = 0;
  36. int self_contained;
  37. long header_offset = 0;
  38. int use_ansi=0;
  39. int use_mono=0;
  40.  
  41. static int old_video_mode;
  42.  
  43. extern near go32();
  44. extern near go_real_mode();
  45. extern int was_exception;
  46. extern near ivec0(), ivec1(), ivec7(), ivec75();
  47. extern near interrupt_common(), page_fault();
  48. extern near test();
  49.  
  50. extern word32 far *pd;
  51.  
  52. fillgdt(int sel, word32 limit, word32 base, word8 type, int G)
  53. {
  54.   GDT_S *g;
  55.   g = gdt+sel;
  56.   if (G & 2)
  57.     limit = limit >> 12;
  58.   g->lim0 = limit & 0xffff;
  59.   g->lim1 = (limit>>16) & 0x0f;
  60.   g->base0 = base & 0xffff;
  61.   g->base1 = (base>>16) & 0xff;
  62.   g->base2 = (base>>24) & 0xff;
  63.   g->stype = type;
  64.   g->lim1 |= G * 0x40;
  65. }
  66.  
  67. word32 ptr2linear(void far *ptr)
  68. {
  69.   return (word32)FP_SEG(ptr) * 16L + (word32)FP_OFF(ptr);
  70. }
  71.  
  72. setup_tss(TSS *t, int (*eip)())
  73. {
  74.   memset(t, 0, sizeof(TSS));
  75.   t->tss_cs = g_rcode*8;
  76.   t->tss_eip = (long)FP_OFF(eip);
  77.   t->tss_ss = g_rdata*8;
  78.   t->tss_esp = (long)FP_OFF(t->tss_stack);
  79.   t->tss_ds = g_rdata*8;
  80.   t->tss_es = g_rdata*8;
  81.   t->tss_fs = g_rdata*8;
  82.   t->tss_gs = g_rdata*8;
  83.   t->tss_eflags = 0x0200;
  84.   t->tss_iomap = 0xffff; /* no map */
  85. }
  86.  
  87. exit_func()
  88. {
  89.   int i;
  90.   dalloc_uninit();
  91.   uninit_controllers();
  92.   xms_free();
  93.  
  94. #if TOPLINEINFO
  95.   for (i=0; i<80; i++)
  96.     poke(screen_seg, i*2, 0x0720);
  97. #endif
  98. }
  99.  
  100. int ctrl_c_flag = 0;
  101.  
  102. ctrlbrk_func()
  103. {
  104. #if DEBUGGER
  105.   ctrl_c_flag = 1;
  106. #else
  107.   exit(3);
  108. #endif
  109. }
  110.  
  111. usage(char *s)
  112. {
  113.   printf("Usage: %s [program [options . . . ]]\n", s);
  114.   _exit(1);
  115. }
  116.  
  117. int have_80387;
  118. static word32 push32(void *ptr, int len);
  119.  
  120. main(int argc, char **argv, char **envp)
  121. {
  122.   int i, n, set_brk=0, emu_installed=0;
  123.   struct stat stbuf;
  124.   char *cp, *path, *argv0, *emu_fn=0;
  125.   unsigned short header[3];
  126.  
  127.   old_video_mode = peekb(0x40, 0x49);
  128.  
  129.   if (strcmp(argv[1], "!proxy") == 0)
  130.   {
  131.     int oseg, optr, i;
  132.     int far *oargv;
  133.     char far *oargve;
  134.     sscanf(argv[2], "%x", &argc);
  135.     sscanf(argv[3], "%x", &oseg);
  136.     sscanf(argv[4], "%x", &optr);
  137.     oargv = MK_FP(oseg, optr);
  138.     argv = (char **)malloc(sizeof(char *) * (argc+1));
  139.     for (i=0; i<argc+1; i++)
  140.     {
  141.       if (oargv[i] == 0)
  142.       {
  143.         argv[i] = 0;
  144.         break;
  145.       }
  146.       oargve = MK_FP(oseg, oargv[i]);
  147.       for (optr=0; oargve[optr]; optr++);
  148.       argv[i] = (char *)malloc(optr+1);
  149.       for (optr=0; oargve[optr]; optr++)
  150.         argv[i][optr] = oargve[optr];
  151.       argv[i][optr] = 0;
  152.     }
  153.   }
  154.  
  155.   switch (cputype())
  156.   {
  157.     case 1:
  158.       fprintf(stderr, "CPU must be a 386 to run this program.\n");
  159.       exit(1);
  160.     case 2:
  161.       fprintf(stderr, "CPU must be in REAL mode (not V86 mode) to run this program.\n");
  162.       exit(1);
  163.   }
  164.  
  165.   if (peekb(0x40,0x49) == 7)
  166.     screen_seg = 0xb000;
  167.  
  168.   _fmode = O_BINARY;
  169.  
  170.   cp = getenv("GO32");
  171.   path = 0;
  172.   if (cp)
  173.     while (1)
  174.     {
  175.       char sw[100];
  176.       char val[100];
  177.       if (sscanf(cp, "%s%n", sw, &i) < 1)
  178.         break;
  179.       cp += i;
  180.       if (strcmp(sw, "ansi") == 0)
  181.         use_ansi = 1;
  182.       else if (strcmp(sw, "mono") == 0)
  183.         use_mono = 1;
  184.       else
  185.       {
  186.         val[0] = 0;
  187.         sscanf(cp, "%s%n", val, &i);
  188.         cp += i;
  189.         if (val[0] == 0)
  190.           break;
  191.       }
  192.       if (strcmp(sw, "driver") == 0)
  193.       {
  194.         if (path) free(path);
  195.         path = strdup(val);
  196.       }
  197.       else if (strcmp(sw, "tw") == 0)
  198.         gr_def_tw = atoi(val);
  199.       else if (strcmp(sw, "th") == 0)
  200.         gr_def_th = atoi(val);
  201.       else if (strcmp(sw, "gw") == 0)
  202.         gr_def_gw = atoi(val);
  203.       else if (strcmp(sw, "gh") == 0)
  204.         gr_def_gh = atoi(val);
  205.       else if (strcmp(sw, "emu") == 0)
  206.       {
  207.         if (emu_fn) free(emu_fn);
  208.         emu_fn = strdup(val);
  209.       }
  210.     }
  211.   setup_graphics_driver(path);
  212.   if (path) free(path);
  213.   if (use_mono)
  214.   {
  215.     use_ansi = 0;
  216.     screen_seg = 0xb000;
  217.   }
  218.  
  219.   setbuf(stdin, 0);
  220.   atexit((atexit_t)exit_func);
  221.   ctrlbrk(ctrlbrk_func);
  222.   n = (int)ivec1-(int)ivec0;
  223.   for (i=0; i<256; i++)
  224.   {
  225.     idt[i].selector = g_rcode*8;
  226.     idt[i].stype = 0x8e00;
  227.     idt[i].offset0 = FP_OFF((int)ivec0+n*i);
  228.     idt[i].offset1 = 0;
  229.   }
  230.   idt[14].selector = g_ptss*8;
  231.   idt[14].stype = 0x8500;
  232.   idt[14].offset0 = 0;
  233.   idt[14].offset1 = 0;
  234.  
  235.   cp = getenv("387");
  236.   if (cp)
  237.     if (tolower(cp[0]) == 'n')
  238.       have_80387 = 0;
  239.     else if (tolower(cp[0]) == 'y')
  240.       have_80387 = 1;
  241.     else
  242.       have_80387 = detect_80387();
  243.   else
  244.     have_80387 = detect_80387();
  245.   if (have_80387)
  246.   {
  247.     idt[7].offset0 = (int)ivec7;
  248.     idt[7].offset1 = 0;
  249.     idt[0x75].offset0 = (int)ivec75;
  250.     idt[0x75].offset1 = 0;
  251.   }
  252.  
  253.   if (cp && (tolower(cp[0]) == 'q'))
  254.     if (have_80387)
  255.       printf("An 80387 has been detected.\n");
  256.     else
  257.       printf("No 80387 has been detected.\n");
  258.  
  259.   fillgdt(g_zero, 0, 0, 0, 0);
  260.   fillgdt(g_gdt, sizeof(gdt), ptr2linear(gdt), 0x92, 0);
  261.   fillgdt(g_idt, sizeof(idt), ptr2linear(idt), 0x92, 0);
  262.   fillgdt(g_rcode, 0xffff, (word32)_CS*16L, 0x9a, 0);
  263.   fillgdt(g_rdata, 0xffff, (word32)_DS*16L, 0x92, 0);
  264.   fillgdt(g_core, 0xffffffffL, 0, 0x92, 3);
  265.   fillgdt(g_acode, 0xefffffffL, 0x10000000L, 0x9a, 3);
  266.   fillgdt(g_adata, 0xefffffffL, 0x10000000L, 0x92, 3);
  267.   fillgdt(g_ctss, sizeof(TSS), ptr2linear(&c_tss), 0x89, 3);
  268.   fillgdt(g_atss, sizeof(TSS), ptr2linear(&a_tss), 0x89, 3);
  269.   fillgdt(g_ptss, sizeof(TSS), ptr2linear(&p_tss), 0x89, 3);
  270.   fillgdt(g_itss, sizeof(TSS), ptr2linear(&i_tss), 0x89, 3);
  271.   fillgdt(g_rc32, 0xffff, (word32)_CS*16L, 0x9a, 3);
  272.   fillgdt(g_grdr, 0xffff, (word32)gr_paging_segment*16L, 0x9a, 0);
  273.  
  274.   setup_tss(&c_tss, go_real_mode);
  275.   setup_tss(&a_tss, go_real_mode);
  276.   setup_tss(&o_tss, go_real_mode);
  277.   setup_tss(&f_tss, go_real_mode);
  278.   setup_tss(&i_tss, interrupt_common);
  279.   setup_tss(&p_tss, page_fault);
  280.   tss_ptr = &a_tss;
  281.  
  282.   argv0 = argv[0];
  283.   for (i=0; argv0[i]; i++)
  284.   {
  285.     if (argv0[i] == '\\')
  286.       argv0[i] = '/';
  287.     argv0[i] = tolower(argv0[i]);
  288.   }
  289.   if (strcmp(argv[1], "-nobrk") == 0)
  290.   {
  291.     set_brk=1;
  292.     argv++;
  293.     argc--;
  294.   }
  295.  
  296. #if TOPLINEINFO
  297.   for (i=0; i<80; i++)
  298.     poke(screen_seg, i*2, 0x0720);
  299. #endif
  300.  
  301.   self_contained = 0;
  302.   n = open(argv0, O_RDONLY|O_BINARY);
  303.   header[0] = 0;
  304.   read(n, header, sizeof(header));
  305.   if (header[0] == 0x5a4d)
  306.   {
  307.     header_offset = (long)header[1] + (long)header[2]*512L - 512L;
  308.     lseek(n, header_offset, 0);
  309.     header[0] = 0;
  310.     read(n, header, sizeof(header));
  311.     if (header[0] == 0x010b)
  312.       self_contained = 1;
  313.   }
  314.  
  315.   if (self_contained)
  316.   {
  317. #if DEBUGGER
  318.     debug_mode = 1;
  319. #else
  320.     debug_mode = 0;
  321. #endif
  322.     paging_set_file(argv0);
  323.     emu_installed = emu_install(emu_fn);
  324.     set_command_line(argv, envp);
  325. #if DEBUGGER
  326.     syms_init(argv0);
  327. #endif
  328.   }
  329.   else
  330.   {
  331.     header_offset = 0;
  332.     for (cp=argv0; *cp; cp++)
  333.       if (*cp == '.')
  334.         path = cp;
  335.     *path = 0;
  336.     if (stat(argv0, &stbuf)) /* not found */
  337.     {
  338.       fprintf(stderr, "%s.exe Copyright (C) 1991 DJ Delorie\n", argv0);
  339.       debug_mode = 1;
  340.       if (argv[1] == 0)
  341.         usage(argv0);
  342.       paging_set_file(argv[1]);
  343.       emu_installed = emu_install(emu_fn);
  344.       set_command_line(argv+1, envp);
  345. #if DEBUGGER
  346.       syms_init(argv[1]);
  347. #endif
  348.     }
  349.     else /* found */
  350.     {
  351.       debug_mode = 0;
  352.       paging_set_file(argv0);
  353.       emu_installed = emu_install(emu_fn);
  354.       set_command_line(argv, envp);
  355. #if DEBUGGER
  356.       syms_init(argv0);
  357. #endif
  358.     }
  359.   }
  360.  
  361.   if (set_brk)
  362.     paging_brk(0x8fffffffL);
  363.  
  364.   dalloc_init();
  365.   init_controllers();
  366.   if (emu_installed)
  367.   {
  368.     push32(&(a_tss.tss_eip), 4);
  369.     a_tss.tss_eip = 0xb0000020;
  370.   }
  371. #if DEBUGGER
  372.   debugger();
  373.   if (peekb(0x40, 0x49) != old_video_mode)
  374.   {
  375.     _AX = old_video_mode;
  376.     geninterrupt(0x10);
  377.   }
  378.   return 0;
  379. #else
  380.   go_til_stop();
  381.   if (tss_ptr->tss_irqn == 0x79)
  382.     fprintf(stderr, "Ctrl-C Hit!  Stopped at address %lx\n", tss_ptr->tss_eip);
  383.   else
  384.     fprintf(stderr, "Exception %d at eip=%lx\n", tss_ptr->tss_irqn, tss_ptr->tss_eip);
  385.   return 1;
  386. #endif
  387. }
  388.  
  389. #if !DEBUGGER
  390. gdtprint(i)
  391. {
  392.   printf("0x%02x: base=%02x%02x%04x lim=%02x%04x G=%d type=%02x\n",
  393.     i*8, gdt[i].base2, gdt[i].base1, gdt[i].base0,
  394.     gdt[i].lim1&0x0f, gdt[i].lim0, gdt[i].lim1>>6, gdt[i].stype);
  395. }
  396. #endif
  397.  
  398. static word32 push32(void *ptr, int len)
  399. {
  400.   if ((a_tss.tss_esp & ~0xFFF) != ((a_tss.tss_esp-len) & ~0xFFF))
  401.   {
  402.     a_tss.tss_cr2 = a_tss.tss_esp - len + ARENA;
  403.     page_in();
  404.   }
  405.   a_tss.tss_esp -= len;
  406.   a_tss.tss_esp = a_tss.tss_esp & (~3);
  407.   memput(a_tss.tss_esp+ARENA, ptr, len);
  408.   return a_tss.tss_esp;
  409. }
  410.  
  411. static foreach_arg(char **argv, int (*func)())
  412. {
  413.   int i;
  414.   FILE *f;
  415.   char buf[80];
  416.   for (i=0; argv[i]; i++)
  417.   {
  418.     if (argv[i][0] == '@')
  419.     {
  420.       f = fopen(argv[i]+1, "rt");
  421.       while (fscanf(f, "%s", buf) == 1)
  422.       {
  423.         if (strcmp(buf, "\032") != 0)
  424.           func(buf);
  425.       }
  426.       fclose(f);
  427.     }
  428.     else
  429.       func(argv[i]);
  430.   }
  431. }
  432.  
  433. static int num_actual_args;
  434.  
  435. static just_incr()
  436. {
  437.   num_actual_args++;
  438. }
  439.  
  440. static word32 *a;
  441.  
  442. pusharg(char *ar)
  443. {
  444.   a[num_actual_args] = push32(ar, strlen(ar)+1);
  445.   num_actual_args++;
  446. }
  447.  
  448. set_command_line(char **argv, char **envv)
  449. {
  450.   unsigned envc;
  451.   word32 *e, v, argp, envp;
  452.  
  453.   a_tss.tss_cr2 = a_tss.tss_esp + ARENA;
  454.   page_in();
  455.  
  456.   num_actual_args = 0;
  457.   foreach_arg(argv, just_incr);
  458.  
  459.   for (envc=0; envv[envc]; envc++);
  460.   e = (word32 *)malloc((envc+1)*sizeof(word32));
  461.   if (e == 0)
  462.   {
  463.     printf("Fatal! no memory to copy environment\n");
  464.     exit(1);
  465.   }
  466.   for (envc=0; envv[envc]; envc++)
  467.   {
  468.     v = push32(envv[envc], strlen(envv[envc])+1);
  469.     e[envc] = v;
  470.   }
  471.   e[envc] = 0;
  472.  
  473.   a = (word32 *)malloc((num_actual_args+1)*sizeof(word32));
  474.   if (e == 0)
  475.   {
  476.     printf("Fatal! no memory to copy arguments\n");
  477.     exit(1);
  478.   }
  479.   num_actual_args = 0;
  480.   foreach_arg(argv, pusharg);
  481.   a[num_actual_args] = 0;
  482.  
  483.   envp = push32(e, (envc+1)*sizeof(word32));
  484.   argp = push32(a, (num_actual_args+1)*sizeof(word32));
  485.  
  486.   push32(&envp, sizeof(word32));
  487.   push32(&argp, sizeof(word32));
  488.   v = num_actual_args;
  489.   push32(&v, sizeof(word32));
  490. }
  491.