⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sysemx.c

📁 大量的汇编程序源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
 * 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 <string.h>
#include <malloc.h>
#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;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -