int
linux_sys_sched_get_priority_min(struct lwp *l, const struct linux_sys_sched_get_priority_min_args *uap, register_t *retval)
{
	/* {
		syscallarg(int) policy;
	} */

	switch (SCARG(uap, policy)) {
	case LINUX_SCHED_OTHER:
		*retval = 0;
		break;
	case LINUX_SCHED_FIFO:
	case LINUX_SCHED_RR:
		*retval = LINUX_SCHED_RTPRIO_MIN;
		break;
	default:
		return EINVAL;
	}

	return 0;
}
int
ultrix_sys_sigvec(struct lwp *l, const struct ultrix_sys_sigvec_args *uap, register_t *retval)
{
	struct sigvec nsv, osv;
	struct sigaction nsa, osa;
	int error;

	if (SCARG(uap, nsv)) {
		error = copyin(SCARG(uap, nsv), &nsv, sizeof(nsv));
		if (error)
			return error;
		nsa.sa_handler = nsv.sv_handler;
#if 0 /* documentation */
		/* ONSTACK is identical */
		nsa.sa_flags = nsv.sv_flags & ULTRIX_SV_ONSTACK;
		if ((nsv.sv_flags & ULTRIX_SV_OLDSIG)
		    /* old signal() - always restart */
		    || (!(nsv.sv_flags & ULTRIX_SV_INTERRUPT))
		    /* inverted meaning (same bit) */
		    )
			nsa.sa_flags |= SA_RESTART;
#else /* optimized - assuming ULTRIX_SV_OLDSIG=>!ULTRIX_SV_INTERRUPT */
		nsa.sa_flags = nsv.sv_flags & ~ULTRIX_SV_OLDSIG;
		nsa.sa_flags ^= SA_RESTART;
#endif
		native_sigset13_to_sigset(&nsv.sv_mask, &nsa.sa_mask);
	}
	error = sigaction1(l, SCARG(uap, signum),
	    SCARG(uap, nsv) ? &nsa : 0, SCARG(uap, osv) ? &osa : 0,
	    NULL, 0);
	if (error)
		return error;
	if (SCARG(uap, osv)) {
		osv.sv_handler = osa.sa_handler;
		osv.sv_flags = osa.sa_flags ^ SA_RESTART;
		osv.sv_flags &= (ULTRIX_SV_ONSTACK | ULTRIX_SV_INTERRUPT);
		native_sigset_to_sigset13(&osa.sa_mask, &osv.sv_mask);
		error = copyout(&osv, SCARG(uap, osv), sizeof(osv));
		if (error)
			return error;
	}
	return 0;
}
Beispiel #3
0
int
darwin_sys_socket(struct lwp *l, const struct darwin_sys_socket_args *uap, register_t *retval)
{
	/* {
		syscallarg(int) domain;
		syscallarg(int) type;
		syscallarg(int) protocol;
	} */
	struct compat_30_sys_socket_args cup;

	if ((unsigned)SCARG(uap, domain) >= __arraycount(darwin_to_native_af))
		return (EPROTONOSUPPORT);

	SCARG(&cup, domain) = darwin_to_native_af[SCARG(uap, domain)];
	SCARG(&cup, type) = SCARG(uap, type);
	SCARG(&cup, protocol) = SCARG(uap, protocol);

	return compat_30_sys_socket(l, &cup, retval);
}
Beispiel #4
0
/*
 * Return the process group ID of the session leader (session ID)
 * for the specified process.
 */
int
sys_getsid(struct lwp *l, const struct sys_getsid_args *uap, register_t *retval)
{
	/* {
		syscalldarg(pid_t) pid;
	} */
	pid_t pid = SCARG(uap, pid);
	struct proc *p;
	int error = 0;

	mutex_enter(proc_lock);
	if (pid == 0)
		*retval = l->l_proc->p_session->s_sid;
	else if ((p = proc_find(pid)) != NULL)
		*retval = p->p_session->s_sid;
	else
		error = ESRCH;
	mutex_exit(proc_lock);

	return error;
}
Beispiel #5
0
int
svr4_ustat(struct lwp *l, const struct svr4_ustat_args *uap, register_t *retval)
{
	/* {
		syscallarg(svr4_dev_t)		dev;
		syscallarg(struct svr4_ustat *) name;
	} */
	struct svr4_ustat	us;
	int			error;

	memset(&us, 0, sizeof us);

	/*
         * XXX: should set f_tfree and f_tinode at least
         * How do we translate dev -> fstat? (and then to svr4_ustat)
         */
	if ((error = copyout(&us, SCARG(uap, name), sizeof us)) != 0)
		return (error);

	return 0;
}
Beispiel #6
0
/*
 * Once more: only a signal conversion is needed.
 * Note: also used as sys_rt_queueinfo.  The info field is ignored.
 */
int
linux_sys_rt_queueinfo(struct lwp *l, const struct linux_sys_rt_queueinfo_args *uap, register_t *retval)
{
	/*
		syscallarg(int) pid;
		syscallarg(int) signum;
		syscallarg(linix_siginfo_t *) uinfo;
	*/
	int error;
	linux_siginfo_t info;

	error = copyin(SCARG(uap, uinfo), &info, sizeof(info));
	if (error)
		return error;
	if (info.lsi_code >= 0)
		return EPERM;

	/* XXX To really implement this we need to	*/
	/* XXX keep a list of queued signals somewhere.	*/
	return (linux_sys_kill(l, (const void *)uap, retval));
}
Beispiel #7
0
int
netbsd32_sigqueueinfo(struct lwp *l,
    const struct netbsd32_sigqueueinfo_args *uap, register_t *retval)
{
	/* {
		syscallarg(pid_t) pid;
		syscallarg(const netbsd32_siginfop_t) info;
	} */
	struct __ksiginfo32 ksi32;
	ksiginfo_t ksi;
	int error;

	if ((error = copyin(SCARG_P32(uap, info), &ksi32,
	    sizeof(ksi32))) != 0)
		return error;

	KSI_INIT(&ksi);
	netbsd32_ksi32_to_ksi(&ksi.ksi_info, &ksi32);

	return kill1(l, SCARG(uap, pid), &ksi, retval);
}
int
ultrix_sys_execve(struct lwp *l, const struct ultrix_sys_execve_args *uap, register_t *retval)
{
	/* {
		syscallarg(const char *) path;
		syscallarg(char **) argv;
		syscallarg(char **) envp;
	} */
	struct sys_execve_args ap;

	SCARG(&ap, path) = SCARG(uap, path);
	SCARG(&ap, argp) = SCARG(uap, argp);
	SCARG(&ap, envp) = SCARG(uap, envp);

	return sys_execve(l, &ap, retval);
}
Beispiel #9
0
int
netbsd32_sigaction(struct lwp *l, const struct netbsd32_sigaction_args *uap, register_t *retval)
{
	/* {
		syscallarg(int) signum;
		syscallarg(const netbsd32_sigactionp_t) nsa;
		syscallarg(netbsd32_sigactionp_t) osa;
	} */
	struct sigaction nsa, osa;
	struct netbsd32_sigaction13 *sa32p, sa32;
	int error;

	if (SCARG_P32(uap, nsa)) {
		sa32p = SCARG_P32(uap, nsa);
		if (copyin(sa32p, &sa32, sizeof(sa32)))
			return EFAULT;
		nsa.sa_handler = (void *)NETBSD32PTR64(sa32.netbsd32_sa_handler);
		memset(&nsa.sa_mask, 0, sizeof(nsa.sa_mask));
		nsa.sa_mask.__bits[0] = sa32.netbsd32_sa_mask;
		nsa.sa_flags = sa32.netbsd32_sa_flags;
	}
	error = sigaction1(l, SCARG(uap, signum),
			   SCARG_P32(uap, nsa) ? &nsa : 0,
			   SCARG_P32(uap, osa) ? &osa : 0,
			   NULL, 0);

	if (error)
		return (error);

	if (SCARG_P32(uap, osa)) {
		NETBSD32PTR32(sa32.netbsd32_sa_handler, osa.sa_handler);
		sa32.netbsd32_sa_mask = osa.sa_mask.__bits[0];
		sa32.netbsd32_sa_flags = osa.sa_flags;
		sa32p = SCARG_P32(uap, osa);
		if (copyout(&sa32, sa32p, sizeof(sa32)))
			return EFAULT;
	}

	return (0);
}
Beispiel #10
0
int
linux32_sys_fstat64(struct lwp *l, const struct linux32_sys_fstat64_args *uap, register_t *retval)
{
	/* {
	        syscallarg(int) fd;
	        syscallarg(linux32_stat64p) sp;
	} */
	int error;
	struct stat st;
	struct linux32_stat64 st32;
	struct linux32_stat64 *st32p;

	error = do_sys_fstat(SCARG(uap, fd), &st);
	if (error != 0)
		return error;

	linux32_from_stat(&st, &st32);

	st32p = SCARG_P32(uap, sp);

	return copyout(&st32, st32p, sizeof(*st32p));
}
Beispiel #11
0
int
linux_sys_modify_ldt(struct proc *p, void *v, register_t *retval)
{
	struct linux_sys_modify_ldt_args /* {
		syscallarg(int) func;
		syscallarg(void *) ptr;
		syscallarg(size_t) bytecount;
	} */ *uap = v;

	switch (SCARG(uap, func)) {
#ifdef USER_LDT
	case 0:
		return (linux_read_ldt(p, uap, retval));

	case 1:
		return (linux_write_ldt(p, uap, retval));
#endif /* USER_LDT */

	default:
		return (ENOSYS);
	}
}
int
ultrix_sys_setpgrp(struct lwp *l, const struct ultrix_sys_setpgrp_args *uap, register_t *retval)
{
	struct proc *p = l->l_proc;
	struct sys_setpgid_args ap;

	SCARG(&ap, pid) = SCARG(uap, pid);
	SCARG(&ap, pgid) = SCARG(uap, pgid);
	/*
	 * difference to our setpgid call is to include backwards
	 * compatibility to pre-setsid() binaries. Do setsid()
	 * instead of setpgid() in those cases where the process
	 * tries to create a new session the old way.
	 */
	if (!SCARG(&ap, pgid) &&
	    (!SCARG(&ap, pid) || SCARG(&ap, pid) == p->p_pid))
		return sys_setsid(l, &ap, retval);
	else
		return sys_setpgid(l, &ap, retval);
}
/*
 * The following three functions fiddle with a process' signal mask.
 * Convert the signal masks because of the different signal
 * values for Linux. The need for this is the reason why
 * they are here, and have not been mapped directly.
 */
int
linux_sys_sigsetmask(struct lwp *l, const struct linux_sys_sigsetmask_args *uap, register_t *retval)
{
    /* {
    	syscallarg(linux_old_sigset_t) mask;
    } */
    sigset_t nbss, obss;
    linux_old_sigset_t nlss, olss;
    struct proc *p = l->l_proc;
    int error;

    nlss = SCARG(uap, mask);
    linux_old_to_native_sigset(&nbss, &nlss);
    mutex_enter(p->p_lock);
    error = sigprocmask1(l, SIG_SETMASK, &nbss, &obss);
    mutex_exit(p->p_lock);
    if (error)
        return (error);
    native_to_linux_old_sigset(&olss, &obss);
    *retval = olss;
    return (0);
}
int
netbsd32___clock_getres50(struct lwp *l, const struct netbsd32___clock_getres50_args *uap, register_t *retval)
{
	/* {
		syscallarg(netbsd32_clockid_t) clock_id;
		syscallarg(netbsd32_timespecp_t) tp;
	} */
	struct netbsd32_timespec ts32;
	struct timespec ts;
	int error = 0;

	error = clock_getres1(SCARG(uap, clock_id), &ts);
	if (error != 0)
		return error;

	if (SCARG_P32(uap, tp)) {
		netbsd32_from_timespec(&ts, &ts32);
		error = copyout(&ts32, SCARG_P32(uap, tp), sizeof(ts32));
	}

	return error;
}
Beispiel #15
0
int
kldload(struct proc* p, struct kldload_args* uap)
{
    char* filename = NULL, *modulename;
    linker_file_t lf;
    int error = 0;

    p->p_retval[0] = -1;

    if (securelevel > 0)
	return EPERM;

    if (error = suser(p->p_ucred, &p->p_acflag))
	return error;

    filename = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
    if (error = copyinstr(SCARG(uap, file), filename, MAXPATHLEN, NULL))
	goto out;

    /* Can't load more than one module with the same name */
    modulename = rindex(filename, '/');
    if (modulename == NULL)
	modulename = filename;
    if (linker_find_file_by_name(modulename)) {
	error = EEXIST;
	goto out;
    }

    if (error = linker_load_file(filename, &lf))
	goto out;

    lf->userrefs++;
    p->p_retval[0] = lf->id;

out:
    if (filename)
	free(filename, M_TEMP);
    return error;
}
int
linux_sys_sched_setaffinity(struct lwp *l, const struct linux_sys_sched_setaffinity_args *uap, register_t *retval)
{
	/* {
		syscallarg(linux_pid_t) pid;
		syscallarg(unsigned int) len;
		syscallarg(unsigned long *) mask;
	} */
	proc_t *p;

	/* XXX: Pointless check.  TODO: Actually implement this. */
	mutex_enter(proc_lock);
	p = proc_find(SCARG(uap, pid));
	mutex_exit(proc_lock);
	if (p == NULL) {
		return ESRCH;
	}

	/* Let's ignore it */
	DPRINTF(("%s\n", __func__));
	return 0;
}
Beispiel #17
0
int
linux32_sys_rt_sigsuspend(struct lwp *l, const struct linux32_sys_rt_sigsuspend_args *uap, register_t *retval)
{
	/* {
		syscallarg(linux32_sigsetp_t) unewset;
                syscallarg(netbsd32_size_t) sigsetsize;
	} */
	linux32_sigset_t lss;
	sigset_t bss;
	int error;

	if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t))
		return EINVAL;

	if ((error = copyin(SCARG_P32(uap, unewset), 
	    &lss, sizeof(linux32_sigset_t))) != 0)
		return error;

	linux32_to_native_sigset(&bss, &lss);

	return sigsuspend1(l, &bss);
}
Beispiel #18
0
/*
 * Execve(2). Just check the alternate emulation path, and pass it on
 * to the regular execve().
 */
int
linux_sys_execve(struct proc *p, void *v, register_t *retval)
{
	struct linux_sys_execve_args /* {
		syscallarg(char *) path;
		syscallarg(char **) argv;
		syscallarg(char **) envp;
        } */ *uap = v;
	struct sys_execve_args ap;
	caddr_t sg;

	sg = stackgap_init(p->p_emul);
	LINUX_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));

	SCARG(&ap, path) = SCARG(uap, path);
	SCARG(&ap, argp) = SCARG(uap, argp);
	SCARG(&ap, envp) = SCARG(uap, envp);

	return (sys_execve(p, &ap, retval));
}
Beispiel #19
0
int
compat_13_sys_sigreturn(struct lwp *l, void *v, register_t *retval)
{
	struct compat_13_sys_sigreturn_args /* {
		syscallarg(struct sigcontext13 *) sigcntxp;
	} */ *uap = v;
	struct proc *p = l->l_proc;
	struct trapframe *scf;
	struct sigcontext13 *ucntx;
	struct sigcontext13 ksc;
	sigset_t mask;

	scf = l->l_addr->u_pcb.framep;
	ucntx = SCARG(uap, sigcntxp);
	if (copyin((caddr_t)ucntx, (caddr_t)&ksc, sizeof(struct sigcontext)))
		return EINVAL;

	/* Compatibility mode? */
	if ((ksc.sc_ps & (PSL_IPL | PSL_IS)) ||
	    ((ksc.sc_ps & (PSL_U | PSL_PREVU)) != (PSL_U | PSL_PREVU)) ||
	    (ksc.sc_ps & PSL_CM)) {
		return (EINVAL);
	}
	if (ksc.sc_onstack & SS_ONSTACK)
		p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
	else
		p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK;

	native_sigset13_to_sigset(&ksc.sc_mask, &mask);
	(void) sigprocmask1(p, SIG_SETMASK, &mask, 0);

	scf->fp = ksc.sc_fp;
	scf->ap = ksc.sc_ap;
	scf->pc = ksc.sc_pc;
	scf->sp = ksc.sc_sp;
	scf->psl = ksc.sc_ps;
	return (EJUSTRETURN);
}
Beispiel #20
0
int
sys__lwp_wakeup(struct lwp *l, const struct sys__lwp_wakeup_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(lwpid_t) target;
	} */
	struct lwp *t;
	struct proc *p;
	int error;

	p = l->l_proc;
	mutex_enter(p->p_lock);

	if ((t = lwp_find(p, SCARG(uap, target))) == NULL) {
		mutex_exit(p->p_lock);
		return ESRCH;
	}

	lwp_lock(t);
	t->l_flag |= (LW_CANCELLED | LW_UNPARKED);

	if (t->l_stat != LSSLEEP) {
		lwp_unlock(t);
		error = ENODEV;
	} else if ((t->l_flag & LW_SINTR) == 0) {
		lwp_unlock(t);
		error = EBUSY;
	} else {
		/* Wake it up.  lwp_unsleep() will release the LWP lock. */
		lwp_unsleep(t, true);
		error = 0;
	}

	mutex_exit(p->p_lock);

	return error;
}
Beispiel #21
0
/* Delete a POSIX realtime timer */
int
sys_timer_delete(struct lwp *l, const struct sys_timer_delete_args *uap,
    register_t *retval)
{
	/* {
		syscallarg(timer_t) timerid;
	} */
	struct proc *p = l->l_proc;
	timer_t timerid;
	struct ptimers *pts;
	struct ptimer *pt, *ptn;

	timerid = SCARG(uap, timerid);
	pts = p->p_timers;
	
	if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX)
		return (EINVAL);

	mutex_spin_enter(&timer_lock);
	if ((pt = pts->pts_timers[timerid]) == NULL) {
		mutex_spin_exit(&timer_lock);
		return (EINVAL);
	}
	if (CLOCK_VIRTUAL_P(pt->pt_type)) {
		if (pt->pt_active) {
			ptn = LIST_NEXT(pt, pt_list);
			LIST_REMOVE(pt, pt_list);
			for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list))
				timespecadd(&pt->pt_time.it_value,
				    &ptn->pt_time.it_value,
				    &ptn->pt_time.it_value);
			pt->pt_active = 0;
		}
	}
	itimerfree(pts, timerid);

	return (0);
}
Beispiel #22
0
int
linux_sys_unlinkat(struct lwp *l, const struct linux_sys_unlinkat_args *uap, register_t *retval)
{
	/* {
		syscallarg(int) fd;
		syscallarg(const char *) path;
		syscallarg(int) flag;
	} */
	struct sys_unlinkat_args ua;
	int error;

	SCARG(&ua, fd) = SCARG(uap, fd);
	SCARG(&ua, path) = SCARG(uap, path);
	SCARG(&ua, flag) = linux_to_bsd_atflags(SCARG(uap, flag));

	error = sys_unlinkat(l, &ua, retval);
	if (error == EPERM)
		error = linux_unlink_dircheck(SCARG(uap, path));

	return error;
}
int
linux_sys_sched_getscheduler(struct lwp *l, const struct linux_sys_sched_getscheduler_args *uap, register_t *retval)
{
	/* {
		syscallarg(linux_pid_t) pid;
	} */
	int error, policy;

	*retval = -1;

	error = do_sched_getparam(SCARG(uap, pid), 0, &policy, NULL);
	if (error)
		goto out;

	error = sched_native2linux(policy, NULL, &policy, NULL);
	if (error)
		goto out;

	*retval = policy;

 out:
	return error;
}
static int
filemon_wrapper_execve(struct lwp * l, struct sys_execve_args * uap,
    register_t * retval)
{
	char fname[MAXPATHLEN];
	int ret;
	int error;
	size_t done;
	struct filemon *filemon;
	
	error = copyinstr(SCARG(uap, path), fname, sizeof(fname), &done);

	if ((ret = sys_execve(l, uap, retval)) == EJUSTRETURN && error == 0) {
		filemon = filemon_lookup(curproc);

		if (filemon) {
			filemon_printf(filemon, "E %d %s\n",
			    curproc->p_pid, fname);
			rw_exit(&filemon->fm_mtx);
		}
	}
	return (ret);
}
int
linux32_sys_setrlimit(struct lwp *l, const struct linux32_sys_setrlimit_args *uap, register_t *retval)
{
	/* {
		syscallarg(int) which;
		syscallarg(netbsd32_orlimitp_t) rlp;
	} */
	struct rlimit rl;
	struct orlimit orl;
	int error;
	int which;

	if ((error = copyin(SCARG_P32(uap, rlp), &orl, sizeof(orl))) != 0)
		return error;

	which = linux_to_bsd_limit(SCARG(uap, which));
	if (which < 0)
		return -which;

	linux32_to_bsd_rlimit(&rl, &orl);

	return dosetrlimit(l, l->l_proc, which, &rl);
}
Beispiel #26
0
int
sys_shmdt(struct proc *p, void *v, register_t *retval)
{
	struct sys_shmdt_args /* {
		syscallarg(const void *) shmaddr;
	} */ *uap = v;
	struct shmmap_head *shmmap_h;
	struct shmmap_state *shmmap_s;
	int i;

	shmmap_h = (struct shmmap_head *)p->p_vmspace->vm_shm;
	if (shmmap_h == NULL)
		return (EINVAL);

	for (i = 0, shmmap_s = shmmap_h->state; i < shmmap_h->shmseg;
	    i++, shmmap_s++)
		if (shmmap_s->shmid != -1 &&
		    shmmap_s->va == (vaddr_t)SCARG(uap, shmaddr))
			break;
	if (i == shmmap_h->shmseg)
		return (EINVAL);
	return (shm_delete_mapping(p->p_vmspace, shmmap_s));
}
Beispiel #27
0
/* ARGSUSED */
int
sys_setgid(struct proc *p, void *v, register_t *retval)
{
	struct sys_setgid_args /* {
		syscallarg(gid_t) gid;
	} */ *uap = v;
	struct pcred *pc = p->p_cred;
	gid_t gid;
	int error;

	gid = SCARG(uap, gid);

	if (pc->pc_ucred->cr_gid == gid &&
	    pc->p_rgid == gid &&
	    pc->p_svgid == gid)
		return (0);

	if (gid != pc->p_rgid &&
	    gid != pc->p_svgid &&
	    gid != pc->pc_ucred->cr_gid &&
	    (error = suser(p, 0)))
		return (error);

	if (gid == pc->pc_ucred->cr_gid ||
	    suser(p, 0) == 0) {
		pc->p_rgid = gid;
		pc->p_svgid = gid;
	}

	/*
	 * Copy credentials so other references do not see our changes.
	 */
	pc->pc_ucred = crcopy(pc->pc_ucred);
	pc->pc_ucred->cr_gid = gid;
	atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID);
	return (0);
}
int
linux32_sys_fadvise64_64(struct lwp *l,
    const struct linux32_sys_fadvise64_64_args *uap, register_t *retval)
{
	/* {
		syscallarg(int) fd;
		syscallarg(uint32_t) offlo;
		syscallarg(uint32_t) offhi;
		syscallarg(uint32_t) lenlo;
		syscallarg(uint32_t) lenhi;
		syscallarg(int) advice;
	} */
	off_t off = ((off_t)SCARG(uap, offhi) << 32) + SCARG(uap, offlo);
	off_t len = ((off_t)SCARG(uap, lenhi) << 32) + SCARG(uap, lenlo);

	return do_posix_fadvise(SCARG(uap, fd), off,
	    len, linux_to_bsd_posix_fadv(SCARG(uap, advice)));
}
int
linux_semget(struct lwp *l, const struct linux_sys_ipc_args *uap, register_t *retval)
{
	/* {
		syscallarg(int) what;
		syscallarg(int) a1;
		syscallarg(int) a2;
		syscallarg(int) a3;
		syscallarg(void *) ptr;
	} */
	struct sys_semget_args bsa;

	SCARG(&bsa, key) = (key_t)SCARG(uap, a1);
	SCARG(&bsa, nsems) = SCARG(uap, a2);
	SCARG(&bsa, semflg) = SCARG(uap, a3);

	return sys_semget(l, &bsa, retval);
}
int
linux_semop(struct lwp *l, const struct linux_sys_ipc_args *uap, register_t *retval)
{
	/* {
		syscallarg(int) what;
		syscallarg(int) a1;
		syscallarg(int) a2;
		syscallarg(int) a3;
		syscallarg(void *) ptr;
	} */
	struct sys_semop_args bsa;

	SCARG(&bsa, semid) = SCARG(uap, a1);
	SCARG(&bsa, sops) = (struct sembuf *)SCARG(uap, ptr);
	SCARG(&bsa, nsops) = SCARG(uap, a2);

	return sys_semop(l, &bsa, retval);
}