home *** CD-ROM | disk | FTP | other *** search
/ Internet MPEG Audio Archive / IMAA.mdf / util / dos / l3v100n / rsx / source / sysemx.c < prev    next >
C/C++ Source or Header  |  1994-01-19  |  21KB  |  929 lines

  1. /* This file is SYSEMX.C
  2. **
  3. ** contains :
  4. **
  5. **    - int21 32bit handler (called from adosx32.asm)
  6. **    - int21 emx syscall handler
  7. **
  8. ** Copyright (c) Rainer Schnitker 92,93
  9. */
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <dos.h>
  14. #include <string.h>
  15. #include <malloc.h>
  16. #include <io.h>
  17. #include <time.h>
  18. #include <bios.h>
  19. #include <fcntl.h>
  20. #include <sys/timeb.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #ifdef __TURBOC__
  24. #define SH_DENYWR O_DENYWRITE            /* for Borland compiler */
  25. #else
  26. #include <share.h>
  27. #endif
  28. #include "DPMI.H"
  29. #include "DPMIDOS.H"
  30. #include "PROCESS.H"
  31. #include "SIGNALS.H"
  32. #include "GNUAOUT.H"
  33. #include "START32.H"
  34. #include "CDOSX32.H"
  35. #include "COPY32.H"
  36. #include "EXCEP32.H"
  37. #include "RSX.H"
  38. #include "PTRACE.H"
  39. #include "TERMIO.H"
  40. #include "DOSERRNO.H"
  41.  
  42. static DWORD can_run_emx = 0x302e3868;        /* ascii = 0.8h */
  43.  
  44. static int time_reached(unsigned long time)
  45. {
  46.     if (time <= time_tic)
  47.     return 1;
  48.     else
  49.     return 0;
  50. }
  51.  
  52. static void set_ecx_error(int err)
  53. {
  54.     EAX = -1L;
  55.     if (npz->p_flags & PF_DJGPP_FILE)
  56.     err = errno_djgpp(err);
  57.     ECX = (long) err;
  58. }
  59.  
  60. static void set_no_error(void)
  61. {
  62.     EAX = ECX = 0L;
  63. }
  64.  
  65. static void set_eax_return(DWORD reg_eax)
  66. {
  67.     EAX = reg_eax;
  68.     ECX = 0L;
  69. }
  70.  
  71. /* oldbrk_eax sbrk(inc_edx) ; err:eax=-1 */
  72. static int sys_emx00_sbrk(void)
  73. {
  74.     EAX = getmem(EDX, npz);
  75.     return CARRY_NON;
  76. }
  77.  
  78. /* eax=0 brk(newbrk_edx) ; err:eax=-1 */
  79. static int sys_emx01_brk(void)
  80. {
  81.     if (EDX <= npz->brk_value)
  82.     EAX = -1L;
  83.     else if ((EAX = getmem(EDX - npz->brk_value, npz)) != -1L)
  84.     EAX = 0L;
  85.     return CARRY_NON;
  86. }
  87.  
  88. /* maxbrk_eax ulimit(cmd_ecx,newlimit_edx) errno:ecx */
  89. static int sys_emx02_ulimit(void)
  90. {
  91.     if (ECX == 3L) {
  92.     FREEMEMINFO fm;
  93.     GetFreeMemInfo(&fm);
  94.     set_eax_return(fm.LargestFree + npz->brk_value);
  95.     } else
  96.     set_ecx_error(EMX_EINVAL);
  97.     return CARRY_NON;
  98. }
  99.  
  100. /* emx special: void vmstat() */
  101. static int sys_emx03_vmstat(void)
  102. {
  103.     return CARRY_NON;
  104. }
  105.  
  106. /* eax=filepermmask umask(edx) ; err:- */
  107. static int sys_emx04_umask(void)
  108. {
  109.     EAX = EDX;
  110.     return CARRY_NON;
  111. }
  112.  
  113. /* eax getpid(void) err:- */
  114. static int sys_emx05_getpid(void)
  115. {
  116.     EAX = (DWORD) npz->pid;
  117.     return CARRY_NON;
  118. }
  119.  
  120. /*
  121. ** eax = spawnve(proc_env *edx) err:carry errno:eax
  122. */
  123. static int sys_emx06_spawn(void)
  124. {
  125.     int i, ret;
  126.     PROCESS_ENV pe;
  127.     static char filename[256];
  128.     char **argp = NULL, **envp = NULL;
  129.     char *envmem = NULL, *argmem = NULL;
  130.  
  131.     /* get process data, check mode */
  132.     cpy32_16(DS, EDX, &pe, (DWORD) sizeof(PROCESS_ENV));
  133.     pe.mode &= 0xff;
  134.     if (pe.mode == P_SESSION || pe.mode == P_DETACH) {
  135.     EAX = EMX_EINVAL;
  136.     return CARRY_ON;
  137.     }
  138.     /* get args and env from caller */
  139.     if ((argp = (char **) malloc((pe.arg_count + 1) * sizeof(char *))) == NULL
  140.     || (envp = (char **) malloc((pe.env_count + 1) * sizeof(char *))) == NULL
  141.     || (argmem = (char *) malloc((pe.arg_size + 1) & ~1)) == NULL
  142.     || (envmem = (char *) malloc((pe.env_size + 1) & ~1)) == NULL
  143.     ) {
  144.     printf("argmem,envmem to large a:%d e:%d\n", pe.arg_size, pe.env_size);
  145.     if (argp != NULL)
  146.         free(argp);
  147.     if (envp != NULL)
  148.         free(envp);
  149.     if (argmem != NULL)
  150.         free(argmem);
  151.     if (envmem != NULL)
  152.         free(envmem);
  153.     EAX = EMX_E2BIG;
  154.     return CARRY_ON;
  155.     }
  156.     /* get args from user ds, built arg-vector */
  157.     cpy32_16(DS, pe.arg_off, argmem, (DWORD) pe.arg_size);
  158.     for (i = 0; i < (int) pe.arg_count; i++) {
  159.     argmem++;        /* skip flag */
  160.     argp[i] = argmem;
  161.     argmem += (strlen(argp[i]) + 1);
  162.     }
  163.     argp[i] = NULL;
  164.  
  165.     /* get env from user ds, built env-vector */
  166.     cpy32_16(DS, pe.env_off, envmem, (DWORD) pe.env_size);
  167.     for (i = 0; i < (int) pe.env_count; i++) {
  168.     envp[i] = envmem;
  169.     envmem += (strlen(envp[i]) + 1);
  170.     }
  171.     envp[i] = NULL;
  172.  
  173.     /* get filename */
  174.     strcpy32_16(DS, pe.fname_off, filename);
  175.  
  176.     /* load a.out prg */
  177.     ret = exec32(pe.mode, filename, pe.arg_count, argp, pe.env_count, envp);
  178.  
  179.     /* if error, try a real-mode prg */
  180.     if (ret == EMX_ENOEXEC && pe.mode == P_WAIT)
  181.     ret = realmode_prg(filename, argp, envp);
  182.  
  183.     free(argmem);
  184.     free(envmem);
  185.     free(argp);
  186.     free(envp);
  187.  
  188.     /* check error and return */
  189.     if (ret) {
  190.     EAX = (DWORD) ret;
  191.     return CARRY_ON;
  192.     } else
  193.     return CARRY_OFF;
  194. }
  195.  
  196. static int sys_emx07_unused(void)
  197. {
  198.     return CARRY_NON;
  199. }
  200.  
  201. /* eax ptrace(ebx,edi,edx,ecx) err:ecx!=0 eax=-1 */
  202. static int sys_emx08_ptrace(void)
  203. {
  204.     int ret;
  205.     DWORD data;
  206.     WORD pid_now = npz->pid;
  207.     if ((ret = do_ptrace(BX, DI, EDX, ECX, &data)) != 0)
  208.     set_ecx_error(ret);
  209.     else if (pid_now == npz->pid)    /* save if same process */
  210.     set_eax_return(data);
  211.     return CARRY_NON;
  212. }
  213.  
  214. /* eax=child_id wait(status_edx) ; errno:ecx */
  215. static int sys_emx09_wait(void)
  216. {
  217.     int ret;
  218.     WORD status;
  219.     if ((ret = sys_wait(&status)) != -1) {
  220.     EDX = (DWORD) status;
  221.     set_eax_return((DWORD) (unsigned) ret);
  222.     } else
  223.     set_ecx_error(EMX_ESRCH);
  224.     return CARRY_NON;
  225. }
  226.  
  227. /* get emx-version ; err:- */
  228. static int sys_emx0a_version(void)
  229. {
  230.     EAX = can_run_emx;
  231.     if (dpmi10)
  232.     EBX = 1L << 8;        /* dpmi 0.9 bit */
  233.     else
  234.     EBX = 1L << 7;        /* dpmi 1.0 bit */
  235.     ECX = 0L;            /* emx revision */
  236.     EDX = 0L;
  237.     return CARRY_NON;
  238. }
  239.  
  240. /* eax_pages memavail(void) ; err:- */
  241. static int sys_emx0b_memavail(void)
  242. {
  243.     FREEMEMINFO fm;
  244.  
  245.     GetFreeMemInfo(&fm);
  246.     EAX = fm.MaxUnlockedPages;
  247.     return CARRY_NON;
  248. }
  249.  
  250. /* (*prevh) signal(signo_ecx,address_edx) err:eax=-1 */
  251. static int sys_emx0c_signal(void)
  252. {
  253.     if (ECX >= MAX_SIGNALS || ECX == SIGKILL) {
  254.     EAX = SIG_ERR;
  255.     return CARRY_NON;
  256.     }
  257.     EAX = npz->sigs[CX];    /* return prev handler */
  258.  
  259.     if (EDX == SIG_DFL || EDX == SIG_IGN)
  260.     npz->sigs[CX] = EDX;
  261.     else if (EDX == SIG_ACK)
  262.     npz->sig_ack &= ~(1L << CX);
  263.     else if (verify_illegal(npz, EDX, 4))    /* user handler */
  264.     EAX = SIG_ERR;
  265.     else
  266.     npz->sigs[CX] = EDX;
  267.     return CARRY_NON;
  268. }
  269.  
  270. /* eax=0 kill(id_edx,signo_ecx) errno:ecx eax=-1 */
  271. static int sys_emx0d_kill(void)
  272. {
  273.     NEWPROCESS *p;
  274.     if (!(p = find_process(DX))) {
  275.     set_ecx_error(EMX_ESRCH);
  276.     return CARRY_NON;
  277.     } else if (send_signal(p, CX)) {
  278.     set_ecx_error(EMX_EINVAL);
  279.     return CARRY_NON;
  280.     } else
  281.     set_no_error();
  282.     /* to simulate multitasking, we switch to child */
  283.     if (p->pptr->pid == npz->pid) {
  284.     npz->p_status = PS_SYS_KILL;
  285.     switch_to_process(p);
  286.     npz->p_status = PS_RUN;
  287.     }
  288.     return CARRY_NON;
  289. }
  290.  
  291. /* eax raise(ecx) errno:ecx eax=-1 */
  292. static int sys_emx0e_raise(void)
  293. {
  294.     if (send_signal(npz, CX))
  295.     set_ecx_error(EMX_EINVAL);
  296.     return CARRY_NON;
  297. }
  298.  
  299. /* oldflags uflags(mask=ecx,new=edx) */
  300. static int sys_emx0f_uflags(void)
  301. {
  302.     return CARRY_NON;
  303. }
  304.  
  305. /* void unwind(void) err:no */
  306. static int sys_emx10_unwind(void)
  307. {
  308.     return CARRY_NON;
  309. }
  310.  
  311. /* core(handle_ebx) err:carry errno */
  312. static int sys_emx11_core(void)
  313. {
  314.     EAX = EMX_EINVAL;
  315.     return CARRY_ON;
  316. }
  317.  
  318. /* portaccess(ecx,edx) ecx=first edx=last, err:cy errno:eax */
  319. static int sys_emx12_portaccess(void)
  320. {
  321.     /* dpmi-server must allow this */
  322.     ECX = 0L;            /* first port *
  323.     EDX = 0x3ffL;        /* last port */
  324.     EAX = 0L;
  325.     return CARRY_OFF;
  326. }
  327.  
  328. /* eax memaccess(ebx,ecx,edx) err:carry errno:eax */
  329. /* under DPMI it's better to used a different segment */
  330. /* memaccess destroy protection -> limit 0xffffffff */
  331. /* must use wrap-around to access memory */
  332. static int sys_emx13_memaccess(void)
  333. {
  334.     if (opt_memaccess && ECX <= 0xFFFFFL) {
  335.     EAX = EBX - npz->memaddress;
  336.     return CARRY_OFF;
  337.     } else {
  338.     EAX = EMX_EINVAL;
  339.     return CARRY_ON;
  340.     }
  341. }
  342.  
  343.  
  344. /*
  345. ** eax = ioctl2(ebx,ecx,edx) errno:ecx eax=-1
  346. */
  347. static int sys_emx14_ioctl(void)
  348. {
  349.     int i, ret;
  350.     long temp;
  351.  
  352.     if ((ECX >= TCGETA && ECX <= TCFLSH) || ECX == FIONREAD) {
  353.     if (EBX == 0) {
  354.         if (!(ret = kbd_ioctl(CX, EDX)))
  355.         set_no_error();
  356.         else
  357.         set_ecx_error(ret);
  358.     } else
  359.         set_ecx_error(EMX_EBADF);
  360.     } else if (ECX == FGETHTYPE) {
  361.     tr.eax = 0x4400;
  362.     tr.ebx = EBX;
  363.     if (realdos())
  364.         set_ecx_error(EMX_EBADF);
  365.     else {
  366.         i = (WORD) tr.edx;
  367.         if (!(i & 128))
  368.         temp = HT_FILE;
  369.         else if (i & 3)
  370.         temp = HT_DEV_CON;
  371.         else if (i & 4)
  372.         temp = HT_DEV_NUL;
  373.         else if (i & 8)
  374.         temp = HT_DEV_CLK;
  375.         else
  376.         temp = HT_DEV_OTHER;
  377.  
  378.         set_no_error();
  379.         store32(DS, EDX, temp);
  380.     }
  381.     } else
  382.     set_ecx_error(EMX_EINVAL);
  383.  
  384.     return CARRY_NON;
  385. }
  386.  
  387. /* eax=sec alarm(sec_edx) err:no */
  388. static int sys_emx15_alarm(void)
  389. {
  390.     if (time_tic < npz->time_alarm)    /* there seconds left */
  391.     EAX = (npz->time_alarm - time_tic) * 10 / 182;
  392.     else
  393.     EAX = 0;
  394.  
  395.     if (EDX == 0)        /* clear alarm */
  396.     npz->time_alarm = 0;
  397.     else            /* set alarm */
  398.     npz->time_alarm = time_tic + EDX * 182 / 10;
  399.     return CARRY_NON;
  400. }
  401.  
  402. /* no syscall; internal */
  403. static int sys_emx16_internal(void)
  404. {
  405.     return CARRY_NON;
  406. }
  407.  
  408. /* eax=0 sleep(edx) err:no */
  409. static int sys_emx17_sleep(void)
  410. {
  411.     unsigned long timel;
  412.  
  413.     timel = time_tic + EDX * 182 / 10;
  414.     for (;;)
  415.     if (time_reached(timel))
  416.         break;
  417.     EAX = 0;
  418.     return CARRY_NON;
  419. }
  420.  
  421. /*
  422. ** chsize(handle_ebx,lenght_edx) err:carry eax=errno
  423. */
  424. static int sys_emx18_chsize(void)
  425. {
  426.     tr.eax = 0x4200L;
  427.     tr.ebx = EBX;
  428.     tr.ecx = EDX >> 16;
  429.     tr.edx = EDX & 0xFFFF;
  430.     tr.flags = FLAGS & ~1;
  431.     if (realdos()) {
  432.     EAX = (DWORD) doserror_to_errno((WORD) tr.eax);
  433.     return CARRY_ON;
  434.     }
  435.     tr.eax = 0x4000L;
  436.     tr.ebx = EBX;
  437.     tr.ecx = 0;
  438.     tr.edx = (DWORD) (WORD) iobuf;
  439.     tr.flags = FLAGS & ~1;
  440.     if (realdos()) {
  441.     EAX = (DWORD) doserror_to_errno((WORD) tr.eax);
  442.     return CARRY_ON;
  443.     }
  444.     EAX = 0;
  445.     return CARRY_OFF;
  446. }
  447.  
  448. /* eax fcntl(handle ebx,req ecx,arg edx) errno:ecx */
  449. static int sys_emx19_fcntl(void)
  450. {
  451.     if (ECX != F_SETFL && (EDX & ~(FCNTL_NDELAY | FCNTL_APPEND)) == 0)
  452.     set_ecx_error(EMX_EINVAL);
  453.     else if (EBX == 0) {
  454.     set_fcntl_flag(DX);
  455.     set_no_error();
  456.     } else
  457.     set_ecx_error(EMX_EBADF);
  458.     return CARRY_NON;
  459. }
  460.  
  461. /* eax pipe(edx,ecx) errno:ecx*/
  462. static int sys_emx1a_pipe(void)
  463. {
  464.     set_ecx_error(EMX_EMSDOS);
  465.     return CARRY_NON;
  466. }
  467.  
  468. /* eax fsync(ebx) errno:ecx */
  469. static int sys_emx1b_fsync(void)
  470. {
  471.     set_ecx_error(EMX_EMSDOS);
  472.     return CARRY_NON;
  473. }
  474.  
  475. /* eax fork(void) errno:ecx */
  476. static int sys_emx1c_fork(void)
  477. {
  478.     int ret;
  479.     if ((ret = sys_fork()) != 0)
  480.     set_ecx_error(ret);
  481.     else {
  482.     set_eax_return((DWORD) npz->cptr->pid);
  483.     npz->p_status = PS_SYS_FORK;
  484.     switch_to_process(npz->cptr);
  485.     npz->p_status = PS_RUN;
  486.     set_no_error();
  487.     }
  488.     return CARRY_NON;
  489. }
  490.  
  491. /* void scrsize(EDX) */
  492. static int sys_emx1d_scrsize(void)
  493. {
  494.     store32(DS, EDX + 0, (*(unsigned short far *) (0x0040004a)));
  495.     store32(DS, EDX + 4, (*(unsigned char far *) (0x00400084)) + 1);
  496.     return CARRY_NON;
  497. }
  498.  
  499. /* void select(edx) errno:ecx */
  500. static int sys_emx1e_select(void)
  501. {
  502.     set_ecx_error(EMX_EMSDOS);
  503.     return CARRY_NON;
  504. }
  505.  
  506. /* eax syserrno(void) */
  507. static int sys_emx1f_syserrno(void)
  508. {
  509.     EAX = doserror_to_errno(_doserrno);
  510.     return CARRY_NON;
  511. }
  512.  
  513. /*
  514. ** eax stat(name_edx,struc_edi) errno:ecx
  515. */
  516. static int sys_emx20_stat(void)
  517. {
  518.     struct stat st;
  519.     long stat32[13];
  520.  
  521.     strcpy32_16(DS, EDX, iobuf);
  522.     if (!stat(iobuf, &st)) {
  523.     stat32[0] = (long) st.st_dev;
  524.     stat32[1] = (long) st.st_ino;
  525.     stat32[2] = (long) st.st_mode;
  526.     stat32[3] = 1;        /* st_nlink */
  527.     stat32[4] = 0;        /* st_uid */
  528.     stat32[5] = 0;        /* st_gid */
  529.     stat32[6] = 0;        /* st_rdev */
  530.     stat32[7] = st.st_size;
  531.     stat32[8] = st.st_atime;
  532.     stat32[9] = st.st_mtime;
  533.     stat32[10] = st.st_ctime;
  534.     stat32[11] = 0;        /* attribut file _A_NORMAL */
  535.     stat32[12] = 0;
  536.     cpy16_32(DS, EDI, stat32, 13 * sizeof(DWORD));
  537.     set_no_error();
  538.     } else
  539.     set_ecx_error(doserror_to_errno(_doserrno));
  540.     return CARRY_NON;
  541. }
  542.  
  543. /*
  544. ** eax fstat(ebx, edi) errno:ecx
  545. */
  546. static int sys_emx21_fstat(void)
  547. {
  548.     struct stat st;
  549.     long stat32[13];
  550.  
  551.     if (!fstat(BX, &st)) {
  552.     stat32[0] = (long) st.st_dev;
  553.     stat32[1] = (long) st.st_ino;
  554.     stat32[2] = (long) st.st_mode;
  555.     stat32[3] = 1;        /* st_nlink */
  556.     stat32[4] = 0;        /* st_uid */
  557.     stat32[5] = 0;        /* st_gid */
  558.     stat32[6] = 0;        /* st_rdev */
  559.     stat32[7] = st.st_size;
  560.     stat32[8] = st.st_atime;
  561.     stat32[9] = st.st_mtime;
  562.     stat32[10] = st.st_ctime;
  563.     stat32[11] = 0; /* _A_NORMAL  attribut file */ ;
  564.     stat32[12] = 0;
  565.     cpy16_32(DS, EDI, stat32, 13 * 4);
  566.     set_no_error();
  567.     } else
  568.     set_ecx_error(doserror_to_errno(_doserrno));
  569.     return CARRY_NON;
  570. }
  571.  
  572. static int sys_emx22_unused(void)
  573. {
  574.     return CARRY_NON;
  575. }
  576.  
  577. /* filesys(edx,edi,ecx) errno:ecx */
  578. static int sys_emx23_filesys(void)
  579. {
  580.     strcpy32_16(DS, EDI, (char *) "FAT");
  581.     set_no_error();
  582.     return CARRY_NON;
  583. }
  584.  
  585. /* eax utimes(name_edx,struct tval esi) errno:ecx */
  586. /* set access and modif time of file  */
  587. static int sys_emx24_utimes(void)
  588. {
  589.     int handle;
  590.     struct tm *tm;
  591.     unsigned int dostime, dosdate;
  592.     long utimes[2];
  593.  
  594.     strcpy32_16(DS, EDX, iobuf);
  595.     cpy32_16(DS, ESI, utimes, sizeof(utimes));
  596.  
  597.     handle = sopen(iobuf, O_RDONLY | O_BINARY, SH_DENYWR, S_IREAD | S_IWRITE);
  598.     if (handle == -1) {
  599.     set_ecx_error(doserror_to_errno(_doserrno));
  600.     return CARRY_NON;
  601.     }
  602.     tm = localtime(&utimes[0]);
  603.     dosdate = tm->tm_mday + ((tm->tm_mon + 1) << 5) +
  604.     ((tm->tm_year - 80) << 9);
  605.     dostime = tm->tm_sec / 2 + (tm->tm_min << 5) +
  606.     (tm->tm_hour << 11);
  607.  
  608.     (WORD)tr.eax = 0x5701;
  609.     (WORD)tr.ebx = handle;
  610.     (WORD)tr.ecx = dostime;
  611.     (WORD)tr.edx = dosdate;
  612.     if (realdos())
  613.     set_ecx_error(doserror_to_errno((WORD)tr.eax));
  614.     else
  615.     set_eax_return(0);
  616.     close(handle);
  617.     return CARRY_NON;
  618. }
  619.  
  620. /* eax ftruncate(ebx,edx) errno:ecx */
  621. static int sys_emx25_ftruncate(void)
  622. {
  623.     long temp;
  624.     if ((temp = filelength(BX)) == -1)
  625.     temp = 0;        /* bug? -1: if just opened */
  626.     if (temp > (long) EDX) {
  627.     if (chsize(BX, EDX))
  628.         set_ecx_error(doserror_to_errno(_doserrno));
  629.     else
  630.         set_no_error();
  631.     } else
  632.     set_no_error();
  633.     return CARRY_NON;
  634. }
  635.  
  636. /* eax clock(void) err:no */
  637. static int sys_emx26_clock(void)
  638. {
  639.     /* clk_tck = 100 ; timer 18.2 pre sec */
  640.     EAX = (time_tic - npz->time_tic) * 500 / 91;
  641.     EDX = 0;
  642.     return CARRY_NON;
  643. }
  644.  
  645. /* void ftime(edx) err:no */
  646. static int sys_emx27_ftime(void)
  647. {
  648.     struct timeb my_timeb;
  649.     struct emx_timeb {
  650.       long time, millitm, timezone, dstflag;
  651.     } emx_timeb;
  652.  
  653.     ftime(&my_timeb);
  654.     emx_timeb.time = my_timeb.time;
  655.     emx_timeb.millitm = (long) my_timeb.millitm;
  656.     emx_timeb.timezone = (long) my_timeb.timezone;
  657.     emx_timeb.dstflag = (long) my_timeb.dstflag;
  658.     cpy16_32(DS, EDX, &emx_timeb, sizeof(emx_timeb));
  659.     return CARRY_NON;
  660. }
  661.  
  662. /* eax umask(edx) err:no */
  663. static int sys_emx28_umask(void)
  664. {
  665.     EAX = EDX;
  666.     return CARRY_NON;
  667. }
  668.  
  669. /* eax getppid(void) err:no */
  670. static int sys_emx29_getppid(void)
  671. {
  672.     EAX = (DWORD) npz->pptr->pid;
  673.     return CARRY_NON;
  674. }
  675.  
  676. /* void nls_menupr(buf edx,size ecx) err:no */
  677. /* buffer to upper case */
  678. static int sys_emx2a_nlsmemupr(void)
  679. {
  680.     return CARRY_NON;
  681. }
  682.  
  683. /*
  684. **  eax open(edx, ecx) errno:ecx
  685. **
  686. **  pathname <= sizeof(iobuf) !
  687. **  creat: CH = creat file attr
  688. **  open:  CL = access & sharing mode
  689. */
  690. static int sys_emx2b_open(void)
  691. {
  692.     int i;
  693.  
  694.     strcpy32_16(DS, EDX, iobuf);
  695.     i = (int) (ECX >> 16);    /* 1 = O_CREAT, 2 = O_EXCL, 4 = O_TRUNC */
  696.  
  697.     if (i & 0x01) {
  698.     if (i & 0x02)        /* O_CREAT | O_EXCL */
  699.         tr.eax = 0x5B00;
  700.     else if (i & 4)        /* O_CREAT | O_TRUNC */
  701.         tr.eax = 0x3C00;
  702.     else if (access(iobuf, 4))    /* O_CREAT */
  703.         tr.eax = 0x3C00;
  704.     else
  705.         tr.eax = 0x3D00L | (CX & 0xff);
  706.     } else            /* not O_CREAT */
  707.     tr.eax = 0x3D00L | (CX & 0xff);
  708.  
  709.     tr.ecx = (ECX & 0xFFFF) >> 8;
  710.     tr.edx = (DWORD) (WORD) iobuf;
  711.     tr.flags = FLAGS & ~1;
  712.     if (realdos())
  713.     set_ecx_error(doserror_to_errno((WORD) tr.eax));
  714.     else {
  715.     set_eax_return(tr.eax);
  716.     if ((i & 0x05) == 0x4)    /* O_TRUNC with open */
  717.         if (chsize(AX, 0))
  718.         set_ecx_error(doserror_to_errno(_doserrno));
  719.     }
  720.     return CARRY_NON;
  721. }
  722.  
  723. /* eax newthread(edx) errno:ecx */
  724. static int sys_emx2c_newthread(void)
  725. {
  726.     set_ecx_error(EMX_EMSDOS);
  727.     return CARRY_NON;
  728. }
  729.  
  730. /* eax endthread(void) errno:ecx */
  731. static int sys_emx2d_endthread(void)
  732. {
  733.     set_ecx_error(EMX_EMSDOS);
  734.     return CARRY_NON;
  735. }
  736.  
  737. /* waitpid() */
  738. static int sys_emx2e_waitpid(void)
  739. {
  740.     set_ecx_error(EMX_EMSDOS);
  741.     return CARRY_NON;
  742. }
  743.  
  744. static int sys_emx2f_readkbd()
  745. {
  746.     int key;
  747.  
  748.     if (DX & 2) {        /* wait */
  749.     while (_bios_keybrd(kready))
  750.         _bios_keybrd(kread);
  751.     key = _bios_keybrd(kread);
  752.     } else
  753.      /* no wait */ if ((key = _bios_keybrd(kready)) != 0)
  754.     key = _bios_keybrd(kread);
  755.     else {
  756.     EAX = -1;
  757.     return CARRY_NON;
  758.     }
  759.  
  760.     if ((key & 0xff) == 0xE0)
  761.     key = 0;
  762.  
  763.     if (DX & 1)            /* echo */
  764.     if ((key & 0xff) >= 32)
  765.         putchar(key & 0xff);
  766.  
  767.     if (DX & 4 && (char) key == 3)    /* signal */
  768.     send_signal(npz, SIGINT);
  769.  
  770.     EAX = (DWORD) (0 | (key & 0xff));
  771.  
  772.     return CARRY_NON;
  773. }
  774.  
  775. /* sleep2 ; err:-*/
  776. static int sys_emx30_sleep2(void)
  777. {
  778.     unsigned long timel;
  779.  
  780.     timel = time_tic + EDX / 55;
  781.     for (;;)
  782.     if (time_reached(timel))
  783.         break;
  784.     return CARRY_NON;
  785. }
  786.  
  787. /* void unwind2(); not DOS */
  788. static int sys_emx31_unwind2(void)
  789. {
  790.     return CARRY_NON;
  791. }
  792.  
  793. /* void pause(); not DOS */
  794. static int sys_emx32_pause(void)
  795. {
  796.     return CARRY_NON;
  797. }
  798.  
  799. /* int execname(edx=buf, ecx=size); err=-1 */
  800. static int sys_emx33_execname(void)
  801. {
  802.     EAX = -1;
  803.     return CARRY_NON;
  804. }
  805.  
  806. /* int initthread() ; not DOS */
  807. static int sys_emx34_initthread(void)
  808. {
  809.     EAX = -1;
  810.     return CARRY_NON;
  811. }
  812.  
  813. #define EMX_FNCT_MAX 0x35
  814. typedef int (*EMXFNCT)(void);
  815.  
  816. static EMXFNCT emx_fnct[EMX_FNCT_MAX] = {
  817.     sys_emx00_sbrk,
  818.     sys_emx01_brk,
  819.     sys_emx02_ulimit,
  820.     sys_emx03_vmstat,
  821.     sys_emx04_umask,
  822.     sys_emx05_getpid,
  823.     sys_emx06_spawn,
  824.     sys_emx07_unused,
  825.     sys_emx08_ptrace,
  826.     sys_emx09_wait,
  827.     sys_emx0a_version,
  828.     sys_emx0b_memavail,
  829.     sys_emx0c_signal,
  830.     sys_emx0d_kill,
  831.     sys_emx0e_raise,
  832.     sys_emx0f_uflags,
  833.     sys_emx10_unwind,
  834.     sys_emx11_core,
  835.     sys_emx12_portaccess,
  836.     sys_emx13_memaccess,
  837.     sys_emx14_ioctl,
  838.     sys_emx15_alarm,
  839.     sys_emx16_internal,
  840.     sys_emx17_sleep,
  841.     sys_emx18_chsize,
  842.     sys_emx19_fcntl,
  843.     sys_emx1a_pipe,
  844.     sys_emx1b_fsync,
  845.     sys_emx1c_fork,
  846.     sys_emx1d_scrsize,
  847.     sys_emx1e_select,
  848.     sys_emx1f_syserrno,
  849.     sys_emx20_stat,
  850.     sys_emx21_fstat,
  851.     sys_emx22_unused,
  852.     sys_emx23_filesys,
  853.     sys_emx24_utimes,
  854.     sys_emx25_ftruncate,
  855.     sys_emx26_clock,
  856.     sys_emx27_ftime,
  857.     sys_emx28_umask,
  858.     sys_emx29_getppid,
  859.     sys_emx2a_nlsmemupr,
  860.     sys_emx2b_open,
  861.     sys_emx2c_newthread,
  862.     sys_emx2d_endthread,
  863.     sys_emx2e_waitpid,
  864.     sys_emx2f_readkbd,
  865.     sys_emx30_sleep2,
  866.     sys_emx31_unwind2,
  867.     sys_emx32_pause,
  868.     sys_emx33_execname,
  869.     sys_emx34_initthread } ;
  870.  
  871. static int i_21_7f(void)
  872. {
  873.     WORD i = AX & 0xFF;
  874.  
  875.     /* emx fnct = al */
  876.     if (i < EMX_FNCT_MAX)
  877.     return (emx_fnct[i])();
  878.     else {
  879.     printf("Unknown syscall: %04X\n", i);
  880.     send_signal(npz, SIGSEGV);
  881.     return CARRY_ON;
  882.     }
  883. }
  884.  
  885. extern int i_21_ff(void);
  886.  
  887. void int21(void)
  888. {
  889.     WORD ret;
  890.  
  891.     if (opt_print_syscalls)
  892.     printf("DOS 21h: %04X %08lX %08lX %08lX", AX, EBX, ECX, EDX);
  893.  
  894.     if ((AX & 0xff00) == 0x7f00)/* emx functions */
  895.     ret = i_21_7f();
  896.     else if ((AX & 0xff00) == 0xff00)    /* go32 functions */
  897.     ret = i_21_ff();
  898.     else {            /* DOS functions */
  899.     ret = int21normal();
  900.     /* if DOS indicates an error (carry-flag set), convert error code */
  901.     if (ret == CARRY_NON && (FLAGS & 1)) {
  902.         EAX = (DWORD) doserror_to_errno(AX);
  903.         ret = CARRY_ON;
  904.     }
  905.     }
  906.  
  907.     if (ret == CARRY_ON) {
  908.     EFLAGS |= 1;
  909.     if (npz->p_flags & PF_DJGPP_FILE)
  910.         EAX = (DWORD) errno_djgpp(AX);
  911.     } else if (ret == CARRY_OFF)
  912.     EFLAGS &= ~1L;
  913.  
  914.     if (opt_print_syscalls)
  915.     printf(" ret=%lX\n", EAX);
  916.  
  917.     if (npz->time_alarm != 0 && time_reached(npz->time_alarm)) {
  918.     npz->time_alarm = 0;
  919.     send_signal(npz, SIGALRM);
  920.     }
  921.     /* stack check */
  922.     if (npz->stack_down + 0x1000L >= ESP) {
  923.     puts("stack too small!!");
  924.     printf("ESP %lX  stack : min %lX max %lX\n",
  925.            ESP, npz->stack_down, npz->stack_top);
  926.     send_signal(npz, SIGKILL);
  927.     }
  928. }
  929.