/***************************************************************************** * FILE: sysemx.c * * * * DESC: * * - int 0x21 32 bit handler * * - int 0x21 emx syscall handler * * * * Copyright (C) 1993,1994 * * Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld * * email: rainer@mathematik.uni-bielefeld.de * * * *****************************************************************************/ #include #include #include "DPMI.H" #include "PRINTF.H" #include "RMLIB.H" #include "TIMEDOS.H" #include "PROCESS.H" #include "SIGNALS.H" #include "GNUAOUT.H" #include "START32.H" #include "CDOSX32.H" #include "COPY32.H" #include "EXCEP32.H" #include "RSX.H" #include "STATEMX.H" #include "PTRACE.H" #include "LOADPRG.H" #include "TERMIO.H" #include "DOSERRNO.H" #define CONVERT1_BX_HANDLE \ int h = get_dos_handle(BX); \ if (h < 0) { \ EAX = EMX_EBADF; \ return CARRY_ON; \ } \ else BX = h; #define CONVERT2_BX_HANDLE \ int h = get_dos_handle(BX); \ if (h < 0) { \ set_ecx_error(EMX_EBADF); \ return CARRY_ON; \ } \ else BX = h; static DWORD can_run_emx = 0x302e3961; /* ascii = 0.9a */ static int time_reached(unsigned long time) { if (time <= time_tic) return 1; else return 0; } static void set_ecx_error(int err) { EAX = -1L; if (npz->p_flags & PF_DJGPP_FILE) err = errno_djgpp(err); ECX = (long) err; } static void set_no_error(void) { EAX = ECX = 0L; } static void set_eax_return(DWORD reg_eax) { EAX = reg_eax; ECX = 0L; } /* ** SYSEMX functions returns: ** ** CARRY_ON : error, set carry-bit ** CARRY_OFF: no error, clear carry-bit ** CARRY_NON: do nothing */ /* oldbrk_eax sbrk(inc_edx) ; err:eax=-1 */ static int sys_emx00_sbrk(void) { EAX = getmem(EDX, npz); return CARRY_NON; } /* eax=0 brk(newbrk_edx) ; err:eax=-1 */ static int sys_emx01_brk(void) { if (EDX <= npz->brk_value) EAX = -1L; else if ((EAX = getmem(EDX - npz->brk_value, npz)) != -1L) EAX = 0L; return CARRY_NON; } /* maxbrk_eax ulimit(cmd_ecx,newlimit_edx) errno:ecx */ static int sys_emx02_ulimit(void) { if (ECX == 3L) { FREEMEMINFO fm; GetFreeMemInfo(&fm); set_eax_return(fm.LargestFree + npz->brk_value); } else set_ecx_error(EMX_EINVAL); return CARRY_NON; } /* emx special: void vmstat() */ static int sys_emx03_vmstat(void) { return CARRY_NON; } /* eax=filepermmask umask(edx) ; err:- */ static int sys_emx04_umask(void) { EAX = EDX; return CARRY_NON; } /* eax getpid(void) err:- */ static int sys_emx05_getpid(void) { EAX = (DWORD) npz->pid; return CARRY_NON; } /* ** eax = spawnve(proc_env *edx) err:carry errno:eax */ static int sys_emx06_spawn(void) { int i, ret; PROCESS_ENV pe; static char filename[260]; char **argp = NULL, **envp = NULL; char *envmem = NULL, *argmem = NULL; char *s; /* get process data, check mode */ cpy32_16(DS, EDX, &pe, (DWORD) sizeof(PROCESS_ENV)); pe.mode &= 0xff; if (pe.mode >= P_SESSION) { /* OS/2 modes */ EAX = EMX_EINVAL; return CARRY_ON; } /* get memory for args and environment (env must para aligned) */ if ((argp = (char **) malloc((pe.arg_count + 1) * sizeof(char *))) == NULL || (envp = (char **) malloc((pe.env_count + 1) * sizeof(char *))) == NULL || (argmem = (char *) malloc((pe.arg_size + 1) & ~1)) == NULL || (envmem = (char *) malloc((pe.env_size + 20) & ~1)) == NULL ) { printf("argmem,envmem to large a:%d e:%d\n", pe.arg_size, pe.env_size); if (argp != NULL) free(argp); if (envp != NULL) free(envp); if (argmem != NULL) free(argmem); if (envmem != NULL) free(envmem); EAX = EMX_E2BIG; return CARRY_ON; } /* get args from user ds, built arg-vector */ cpy32_16(DS, pe.arg_off, argmem, (DWORD) pe.arg_size); s = argmem; for (i = 0; i < (int) pe.arg_count; i++) { s++; /* skip flag bits */ argp[i] = s; s += (strlen(argp[i]) + 1); } argp[i] = NULL; /* get env from user ds, built env-vector */ s = (char *) (((int)envmem + 15) & ~15); /* segment align */ cpy32_16(DS, pe.env_off, s, (DWORD) pe.env_size); s[pe.env_size] = 0; /* for dos exec */ s[pe.env_size+1] = 0; for (i = 0; i < (int) pe.env_count; i++) { envp[i] = s; s += (strlen(envp[i]) + 1); } envp[i] = NULL; /* get filename */ strcpy32_16(DS, pe.fname_off, filename); /* load a.out prg */ ret = exec32(pe.mode, filename, pe.arg_count, argp, pe.env_count, envp); /* if error, try a real-mode prg */ if (ret == EMX_ENOEXEC) { ret = realmode_prg(filename, argp, envp); if (pe.mode == P_OVERLAY && ret != -1) do_exit4c(0); /* close current emx program */ } free(argmem); free(envmem); free(argp); free(envp); /* check error and return */ if (ret) { EAX = (DWORD) ret; return CARRY_ON; } else return CARRY_OFF; } static int sys_emx07_sigreturn(void) { signal_handler_returned(); return CARRY_NON; } /* eax ptrace(ebx,edi,edx,ecx) err:ecx!=0 eax=-1 */ static int sys_emx08_ptrace(void) { int error; DWORD data; if ((error = do_ptrace(BX, DI, EDX, ECX, &data)) != 0) set_ecx_error(error); else set_eax_return(data); return CARRY_NON; } /* eax=child_id wait(status_edx) ; errno:ecx */ static int sys_emx09_wait(void) { int ret; unsigned status; if ((ret = sys_wait(&status)) != -1) { EDX = (DWORD) status; set_eax_return((DWORD) (unsigned) ret); } else set_ecx_error(EMX_ESRCH); return CARRY_NON; } #define RUN_VCPI 0x0001L #define RUN_XMS 0x0002L #define RUN_VDISK 0x0004L #define RUN_DESQVIEW 0x0008L #define RUN_287 0x0010L #define RUN_387 0x0020L #define RUN_486 0x0040L #define RUN_DPMI09 0x0080L #define RUN_DPMI10 0x0100L #define RUN_OS2 0x0200L #define RUN_T_OPT 0x0400L #define RUN_AC_OPT 0x0800L #define RUN_RSX 0x1000L /* get emx-version ; err:- */ static int sys_emx0a_version(void) { DWORD run_info; run_info = RUN_RSX | RUN_AC_OPT; /* RSX | data executable bit */ if (copro) run_info |= RUN_387; /* with emu */ if (dpmi10) run_info |= RUN_DPMI10; else run_info |= RUN_DPMI09; /* enable gcc -pipe for emx 0.8x */ if (opt_os2) run_info |= RUN_OS2; EAX = can_run_emx; EBX = run_info; ECX = 0L; EDX = 0L; return CARRY_NON; } /* eax_pages memavail(void) ; err:- */ static int sys_emx0b_memavail(void) { FREEMEMINFO fm; GetFreeMemInfo(&fm); EAX = fm.MaxUnlockedPages; return CARRY_NON; } /* (*prevh) signal(signo_ecx,address_edx) err:eax=-1 */ static int sys_emx0c_signal(void) { EAX = sys_signal ((int)ECX, EDX); return CARRY_NON; } /* eax=0 kill(id_edx,signo_ecx) errno:ecx eax=-1 */ static int sys_emx0d_kill(void) { NEWPROCESS *p; if (!(p = find_process((unsigned) EDX))) { set_ecx_error(EMX_ESRCH); return CARRY_NON; } else if (send_signal(p, (int) (long) ECX)) { set_ecx_error(EMX_EINVAL); return CARRY_NON; } else set_no_error(); /* switch, if child */ if (p->pptr->pid == npz->pid) { p->p_status = PS_RUN; switch_context(p); } return CARRY_NON; } /* eax raise(ecx) errno:ecx eax=-1 */ static int sys_emx0e_raise(void) { if (send_signal(npz, CX)) set_ecx_error(EMX_EINVAL); return CARRY_NON; } /* oldflags uflags(mask=ecx,new=edx) ;; bits 0-1 emx,SysV,BSD signals */ static int sys_emx0f_uflags(void) { EAX = npz->uflags; npz->uflags &= ~ECX; npz->uflags |= EDX; return CARRY_NON; } /* void unwind(void) err:no */ static int sys_emx10_unwind(void) { return CARRY_NON; } /* core(handle_ebx) err:carry errno */ static int sys_emx11_core(void) { CONVERT1_BX_HANDLE ; write_core(BX, npz); EAX = 0; return CARRY_OFF; } /* portaccess(ecx,edx) ecx=first edx=last, err:cy errno:eax */ static int sys_emx12_portaccess(void) { /* dpmi-server must allow this */ ECX = 0L; /* first port */ EDX = 0x3ffL; /* last port */ EAX = 0L; return CARRY_OFF; } /* eax memaccess(Start=ebx,End=ecx,Flags=edx) err:carry errno:eax */ /* under DPMI it's better to used a different segment */ /* memaccess destroy protection -> limit 0xffffffff */ /* must use wrap-around to access memory */ static int sys_emx13_memaccess(void) { if ((opt_memaccess || (npz->options & OPT_MEMACCESS)) && EBX <= 0xFFFFFL && ECX <= 0xFFFFFL) { if (!dpmi10) { /* UINT sel; DWORD screen_base; if (SegToSel((UINT)(EBX >> 4), &sel)) screen_base = EBX; else GetBaseAddress(sel, &screen_base); EAX = screen_base - npz->memaddress; */ EAX = EBX - npz->memaddress; } else EAX = EBX + DPMI_PRG_DATA; return CARRY_OFF; } else { EAX = EMX_EINVAL; return CARRY_ON; } } int sysemx_ioctl(int dos_handle, ARGUSER request, ARGUSER arg) { int attr, ret; if ((attr = rm_ioctl_getattr(dos_handle)) == -1) return -EMX_EBADF; if (request >= TCGETA && request <= TCFLSH) { if (dos_handle == 0 && (attr & 128)) { /* keyboard handle */ return kbd_ioctl((unsigned)request, arg); } else /* others not supported */ return -EMX_EBADF; } else if (request == FIONREAD) { if (dos_handle == 0 && (attr & 128) && (npz->p_flags & PF_TERMIO)) ret = kbd_ioctl((unsigned)request, arg); else { /* others: 1=ready 0=not */ ret = rm_ioctl_select_in(dos_handle); store32(npz->data32sel, arg, (long) ret); ret = 0; } return ret; } else if (request == FGETHTYPE) { long temp; if (!(attr & 128)) temp = HT_FILE; else if (attr & 3) temp = HT_DEV_CON; else if (attr & 4) temp = HT_DEV_NUL; else if (attr & 8) temp = HT_DEV_CLK; else temp = HT_DEV_OTHER; store32(DS, arg, temp); return 0; } else return -EMX_EINVAL; } /* ** eax = ioctl2(ebx,ecx,edx) errno:ecx eax=-1 */ static int sys_emx14_ioctl(void) { int ret = sys_ioctl((int)EBX, ECX, EDX); if (ret < 0) set_ecx_error(-ret); else set_eax_return(ret); return CARRY_NON; } /* eax=sec alarm(sec_edx) err:no */ static int sys_emx15_alarm(void) { if (time_tic < npz->time_alarm) /* there seconds left */ EAX = (npz->time_alarm - time_tic) * 182 / 10; else EAX = 0; if (EDX == 0) /* clear alarm */ npz->time_alarm = 0; else /* set alarm */ npz->time_alarm = time_tic + EDX * 182 / 10; return CARRY_NON; } /* no syscall; internal */ static int sys_emx16_internal(void) { return CARRY_NON; } /* ** return ramaining clock tics */ static DWORD sleep_until(DWORD timel) { for (;;) { if (time_reached(timel)) return 0; if (npz->sig_raised & ~npz->sig_blocked) return (timel - time_tic - 1); schedule(); } } /* eax=0 sleep(edx) err:no */ static int sys_emx17_sleep(void) { EAX = sleep_until(time_tic + EDX * 182 / 10) * 10 / 182; return CARRY_NON; } /* ** chsize(handle_ebx, lenght_edx) err:carry eax=errno */ static int sys_emx18_chsize(void) { CONVERT1_BX_HANDLE; if (rm_lseek(BX, EDX, SEEK_SET) == -1L || rm_write(BX, iobuf, 0) == -1) { EAX = (DWORD) doserror_to_errno(_doserrno); return CARRY_ON; } EAX = 0; return CARRY_OFF; } /* eax fcntl(handle ebx,req ecx,arg edx) errno:ecx */ static int sys_emx19_fcntl(void) { int fd = (int) (long) EBX; struct file *filp; if (fd >= N_FILES) return -EMX_EBADF; if (!(filp = npz->filp[fd])) return -EMX_EBADF; switch ((int)(long)ECX) { case F_GETFL: set_eax_return(filp->f_flags); break; case F_SETFL: filp->f_flags &= ~(FCNTL_NDELAY | FCNTL_APPEND); filp->f_flags |= EDX & (FCNTL_NDELAY | FCNTL_APPEND); set_no_error(); break; case F_GETFD: set_eax_return(FD_ISSET(fd, &npz->close_on_exec)); break; case F_SETFD: if (EDX & 1) FD_SET(fd, &npz->close_on_exec); else FD_CLR(fd, &npz->close_on_exec); set_no_error(); break; default: set_ecx_error(EMX_EINVAL); break; } return CARRY_NON; } /* eax pipe(edx,ecx) errno:ecx*/ static int sys_emx1a_pipe(void) { int ret = sys_pipe(ECX, EDX); if (ret) set_ecx_error(-ret); else set_no_error(); return CARRY_NON; } /* eax fsync(ebx) errno:ecx */ static int sys_emx1b_fsync(void) { set_ecx_error(EMX_EMSDOS); return CARRY_NON; } /* eax fork(void) errno:ecx */ static int sys_emx1c_fork(void) { int ret; if ((ret = sys_fork()) < 0) set_ecx_error(-ret); else set_eax_return(ret); return CARRY_NON; } /* void scrsize(EDX) */ static int sys_emx1d_scrsize(void) { store32(DS, EDX + 0L, read32(bios_selector, 0x4AL) & 0xFFFFL); store32(DS, EDX + 4L, (read32(bios_selector, 0x84L) & 0xFFL) + 1L); return CARRY_NON; } int sysemx_select(int dos_handle, DWORD tics) { int is_termio_handle = 0; DWORD time_end = time_tic + tics; if (dos_handle == 0 && rm_isatty(dos_handle) && (npz->p_flags & PF_TERMIO)) is_termio_handle = 1; for (;;) { if (is_termio_handle) { if (rm_bios_read_keybrd(kready)) return 1; } if (rm_ioctl_select_in(dos_handle)) return 1; if (tics != 0xFFFFFFFF && time_reached(time_end)) return 0; } } /* void select(edx) errno:ecx */ static int sys_emx1e_select(void) { int ret = sys_select(EDX); if (ret < 0) set_ecx_error(-ret); else set_eax_return(ret); return CARRY_NON; } /* eax syserrno(void) */ static int sys_emx1f_syserrno(void) { EAX = doserror_to_errno(_doserrno); return CARRY_NON; } /* ** eax stat(name_edx,struc_edi) errno:ecx */ static int sys_emx20_stat(void) { struct stat st; strcpy32_16(DS, EDX, iobuf); if (!sys_stat(iobuf, &st)) { cpy16_32(DS, EDI, &st, sizeof(st)); set_no_error(); } else set_ecx_error(doserror_to_errno(_doserrno)); return CARRY_NON; } /* ** eax fstat(ebx, edi) errno:ecx */ static int sys_emx21_fstat(void) { struct stat st; CONVERT2_BX_HANDLE; if (!sys_fstat(BX, &st)) { cpy16_32(DS, EDI, &st, sizeof(st)); set_no_error(); } else set_ecx_error(doserror_to_errno(_doserrno)); return CARRY_NON; } static int sys_emx22_unused(void) { return CARRY_NON; } /* filesys(edx,edi,ecx) errno:ecx */ static int sys_emx23_filesys(void) { char drive[4]; char *res; int ret; *(DWORD *) drive = read32(DS, EDX); if (drive[0] >= 'a') drive[0] -= 0x20; if (drive[0] < 'A' || drive[0] > 'Z' || drive[1] != ':' || drive[2] != 0) { set_ecx_error(EMX_EINVAL); return -1; } drive[0] -= ('A' - 1); ret = rm_ioctl_remotedrive(drive[0]); if (ret == 1) res = "LAN"; else res = "FAT"; strcpy16_32(DS, EDI, res); set_no_error(); return CARRY_NON; } /* eax utimes(name_edx,struct tval esi) errno:ecx */ /* set access and modif time of file */ static int sys_emx24_utimes(void) { struct file_time ft; DWORD utimes[2]; int handle; strcpy32_16(DS, EDX, iobuf); cpy32_16(DS, ESI, utimes, sizeof(utimes)); if ((handle = rm_open(iobuf, RM_O_WRONLY)) == -1) { set_ecx_error(doserror_to_errno(_doserrno)); return CARRY_NON; } gmt2filetime(utimes[0], &ft); if (rm_setftime(handle, ft.ft_date, ft.ft_time) == -1) set_ecx_error(doserror_to_errno(_doserrno)); else set_eax_return(0); rm_close(handle); return CARRY_NON; } /* eax ftruncate(ebx,edx) errno:ecx */ static int sys_emx25_ftruncate(void) { long temp; CONVERT2_BX_HANDLE; if ((temp = rm_lseek(BX, 0, SEEK_END)) == -1) { set_ecx_error(doserror_to_errno(_doserrno)); return CARRY_NON; } else if (temp > (long) EDX) { if (rm_lseek(BX, EDX, SEEK_SET) == -1 || rm_write(BX, iobuf, 0) == -1) { set_ecx_error(doserror_to_errno(_doserrno)); return CARRY_NON; } } set_no_error(); return CARRY_NON; } /* eax clock(void) err:no */ static int sys_emx26_clock(void) { /* clk_tck = 100 ; timer 18.2 pre sec */ EAX = (time_tic - npz->time_tic) * 500 / 91; EDX = 0; return CARRY_NON; } /* void ftime(edx) err:no */ static int sys_emx27_ftime(void) { struct emx_timeb { long time, millitm, timezone, dstflag; } emx_timeb; struct dos_date dd; struct dos_time dt; unsigned long gmt; rm_getdate(&dd); rm_gettime(&dt); gmt = dos2gmt(&dd, &dt); emx_timeb.time = gmt; emx_timeb.millitm = (DWORD) dt.dtime_hsec * 10; emx_timeb.timezone = 0; emx_timeb.dstflag = 0; cpy16_32(DS, EDX, &emx_timeb, sizeof(emx_timeb)); return CARRY_NON; } /* eax umask(edx) err:no */ static int sys_emx28_umask(void) { EAX = EDX; return CARRY_NON; } /* eax getppid(void) err:no */ static int sys_emx29_getppid(void) { EAX = (DWORD) npz->pptr->pid; return CARRY_NON; } /* void nls_menupr(buf edx,size ecx) err:no */ /* buffer to upper case */ static int sys_emx2a_nlsmemupr(void) { return CARRY_NON; } /* ** eax open(edx, ecx) errno:ecx ** ** pathname <= sizeof(iobuf) ! ** creat: CH = creat file attr ** open: CL = access & sharing mode */ typedef int (*OPENFUNC) (char *, WORD); static int sys_emx2b_open(void) { int i, dosfile, handle; OPENFUNC openfn; WORD p2; strcpy32_16(DS, EDX, iobuf); /* replace unix names */ if (strcmp("/dev/null", iobuf) == 0) strcpy(iobuf, "nul"); else if (strcmp("/dev/tty", iobuf) == 0) strcpy(iobuf, "con"); i = (int) (ECX >> 16); /* 1 = O_CREAT, 2 = O_EXCL, 4 = O_TRUNC */ /* 8 = O_INHERIT, 16 = SYNC */ if (i & 0x01) { if (i & 0x02) /* O_CREAT | O_EXCL */ openfn = rm_creatnew; else if (i & 4) /* O_CREAT | O_TRUNC */ openfn = rm_creat; else if (rm_access(iobuf, 0) == -1) /* old file there ? */ openfn = rm_creat; else openfn = rm_open; } else /* not O_CREAT */ openfn = rm_open; if (openfn == rm_open) p2 = CX & 0xff; /* open mode */ else p2 = CX >> 8; /* creat attrib */ dosfile = (*openfn) (iobuf, p2); if (dosfile == -1) set_ecx_error(doserror_to_errno(_doserrno)); else { if ((i & 0x05) == 0x4) { /* O_TRUNC with open */ if (rm_lseek(dosfile, 0, SEEK_SET) == -1L || rm_write(dosfile, iobuf, 0) == -1) { set_ecx_error(doserror_to_errno(_doserrno)); return CARRY_NON; } } handle = get_empty_proc_filp(); npz->filp[handle]->f_mode = FMODE_READ | FMODE_WRITE; npz->filp[handle]->f_doshandle = dosfile; npz->filp[handle]->f_op = & msdos_fop; if (i & 16) /* inherit file handle */ FD_CLR(handle, &npz->close_on_exec); set_eax_return(handle); } return CARRY_NON; } /* eax newthread(edx) errno:ecx */ static int sys_emx2c_newthread(void) { set_ecx_error(EMX_EMSDOS); return CARRY_NON; } /* eax endthread(void) errno:ecx */ static int sys_emx2d_endthread(void) { set_ecx_error(EMX_EMSDOS); return CARRY_NON; } /* waitpid(pid_edx, options_ecx) ret: eax,ecx edx=status*/ static int sys_emx2e_waitpid(void) { if (!opt_schedule) set_ecx_error(EMX_EMSDOS); else { int ret; unsigned status; if ((ret = sys_waitpid((int)EDX, &status)) >= 0) { EDX = (DWORD) status; set_eax_return((DWORD) (unsigned) ret); } else set_ecx_error(EMX_ESRCH); } return CARRY_NON; } static int sys_emx2f_readkbd() { static unsigned char next_key = 0; int key; unsigned char ascii, scan; if (next_key) { EAX = (DWORD) next_key; next_key = 0; return CARRY_NON; } if (DX & 2) { /* wait */ while (rm_bios_read_keybrd(kready)) rm_bios_read_keybrd(kread); key = rm_bios_read_keybrd(kread); } else if ((key = rm_bios_read_keybrd(kready)) != 0) key = rm_bios_read_keybrd(kread); else { EAX = -1; return CARRY_NON; } ascii = (BYTE) (key & 0xFF); scan = (BYTE) (key >> 8); if (ascii == 0xE0) ascii = 0; if (ascii == 0) next_key = scan; if (DX & 1) /* echo */ if (ascii >= 32) /* change to: sys_write() */ rm_write((int) npz->filp[1]->f_doshandle, &ascii, 1); if ((DX & 4) && ascii == 3) /* signal */ send_signal(npz, SIGINT); EAX = (DWORD) (ascii); return CARRY_NON; } /* sleep2 ; err:-*/ static int sys_emx30_sleep2(void) { sleep_until(time_tic + EDX / 55); EAX = 0; return CARRY_NON; } /* void unwind2(); not DOS */ static int sys_emx31_unwind2(void) { return CARRY_NON; } /* void pause(); err: eax=-1, return until signal handler */ static int sys_emx32_pause(void) { for (;;) { if (npz->sig_raised & ~npz->sig_blocked) { EAX = 0; break; } if (!schedule()) { /* no other processes */ EAX = -1L; break; } } return CARRY_NON; } /* int execname(edx=buf, ecx=size); err=-1 */ static int sys_emx33_execname(void) { DWORD pos = read32(npz->data32sel, npz->stack_top - 8L); DWORD len = read32(npz->data32sel, npz->stack_top - 12L); if (ECX < len || verify_illegal(npz, EDX, len) || verify_illegal(npz, pos, len)) { EAX = -1; return CARRY_NON; } cpy32_32(npz->data32sel, pos, npz->data32sel, EDX, npz->stack_top - pos); EAX = 0; return CARRY_NON; } /* int initthread() ; not DOS */ static int sys_emx34_initthread(void) { EAX = -1; return CARRY_NON; } /* int sigaction(no ECX, in EDX, out EBX) */ static int sys_emx35_sigaction(void) { int err = sys_sigaction((int)ECX, EDX, EBX); if (err < 0) set_ecx_error(-err); else set_eax_return(err); return CARRY_NON; } /* int sigpending(in EDX) */ static int sys_emx36_sigpending(void) { int err = sys_sigpending(EDX); if (err < 0) set_ecx_error(-err); else set_eax_return(err); return CARRY_NON; } /* int sigprocmask(how ECX, in EDX, out EBX) */ static int sys_emx37_sigprocmask(void) { int err = sys_sigprocmask((int)ECX, EDX, EBX); if (err < 0) set_ecx_error(-err); else set_eax_return(err); return CARRY_NON; } /* int sigsuspend(sigset_t EDX) */ static int sys_emx38_sigsuspend(void) { set_ecx_error(EMX_EMSDOS); return CARRY_NON; } /* os/2 only */ static int sys_emx39_imphandle(void) { set_ecx_error(EMX_EMSDOS); return CARRY_NON; } #define EMX_FNCT_MAX 0x40 typedef int (*EMXFNCT) (void); static EMXFNCT emx_fnct[EMX_FNCT_MAX] = { sys_emx00_sbrk, sys_emx01_brk, sys_emx02_ulimit, sys_emx03_vmstat, sys_emx04_umask, sys_emx05_getpid, sys_emx06_spawn, sys_emx07_sigreturn, sys_emx08_ptrace, sys_emx09_wait, sys_emx0a_version, sys_emx0b_memavail, sys_emx0c_signal, sys_emx0d_kill, sys_emx0e_raise, sys_emx0f_uflags, sys_emx10_unwind, sys_emx11_core, sys_emx12_portaccess, sys_emx13_memaccess, sys_emx14_ioctl, sys_emx15_alarm, sys_emx16_internal, sys_emx17_sleep, sys_emx18_chsize, sys_emx19_fcntl, sys_emx1a_pipe, sys_emx1b_fsync, sys_emx1c_fork, sys_emx1d_scrsize, sys_emx1e_select, sys_emx1f_syserrno, sys_emx20_stat, sys_emx21_fstat, sys_emx22_unused, sys_emx23_filesys, sys_emx24_utimes, sys_emx25_ftruncate, sys_emx26_clock, sys_emx27_ftime, sys_emx28_umask, sys_emx29_getppid, sys_emx2a_nlsmemupr, sys_emx2b_open, sys_emx2c_newthread, sys_emx2d_endthread, sys_emx2e_waitpid, sys_emx2f_readkbd, sys_emx30_sleep2, sys_emx31_unwind2, sys_emx32_pause, sys_emx33_execname, sys_emx34_initthread, sys_emx35_sigaction, sys_emx36_sigpending, sys_emx37_sigprocmask, sys_emx38_sigsuspend, sys_emx39_imphandle /* sys_emx3a_fpu */ }; static int i_21_7f(void) { WORD i = AX & 0xFF; /* emx fnct = al */ if (i < EMX_FNCT_MAX) return (emx_fnct[i]) (); else { set_ecx_error(EMX_EMSDOS); if (opt_printall) printf("Warning: unknown emx syscall: %04X\n", i); return CARRY_ON; } } extern int i_21_ff(void); extern int i_21_fe(void); void int21(void) { WORD ret; if (opt_print_syscalls) printf("21h: a=%08X b=%08lX c=%08lX d=%08lX D=%08lX S=%08lX\n" , AX, EBX, ECX, EDX, EDI, ESI); /* emx functions */ if ((AX & 0xff00) == 0x7f00) ret = i_21_7f(); /* go32 functions */ else if ((AX & 0xff00) == 0xff00) ret = i_21_ff(); /* go32 debug */ else if ((AX & 0xff00) == 0xfe00) ret = i_21_fe(); /* DOS functions */ else { ret = int21normal(); /* if DOS indicates an error (carry-flag set), convert error code */ if (ret == CARRY_NON && (FLAGS & 1)) { EAX = (DWORD) doserror_to_errno(AX); ret = CARRY_ON; } } if (ret == CARRY_ON) { EFLAGS |= 1; if (npz->p_flags & PF_DJGPP_FILE) EAX = (DWORD) errno_djgpp(AX); } else if (ret == CARRY_OFF) EFLAGS &= ~1L; if (opt_print_syscalls) printf(" : a=%08lX b=%08lX c=%08lX d=%08lX D=%08lX S=%08lX F:%04X\n" , EAX, EBX, ECX, EDX, EDI, ESI, FLAGS); if (npz->time_alarm != 0 && time_reached(npz->time_alarm)) { npz->time_alarm = 0; send_signal(npz, SIGALRM); } /* stack check */ if (npz->stack_down + 0x1000L >= ESP) { puts("stack too small!!"); printf("ESP %lX stack : min %lX max %lX\n", ESP, npz->stack_down, npz->stack_top); send_signal(npz, SIGKILL); } }