home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / c / cl5sr386.zip / GO32 / CONTROL.C < prev    next >
C/C++ Source or Header  |  1992-08-26  |  18KB  |  725 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. /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
  16. /* History:87,1 */
  17. #include <dos.h>
  18. #include <dir.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <fcntl.h>
  22. #include <sys/stat.h>
  23. #include <string.h>
  24. #include <ctype.h>
  25. #include <setjmp.h>
  26.  
  27. #include "build.h"
  28. #include "types.h"
  29. #include "gdt.h"
  30. #include "idt.h"
  31. #include "tss.h"
  32. #include "valloc.h"
  33. #include "utils.h"
  34. #include "syms.h"
  35. #include "graphics.h"
  36. #include "mono.h"
  37. #include "vcpi.h"
  38.  
  39. TSS *tss_ptr;
  40. int debug_mode = 0;
  41. int self_contained;
  42. long header_offset = 0;
  43. int use_ansi=0;
  44. int use_mono=0;
  45. int redir_1_mono=0;
  46. int redir_2_mono=0;
  47. int redir_2_1=0;
  48. int redir_1_2=0;
  49.  
  50. static int old_video_mode;
  51. static int globbing=1;
  52.  
  53. int16 ems_handle=0;        /*  Get EMS Handle  */
  54. word16 vcpi_installed = 0;    /*  VCPI Installed Flag  */
  55.  
  56. extern near go32();
  57. extern near go_real_mode();
  58. extern void vcpi_flush();    /*  VCPI Memory All Cleared  */
  59.  
  60. extern int was_exception;
  61. extern near ivec0(), ivec1(), ivec7(), ivec75();
  62. extern near interrupt_common(), page_fault();
  63. extern near v74_handler(), v78_handler(), v79_handler();
  64.  
  65. extern short new_pic;
  66. extern word32 far *pd;
  67.  
  68. short _openfd[255] = {
  69.   0x2001,0x2002,0x2002,0xa004,0xa002,0xffff,0xffff,0xffff,
  70.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  71.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  72.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  73.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  74.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  75.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  76.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  77.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  78.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  79.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  80.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  81.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  82.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  83.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  84.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  85.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  86.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  87.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  88.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  89.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  90.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  91.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  92.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  93.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  94.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  95.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  96.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  97.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  98.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  99.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
  100.   0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff
  101. };
  102.  
  103. bump_file_limit()
  104. {
  105.   if (((((int)_osmajor)<<8)|_osminor) < 0x0303)
  106.     return;
  107.   _AH = 0x67;
  108.   _BX = 255;
  109.   geninterrupt(0x21);
  110. }
  111.  
  112. initialize_printer()
  113. {
  114.   _BX=4;
  115.   _AH=0x44;
  116.   _AL=0x01;
  117.   _DX=0xa0;
  118.   geninterrupt(0x21);
  119.   setmode(4, O_BINARY);
  120. }
  121.  
  122. fillgdt(int sel, word32 limit, word32 base, word8 type, int G)
  123. {
  124.   GDT_S *g;
  125.   g = gdt+sel;
  126.   if (G & 2)
  127.     limit = limit >> 12;
  128.   g->lim0 = limit & 0xffff;
  129.   g->lim1 = (limit>>16) & 0x0f;
  130.   g->base0 = base & 0xffff;
  131.   g->base1 = (base>>16) & 0xff;
  132.   g->base2 = (base>>24) & 0xff;
  133.   g->stype = type;
  134.   g->lim1 |= G * 0x40;
  135. }
  136.  
  137. word32 ptr2linear(void far *ptr)
  138. {
  139.   return (word32)FP_SEG(ptr) * 16L + (word32)FP_OFF(ptr);
  140. }
  141.  
  142. setup_tss(TSS *t, int (*eip)())
  143. {
  144.   memset(t, 0, sizeof(TSS));
  145.   t->tss_cs = g_rcode*8;
  146.   t->tss_eip = (long)FP_OFF(eip);
  147.   t->tss_ss = g_rdata*8;
  148.   t->tss_esp = (long)FP_OFF(t->tss_stack);
  149.   t->tss_ds = g_rdata*8;
  150.   t->tss_es = g_rdata*8;
  151.   t->tss_fs = g_rdata*8;
  152.   t->tss_gs = g_rdata*8;
  153.   t->tss_eflags = 0x0200;
  154.   t->tss_iomap = 0xffff; /* no map */
  155. }
  156.  
  157. exit_func()
  158. {
  159.   int i;
  160.   dalloc_uninit();
  161.   uninit_controllers();
  162.   xms_free();
  163.   if ((ems_handle)&&(ems_handle != -1))
  164.     ems_free(ems_handle);    /*  Deallocated EMS Page    */
  165.   if (vcpi_installed)
  166.     vcpi_flush();        /*  Deallocated VCPI Pages  */
  167.  
  168. #if TOPLINEINFO
  169.   for (i=0; i<80; i++)
  170.     poke(screen_seg, i*2, 0x0720);
  171. #endif
  172. }
  173.  
  174. int ctrl_c_flag = 0;
  175. enum { BREAK = 1, IGNORED = 0, POLLED = 2 } ctrl_c_behavior = BREAK;
  176. int ctrl_c_pending = 0;
  177. jmp_buf * ctrl_c_handler = NULL;
  178.  
  179. ctrlbrk_func()
  180. {
  181. #if DEBUGGER
  182.   ctrl_c_flag = 1;
  183. #else
  184.   switch (ctrl_c_behavior) {
  185.     case BREAK:
  186.       exit(3);
  187.     case IGNORED:
  188.       break;
  189.     case POLLED:
  190.       ctrl_c_pending = 1;
  191.       if (ctrl_c_handler != NULL) longjmp(*ctrl_c_handler, 1);
  192.   }
  193.   return 1;
  194. #endif
  195. }
  196.  
  197. usage(char *s)
  198. {
  199.   printf("Usage: %s [program [options . . . ]]\n", s);
  200.   _exit(1);
  201. }
  202.  
  203. int have_80387;
  204. int use_xms=0;
  205. static word32 push32(void *ptr, int len);
  206.  
  207. setup_idt_task(int which, int tss)
  208. {
  209.   idt[which].selector = tss*8;
  210.   idt[which].stype = 0x8500;
  211.   idt[which].offset0 = 0;
  212.   idt[which].offset1 = 0;
  213. }
  214.  
  215. main(int argc, char **argv, char **envp)
  216. {
  217.   int i, n, set_brk=0, emu_installed=0;
  218.   struct stat stbuf;
  219.   char *cp, *path, *argv0, *emu_fn=0;
  220.   unsigned short header[3];
  221.  
  222.   bump_file_limit();
  223.  
  224.   if (xms_installed())
  225.     use_xms = 1;
  226.   old_video_mode = peekb(0x40, 0x49);
  227.  
  228.   if (strcmp(argv[1], "!proxy") == 0)
  229.   {
  230.     int oseg, optr, i;
  231.     int far *oargv;
  232.     char far *oargve;
  233.     sscanf(argv[2], "%x", &argc);
  234.     sscanf(argv[3], "%x", &oseg);
  235.     sscanf(argv[4], "%x", &optr);
  236.     oargv = MK_FP(oseg, optr);
  237.     argv = (char **)malloc(sizeof(char *) * (argc+1));
  238.     for (i=0; i<argc+1; i++)
  239.     {
  240.       if (oargv[i] == 0)
  241.       {
  242.         argv[i] = 0;
  243.         break;
  244.       }
  245.       oargve = MK_FP(oseg, oargv[i]);
  246.       for (optr=0; oargve[optr]; optr++);
  247.       argv[i] = (char *)malloc(optr+1);
  248.       for (optr=0; oargve[optr]; optr++)
  249.         argv[i][optr] = oargve[optr];
  250.       argv[i][optr] = 0;
  251.     }
  252.   }
  253.  
  254.   ems_handle = emm_present();
  255.   switch (cputype())
  256.   {
  257.     case 1:
  258.       if ((ems_handle)&&(ems_handle != -1))
  259.     ems_free(ems_handle);
  260.       fprintf(stderr, "CPU must be a 386 to run this program.\n");
  261.       exit(1);
  262.     case 2:
  263.       if (ems_handle)
  264.     {
  265.     if (vcpi_installed = vcpi_present())
  266.       break;
  267.     else if (ems_handle != -1)
  268.       ems_free(ems_handle);
  269.     }
  270.       fprintf(stderr, "CPU must be in REAL mode (not V86 mode) to run this program.\n");
  271.       exit(1);
  272.   }
  273.  
  274.   if (peekb(0x40,0x49) == 7)
  275.     screen_seg = 0xb000;
  276.  
  277.   _fmode = O_BINARY;
  278.  
  279.   cp = getenv("GO32");
  280.   path = 0;
  281.   if (cp)
  282.     while (1)
  283.     {
  284.       char sw[100];
  285.       char val[100];
  286.       if (sscanf(cp, "%s%n", sw, &i) < 1)
  287.         break;
  288.       cp += i;
  289.       if (stricmp(sw, "ansi") == 0)
  290.         use_ansi = 1;
  291.       else if (stricmp(sw, "mono") == 0)
  292.         use_mono = 1;
  293.       else if (stricmp(sw, "2r1") == 0)
  294.         redir_2_1 = 1;
  295.       else if (stricmp(sw, "1r2") == 0)
  296.         redir_1_2 = 1;
  297.       else if (stricmp(sw, "2rm") == 0)
  298.         redir_2_mono = 1;
  299.       else if (stricmp(sw, "1rm") == 0)
  300.         redir_1_mono = 1;
  301.       else if (stricmp(sw, "glob") == 0)
  302.         globbing = 1;
  303.       else if (stricmp(sw, "noglob") == 0)
  304.         globbing = 0;
  305.       else
  306.       {
  307.         val[0] = 0;
  308.         sscanf(cp, "%s%n", val, &i);
  309.         cp += i;
  310.         if (val[0] == 0)
  311.           break;
  312.       }
  313.       if (stricmp(sw, "driver") == 0)
  314.       {
  315.         if (path) free(path);
  316.         path = strdup(val);
  317.       }
  318.       else if (stricmp(sw, "tw") == 0)
  319.         gr_def_tw = atoi(val);
  320.       else if (stricmp(sw, "th") == 0)
  321.         gr_def_th = atoi(val);
  322.       else if (stricmp(sw, "gw") == 0)
  323.         gr_def_gw = atoi(val);
  324.       else if (stricmp(sw, "gh") == 0)
  325.         gr_def_gh = atoi(val);
  326. #ifndef NONEWDRIVER
  327.       else if (stricmp(sw, "nc") == 0)
  328.         gr_def_numcolor = atoi(val);
  329. #endif
  330.       else if (stricmp(sw, "emu") == 0)
  331.       {
  332.         if (emu_fn) free(emu_fn);
  333.         emu_fn = strdup(val);
  334.       }
  335.     }
  336. #if ! DEBUGGER
  337. #if ! TOPLINEINFO
  338.   use_mono = 0;
  339. #endif
  340. #endif
  341.   setup_graphics_driver(path);
  342.   if (path) free(path);
  343.   if (use_mono)
  344.   {
  345.     use_ansi = 0;
  346.     screen_seg = 0xb000;
  347.   }
  348.  
  349.   setbuf(stdin, 0);
  350.   atexit((atexit_t)exit_func);
  351.   ctrlbrk(ctrlbrk_func);
  352.   n = (int)ivec1-(int)ivec0;
  353.   for (i=0; i<256; i++)
  354.   {
  355.     idt[i].selector = g_rcode*8;
  356.     idt[i].stype = 0x8e00;
  357.     idt[i].offset0 = FP_OFF((int)ivec0+n*i);
  358.     idt[i].offset1 = 0;
  359.   }
  360.   setup_idt_task(14, g_ptss);
  361.  
  362.   cp = getenv("387");
  363.   if (cp)
  364.     if (tolower(cp[0]) == 'n')
  365.       have_80387 = 0;
  366.     else if (tolower(cp[0]) == 'y')
  367.       have_80387 = 1;
  368.     else
  369.       have_80387 = detect_80387();
  370.   else
  371.     have_80387 = detect_80387();
  372.   if (have_80387)
  373.   {
  374.     idt[7].offset0 = (int)ivec7;
  375.     idt[7].offset1 = 0;
  376.     idt[0x75].offset0 = (int)ivec75;
  377.     idt[0x75].offset1 = 0;
  378.   }
  379.  
  380.   if (cp && (tolower(cp[0]) == 'q'))
  381.     if (have_80387)
  382.       printf("An 80387 has been detected.\n");
  383.     else
  384.       printf("No 80387 has been detected.\n");
  385.  
  386.   fillgdt(g_zero, 0, 0, 0, 0);
  387.   fillgdt(g_gdt, sizeof(gdt), ptr2linear(gdt), 0x92, 0);
  388.   fillgdt(g_idt, sizeof(idt), ptr2linear(idt), 0x92, 0);
  389.   fillgdt(g_rcode, 0xffff, (word32)_CS*16L, 0x9a, 0);
  390.   fillgdt(g_rdata, 0xffff, (word32)_DS*16L, 0x92, 0);
  391.   fillgdt(g_core, 0xffffffffL, 0, 0x92, 3);
  392.   fillgdt(g_acode, 0xefffffffL, 0x10000000L, 0x9a, 3);
  393.   fillgdt(g_adata, 0xefffffffL, 0x10000000L, 0x92, 3);
  394.   fillgdt(g_ctss, sizeof(TSS), ptr2linear(&c_tss), 0x89, 3);
  395.   fillgdt(g_atss, sizeof(TSS), ptr2linear(&a_tss), 0x89, 3);
  396.   fillgdt(g_ptss, sizeof(TSS), ptr2linear(&p_tss), 0x89, 3);
  397.   fillgdt(g_itss, sizeof(TSS), ptr2linear(&i_tss), 0x89, 3);
  398.   fillgdt(g_rc32, 0xffff, (word32)_CS*16L, 0x9a, 3);
  399.   fillgdt(g_grdr, 0xffff, (word32)gr_paging_segment*16L, 0x9a, 0);
  400.   fillgdt(g_v74, sizeof(TSS), ptr2linear(&v74_tss), 0x89, 3);
  401.   fillgdt(g_v78, sizeof(TSS), ptr2linear(&v78_tss), 0x89, 3);
  402.   fillgdt(g_v79, sizeof(TSS), ptr2linear(&v79_tss), 0x89, 3);
  403.  
  404.   setup_tss(&c_tss, go_real_mode);
  405.   setup_tss(&a_tss, go_real_mode);
  406.   setup_tss(&o_tss, go_real_mode);
  407.   setup_tss(&f_tss, go_real_mode);
  408.   setup_tss(&i_tss, interrupt_common);
  409.   setup_tss(&p_tss, page_fault);
  410.   setup_tss(&v74_tss, v74_handler);
  411.   setup_tss(&v78_tss, v78_handler);
  412.   setup_tss(&v79_tss, v79_handler);
  413.   tss_ptr = &a_tss;
  414.  
  415.   argv0 = argv[0];
  416.   for (i=0; argv0[i]; i++)
  417.   {
  418.     if (argv0[i] == '\\')
  419.       argv0[i] = '/';
  420.     argv0[i] = tolower(argv0[i]);
  421.   }
  422.   if (strcmp(argv[1], "-nobrk") == 0)
  423.   { /* for backwards compatibility only - DO NOT USE */
  424.     set_brk=1;
  425.     argv++;
  426.     argc--;
  427.   }
  428.  
  429. #if TOPLINEINFO
  430.   for (i=0; i<80; i++)
  431.     poke(screen_seg, i*2, 0x0720);
  432. #endif
  433.  
  434.   self_contained = 0;
  435.   n = open(argv0, O_RDONLY|O_BINARY);
  436.   header[0] = 0;
  437.   read(n, header, sizeof(header));
  438.   if (header[0] == 0x5a4d)
  439.   {
  440.     header_offset = (long)header[1] + (long)header[2]*512L - 512L;
  441.     lseek(n, header_offset, 0);
  442.     header[0] = 0;
  443.     read(n, header, sizeof(header));
  444.     if (header[0] == 0x010b)
  445.       self_contained = 1;
  446.   }
  447.   close(n);
  448.  
  449.   if (self_contained)
  450.   {
  451. #if DEBUGGER
  452.     debug_mode = 1;
  453. #else
  454.     debug_mode = 0;
  455. #endif
  456.     paging_set_file(argv0);
  457.     emu_installed = emu_install(emu_fn);
  458.     set_command_line(argv, envp);
  459. #if DEBUGGER
  460.     syms_init(argv0);
  461. #endif
  462.   }
  463.   else
  464.   {
  465.     header_offset = 0;
  466.     for (cp=argv0; *cp; cp++)
  467.       if (*cp == '.')
  468.         path = cp;
  469.     *path = 0;
  470.     if (stat(argv0, &stbuf)) /* not found */
  471.     {
  472.       fprintf(stderr, "%s.exe version 1.06 Copyright (C) 1991 DJ Delorie\n",
  473.               argv0);
  474.       debug_mode = 1;
  475.       if (argv[1] == 0)
  476.         usage(argv0);
  477.       paging_set_file(argv[1]);
  478.       emu_installed = emu_install(emu_fn);
  479.       set_command_line(argv+1, envp);
  480. #if DEBUGGER
  481.       syms_init(argv[1]);
  482. #endif
  483.     }
  484.     else /* found */
  485.     {
  486.       debug_mode = 0;
  487.       paging_set_file(argv0);
  488.       emu_installed = emu_install(emu_fn);
  489.       set_command_line(argv, envp);
  490. #if DEBUGGER
  491.       syms_init(argv0);
  492. #endif
  493.     }
  494.   }
  495.  
  496.   if (set_brk)
  497.     paging_brk(0x8fffffffL);
  498.  
  499.   dalloc_init();
  500.   init_controllers();
  501.  
  502.   setup_idt_task(0x74, g_v74);
  503.   setup_idt_task(new_pic, g_v78);
  504.   setup_idt_task(new_pic+1, g_v79);
  505.  
  506.   if (emu_installed)
  507.   {
  508.     push32(&(a_tss.tss_eip), 4);
  509.     a_tss.tss_eip = 0xb0000020;
  510.   }
  511. #if DEBUGGER
  512.   debugger();
  513.   if (peekb(0x40, 0x49) != old_video_mode)
  514.   {
  515.     _AX = old_video_mode;
  516.     geninterrupt(0x10);
  517.   }
  518.   return 0;
  519. #else
  520.   go_til_stop();
  521.   if (tss_ptr->tss_irqn == 0x79)
  522.     fprintf(stderr, "Ctrl-C Hit!  Stopped at address %lx\n", tss_ptr->tss_eip);
  523.   else
  524.     fprintf(stderr, "Exception %d at eip=%lx\n", tss_ptr->tss_irqn, tss_ptr->tss_eip);
  525.   return 1;
  526. #endif
  527. }
  528.  
  529. #if !DEBUGGER
  530. gdtprint(i)
  531. {
  532.   printf("0x%02x: base=%02x%02x%04x lim=%02x%04x G=%d type=%02x\n",
  533.     i*8, gdt[i].base2, gdt[i].base1, gdt[i].base0,
  534.     gdt[i].lim1&0x0f, gdt[i].lim0, gdt[i].lim1>>6, gdt[i].stype);
  535. }
  536. #endif
  537.  
  538. static word32 push32(void *ptr, int len)
  539. {
  540.   if ((a_tss.tss_esp & ~0xFFF) != ((a_tss.tss_esp-len) & ~0xFFF))
  541.   {
  542.     a_tss.tss_cr2 = a_tss.tss_esp - len + ARENA;
  543.     page_in();
  544.   }
  545.   a_tss.tss_esp -= len;
  546.   a_tss.tss_esp = a_tss.tss_esp & (~3);
  547.   memput(a_tss.tss_esp+ARENA, ptr, len);
  548.   return a_tss.tss_esp;
  549. }
  550.  
  551. static int fscan_q(FILE *f, char *buf)
  552. {
  553.   char *ibuf = buf;
  554.   int c, quote=-1, gotsome=0, addquote=0;
  555.   while ((c = fgetc(f)) != EOF)
  556.   {
  557.     if (c == '\\')
  558.     {
  559.       char c2 = fgetc(f);
  560.       if (! strchr("\"'`\\ \t\n\r", c2))
  561.         *buf++ = c;
  562.       *buf++ = c2;
  563.       addquote = 0;
  564.     }
  565.     else if (c == quote)
  566.     {
  567.       quote = -1;
  568.       if (c == '\'')
  569.         addquote = 1;
  570.     }
  571.     else if (isspace(c) && (quote==-1))
  572.     {
  573.       if (gotsome)
  574.       {
  575.         if (addquote)
  576.           *buf++ = '\'';
  577.         *buf = 0;
  578.         return 1;
  579.       }
  580.       addquote = 0;
  581.     }
  582.     else
  583.     {
  584.       if ((quote == -1) && ((c == '"') || (c == '\'')))
  585.       {
  586.         quote = c;
  587.         gotsome=1;
  588.         if ((c == '\'') && (buf == ibuf))
  589.           *buf++ = c;
  590.       }
  591.       else
  592.       {
  593.         *buf++ = c;
  594.         gotsome=1;
  595.       }
  596.       addquote = 0;
  597.     }
  598.   }
  599.   return 0;
  600. }
  601.  
  602. static glob(char *buf, int (*func)())
  603. {
  604.   if (globbing && strpbrk(buf, "*?"))
  605.   {
  606.     char *dire, *cp;
  607.     struct ffblk ff;
  608.     int done, upcase=0;
  609.     done = findfirst(buf, &ff, FA_RDONLY|FA_DIREC|FA_ARCH);
  610.     if (done)
  611.       func(buf);
  612.     else
  613.     {
  614.       char nbuf[80];
  615.       strcpy(nbuf, buf);
  616.       for (dire=cp=nbuf; *cp; cp++)
  617.       {
  618.         if (strchr("/\\:", *cp))
  619.           dire = cp + 1;
  620.         if (isupper(*cp))
  621.           upcase = 1;
  622.       }
  623.       while (!done)
  624.       {
  625.         strcpy(dire, ff.ff_name);
  626.         if (!upcase)
  627.           strlwr(dire);
  628.         func(nbuf);
  629.         done = findnext(&ff);
  630.       }
  631.     }
  632.   }
  633.   else
  634.     func(buf);
  635. }
  636.  
  637. static foreach_arg(char **argv, int (*func)())
  638. {
  639.   int i;
  640.   char firstc;
  641.   FILE *f;
  642.   char buf[80];
  643.   for (i=0; argv[i]; i++)
  644.   {
  645.     if (argv[i][0] == '@')
  646.     {
  647.       f = fopen(argv[i]+1, "rt");
  648.       while (fscan_q(f, buf) == 1)
  649.       {
  650.         if (!strcmp(buf, "\032"))
  651.           continue;
  652.         glob(buf, func);
  653.       }
  654.       fclose(f);
  655.     }
  656.     else
  657.       glob(argv[i], func);
  658.   }
  659. }
  660.  
  661. static int num_actual_args;
  662.  
  663. static just_incr()
  664. {
  665.   num_actual_args++;
  666. }
  667.  
  668. static word32 *a;
  669.  
  670. pusharg(char *ar)
  671. {
  672.   int s = strlen(ar);
  673.   if ((ar[0] == '\'') && (ar[s-1] == '\''))
  674.   {
  675.     ar[s-1] = '\0';
  676.     ar++;
  677.   }
  678.   a[num_actual_args] = push32(ar, s+1);
  679.   num_actual_args++;
  680. }
  681.  
  682. set_command_line(char **argv, char **envv)
  683. {
  684.   unsigned envc;
  685.   word32 *e, v, argp, envp;
  686.  
  687.   a_tss.tss_cr2 = a_tss.tss_esp + ARENA;
  688.   page_in();
  689.  
  690.   num_actual_args = 0;
  691.   foreach_arg(argv, just_incr);
  692.  
  693.   for (envc=0; envv[envc]; envc++);
  694.   e = (word32 *)malloc((envc+1)*sizeof(word32));
  695.   if (e == 0)
  696.   {
  697.     printf("Fatal! no memory to copy environment\n");
  698.     exit(1);
  699.   }
  700.   for (envc=0; envv[envc]; envc++)
  701.   {
  702.     v = push32(envv[envc], strlen(envv[envc])+1);
  703.     e[envc] = v;
  704.   }
  705.   e[envc] = 0;
  706.  
  707.   a = (word32 *)malloc((num_actual_args+1)*sizeof(word32));
  708.   if (a == 0)
  709.   {
  710.     printf("Fatal! no memory to copy arguments\n");
  711.     exit(1);
  712.   }
  713.   num_actual_args = 0;
  714.   foreach_arg(argv, pusharg);
  715.   a[num_actual_args] = 0;
  716.  
  717.   envp = push32(e, (envc+1)*sizeof(word32));
  718.   argp = push32(a, (num_actual_args+1)*sizeof(word32));
  719.  
  720.   push32(&envp, sizeof(word32));
  721.   push32(&argp, sizeof(word32));
  722.   v = num_actual_args;
  723.   push32(&v, sizeof(word32));
  724. }
  725.