DPRINTF(("break(1): old %x new %x diff %x\n", old, new, diff));
DPRINTF(("break(1): old %lx new %lx diff %x\n", old, new, diff));
static struct proc *svr4_pfind __P((pid_t pid));static int svr4_mknod __P((struct proc *, register_t *, char *,			   svr4_mode_t, svr4_dev_t));intsvr4_sys_wait(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_wait_args *uap = v;	struct sys_wait4_args w4;	int error;	size_t sz = sizeof(*SCARG(&w4, status));	SCARG(&w4, rusage) = NULL;	SCARG(&w4, options) = 0;	if (SCARG(uap, status) == NULL) {		caddr_t sg = stackgap_init(p->p_emul);		SCARG(&w4, status) = stackgap_alloc(&sg, sz);	}	else		SCARG(&w4, status) = SCARG(uap, status);	SCARG(&w4, pid) = WAIT_ANY;	if ((error = sys_wait4(p, &w4, retval)) != 0)		return error;	/*	 * It looks like wait(2) on svr4/solaris/2.4 returns	 * the status in retval[1], and the pid on retval[0].	 * NB: this can break if register_t stops being an int.	 */	return copyin(SCARG(&w4, status), &retval[1], sz);}intsvr4_sys_execv(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_execv_args *uap = v;	struct sys_execve_args ex;	caddr_t sg = stackgap_init(p->p_emul);	SVR4_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));	SCARG(&ex, path) = SCARG(uap, path);	SCARG(&ex, argp) = SCARG(uap, argp);	SCARG(&ex, envp) = NULL;	return sys_execve(p, &ex, retval);}intsvr4_sys_execve(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct sys_execve_args *uap = v;	caddr_t sg = stackgap_init(p->p_emul);	SVR4_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));	return sys_execve(p, uap, retval);}intsvr4_sys_time(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_time_args *uap = v;	int error = 0;	struct timeval tv;	microtime(&tv);	if (SCARG(uap, t))		error = copyout(&tv.tv_sec, SCARG(uap, t),				sizeof(*(SCARG(uap, t))));	*retval = (int) tv.tv_sec;	return error;}/* * Read SVR4-style directory entries.  We suck them into kernel space so * that they can be massaged before being copied out to user code.  Like * SunOS, we squish out `empty' entries. * * This is quite ugly, but what do you expect from compatibility code? */intsvr4_sys_getdents(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_getdents_args *uap = v;	register struct dirent *bdp;	struct vnode *vp;	caddr_t inp, buf;	/* BSD-format */	int len, reclen;	/* BSD-format */	caddr_t outp;		/* SVR4-format */	int resid, svr4_reclen;	/* SVR4-format */	struct file *fp;	struct uio auio;	struct iovec aiov;	struct svr4_dirent idb;	off_t off;		/* true file offset */	int buflen, error, eofflag;	u_long *cookiebuf, *cookie;	int ncookies;	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)		return (error);	if ((fp->f_flag & FREAD) == 0)		return (EBADF);	vp = (struct vnode *)fp->f_data;	if (vp->v_type != VDIR)	/* XXX  vnode readdir op should do this */		return (EINVAL);	buflen = min(MAXBSIZE, SCARG(uap, nbytes));	buf = malloc(buflen, M_TEMP, M_WAITOK);	ncookies = buflen / 16;	cookiebuf = malloc(ncookies * sizeof(*cookiebuf), M_TEMP, M_WAITOK);	VOP_LOCK(vp);	off = fp->f_offset;again:	aiov.iov_base = buf;	aiov.iov_len = buflen;	auio.uio_iov = &aiov;	auio.uio_iovcnt = 1;	auio.uio_rw = UIO_READ;	auio.uio_segflg = UIO_SYSSPACE;	auio.uio_procp = p;	auio.uio_resid = buflen;	auio.uio_offset = off;	/*         * First we read into the malloc'ed buffer, then         * we massage it into user space, one record at a time.         */	error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, cookiebuf,	    ncookies);	if (error)		goto out;	inp = buf;	outp = SCARG(uap, buf);	resid = SCARG(uap, nbytes);	if ((len = buflen - auio.uio_resid) == 0)		goto eof;	for (cookie = cookiebuf; len > 0; len -= reclen) {		bdp = (struct dirent *)inp;		reclen = bdp->d_reclen;		if (reclen & 3)			panic("svr4_getdents");		off = *cookie++;	/* each entry points to the next */		if (bdp->d_fileno == 0) {			inp += reclen;	/* it is a hole; squish it out */			continue;		}		svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);		if (reclen > len || resid < svr4_reclen) {			/* entry too big for buffer, so just stop */			outp++;			break;		}		/*		 * Massage in place to make a SVR4-shaped dirent (otherwise		 * we have to worry about touching user memory outside of		 * the copyout() call).		 */		idb.d_ino = (svr4_ino_t)bdp->d_fileno;		idb.d_off = (svr4_off_t)off;		idb.d_reclen = (u_short)svr4_reclen;		strcpy(idb.d_name, bdp->d_name);		if ((error = copyout((caddr_t)&idb, outp, svr4_reclen)))			goto out;		/* advance past this real entry */		inp += reclen;		/* advance output past SVR4-shaped entry */		outp += svr4_reclen;		resid -= svr4_reclen;	}	/* if we squished out the whole block, try again */	if (outp == SCARG(uap, buf))		goto again;	fp->f_offset = off;	/* update the vnode offset */eof:	*retval = SCARG(uap, nbytes) - resid;out:	VOP_UNLOCK(vp);	free(cookiebuf, M_TEMP);	free(buf, M_TEMP);	return error;}intsvr4_sys_mmap(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_mmap_args	*uap = v;	struct sys_mmap_args	 mm;	caddr_t 		 rp;#define _MAP_NEW	0x80000000	/*         * Verify the arguments.         */	if (SCARG(uap, prot) & ~(PROT_READ | PROT_WRITE | PROT_EXEC))		return EINVAL;	/* XXX still needed? */	SCARG(&mm, prot) = SCARG(uap, prot);	SCARG(&mm, len) = SCARG(uap, len);	SCARG(&mm, flags) = SCARG(uap, flags) & ~_MAP_NEW;	SCARG(&mm, fd) = SCARG(uap, fd);	SCARG(&mm, addr) = SCARG(uap, addr);	SCARG(&mm, pos) = SCARG(uap, pos);	rp = (caddr_t) round_page(p->p_vmspace->vm_daddr + MAXDSIZ);	if ((SCARG(&mm, flags) & MAP_FIXED) == 0 &&	    SCARG(&mm, addr) != 0 && SCARG(&mm, addr) < rp)		SCARG(&mm, addr) = rp;	return sys_mmap(p, &mm, retval);}intsvr4_sys_fchroot(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_fchroot_args *uap = v;	struct filedesc	*fdp = p->p_fd;	struct vnode	*vp;	struct file	*fp;	int		 error;	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)		return error;	if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)		return error;	vp = (struct vnode *) fp->f_data;	VOP_LOCK(vp);	if (vp->v_type != VDIR)		error = ENOTDIR;	else		error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);	VOP_UNLOCK(vp);	if (error)		return error;	VREF(vp);	if (fdp->fd_rdir != NULL)		vrele(fdp->fd_rdir);	fdp->fd_rdir = vp;	return 0;}static intsvr4_mknod(p, retval, path, mode, dev)	struct proc *p;	register_t *retval;	char *path;	svr4_mode_t mode;	svr4_dev_t dev;{	caddr_t sg = stackgap_init(p->p_emul);	SVR4_CHECK_ALT_EXIST(p, &sg, path);	if (S_ISFIFO(mode)) {		struct sys_mkfifo_args ap;		SCARG(&ap, path) = path;		SCARG(&ap, mode) = mode;		return sys_mkfifo(p, &ap, retval);	} else {		struct sys_mknod_args ap;		SCARG(&ap, path) = path;		SCARG(&ap, mode) = mode;		SCARG(&ap, dev) = dev;		return sys_mknod(p, &ap, retval);	}}intsvr4_sys_mknod(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_mknod_args *uap = v;	return svr4_mknod(p, retval,			  SCARG(uap, path), SCARG(uap, mode), SCARG(uap, dev));}intsvr4_sys_xmknod(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_xmknod_args *uap = v;	return svr4_mknod(p, retval,			  SCARG(uap, path), SCARG(uap, mode), SCARG(uap, dev));}intsvr4_sys_vhangup(p, v, retval)	struct proc *p;	void *v;	register_t *retval;{	return 0;}intsvr4_sys_sysconfig(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_sysconfig_args *uap = v;	extern int	maxfiles;	switch (SCARG(uap, name)) {	case SVR4_CONFIG_UNUSED:		*retval = 0;		break;	case SVR4_CONFIG_NGROUPS:		*retval = NGROUPS_MAX;		break;	case SVR4_CONFIG_CHILD_MAX:		*retval = maxproc;		break;	case SVR4_CONFIG_OPEN_FILES:		*retval = maxfiles;		break;	case SVR4_CONFIG_POSIX_VER:		*retval = 198808;		break;	case SVR4_CONFIG_PAGESIZE:		*retval = NBPG;		break;	case SVR4_CONFIG_CLK_TCK:		*retval = 60;	/* should this be `hz', ie. 100? */		break;	case SVR4_CONFIG_XOPEN_VER:		*retval = 2;	/* XXX: What should that be? */		break;	case SVR4_CONFIG_PROF_TCK:		*retval = 60;	/* XXX: What should that be? */		break;	case SVR4_CONFIG_NPROC_CONF:		*retval = 1;	/* Only one processor for now */		break;	case SVR4_CONFIG_NPROC_ONLN:		*retval = 1;	/* And it better be online */		break;	case SVR4_CONFIG_AIO_LISTIO_MAX:	case SVR4_CONFIG_AIO_MAX:	case SVR4_CONFIG_AIO_PRIO_DELTA_MAX:		*retval = 0;	/* No aio support */		break;	case SVR4_CONFIG_DELAYTIMER_MAX:		*retval = 0;	/* No delaytimer support */		break;	case SVR4_CONFIG_MQ_OPEN_MAX:		*retval = msginfo.msgmni;		break;	case SVR4_CONFIG_MQ_PRIO_MAX:		*retval = 0;	/* XXX: Don't know */		break;	case SVR4_CONFIG_RTSIG_MAX:		*retval = 0;		break;	case SVR4_CONFIG_SEM_NSEMS_MAX:		*retval = seminfo.semmni;		break;	case SVR4_CONFIG_SEM_VALUE_MAX:		*retval = seminfo.semvmx;		break;	case SVR4_CONFIG_SIGQUEUE_MAX:		*retval = 0;	/* XXX: Don't know */		break;	case SVR4_CONFIG_SIGRT_MIN:	case SVR4_CONFIG_SIGRT_MAX:		*retval = 0;	/* No real time signals */		break;	case SVR4_CONFIG_TIMER_MAX:		*retval = 3;	/* XXX: real, virtual, profiling */		break;	case SVR4_CONFIG_PHYS_PAGES:		*retval = cnt.v_free_count;	/* XXX: free instead of total */		break;	case SVR4_CONFIG_AVPHYS_PAGES:		*retval = cnt.v_active_count;	/* XXX: active instead of avg */		break;	default:		return EINVAL;	}	return 0;}#define SVR4_RLIMIT_NOFILE	5	/* Other RLIMIT_* are the same */#define SVR4_RLIMIT_VMEM	6	/* Other RLIMIT_* are the same */#define SVR4_RLIM_NLIMITS	7intsvr4_sys_getrlimit(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_getrlimit_args *uap = v;	struct compat_43_sys_getrlimit_args ap;	if (SCARG(uap, which) >= SVR4_RLIM_NLIMITS)		return EINVAL;	if (SCARG(uap, which) == SVR4_RLIMIT_NOFILE)		SCARG(uap, which) = RLIMIT_NOFILE;	if (SCARG(uap, which) == SVR4_RLIMIT_VMEM)		SCARG(uap, which) = RLIMIT_RSS;	SCARG(&ap, which) = SCARG(uap, which);	SCARG(&ap, rlp) = SCARG(uap, rlp);	return compat_43_sys_getrlimit(p, &ap, retval);}intsvr4_sys_setrlimit(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_setrlimit_args *uap = v;	struct compat_43_sys_setrlimit_args ap;	if (SCARG(uap, which) >= SVR4_RLIM_NLIMITS)		return EINVAL;	if (SCARG(uap, which) == SVR4_RLIMIT_NOFILE)		SCARG(uap, which) = RLIMIT_NOFILE;	if (SCARG(uap, which) == SVR4_RLIMIT_VMEM)		SCARG(uap, which) = RLIMIT_RSS;	SCARG(&ap, which) = SCARG(uap, which);	SCARG(&ap, rlp) = SCARG(uap, rlp);	return compat_43_sys_setrlimit(p, uap, retval);}/* ARGSUSED */intsvr4_sys_break(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_break_args *uap = v;	register struct vmspace *vm = p->p_vmspace;	vm_offset_t     new, old;	int             rv;	register int    diff;	old = (vm_offset_t) vm->vm_daddr;	new = round_page(SCARG(uap, nsize));	diff = new - old;	DPRINTF(("break(1): old %x new %x diff %x\n", old, new, diff));	if (diff > p->p_rlimit[RLIMIT_DATA].rlim_cur)		return ENOMEM;	old = round_page(old + ctob(vm->vm_dsize));	DPRINTF(("break(2): dsize = %x ctob %x\n",		 vm->vm_dsize, ctob(vm->vm_dsize)));	diff = new - old;	DPRINTF(("break(3): old %x new %x diff %x\n", old, new, diff));	if (diff > 0) {		rv = vm_allocate(&vm->vm_map, &old, diff, FALSE);		if (rv != KERN_SUCCESS) {			uprintf("sbrk: grow failed, return = %d\n", rv);			return ENOMEM;		}		vm->vm_dsize += btoc(diff);	} else if (diff < 0) {		diff = -diff;		rv = vm_deallocate(&vm->vm_map, new, diff);		if (rv != KERN_SUCCESS) {			uprintf("sbrk: shrink failed, return = %d\n", rv);			return ENOMEM;		}		vm->vm_dsize -= btoc(diff);	}	return 0;}static __inline clock_ttimeval_to_clock_t(tv)	struct timeval *tv;{	return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz);}intsvr4_sys_times(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_times_args *uap = v;	int			 error;	struct tms		 tms;	struct timeval		 t;	struct rusage		*ru;	struct rusage		 r;	struct sys_getrusage_args 	 ga;	caddr_t sg = stackgap_init(p->p_emul);	ru = stackgap_alloc(&sg, sizeof(struct rusage));	SCARG(&ga, who) = RUSAGE_SELF;	SCARG(&ga, rusage) = ru;	error = sys_getrusage(p, &ga, retval);	if (error)		return error;	if ((error = copyin(ru, &r, sizeof r)) != 0)		return error;	tms.tms_utime = timeval_to_clock_t(&r.ru_utime);	tms.tms_stime = timeval_to_clock_t(&r.ru_stime);	SCARG(&ga, who) = RUSAGE_CHILDREN;	error = sys_getrusage(p, &ga, retval);	if (error)		return error;	if ((error = copyin(ru, &r, sizeof r)) != 0)		return error;	tms.tms_cutime = timeval_to_clock_t(&r.ru_utime);	tms.tms_cstime = timeval_to_clock_t(&r.ru_stime);	microtime(&t);	*retval = timeval_to_clock_t(&t);	return copyout(&tms, SCARG(uap, tp), sizeof(tms));}intsvr4_sys_ulimit(p, v, retval)	register struct proc *p;	void *v;	register_t *retval;{	struct svr4_sys_ulimit_args *uap = v;	switch (SCARG(uap, cmd)) {	case SVR4_GFILLIM:		*retval = p->p_rlimit[RLIMIT_FSIZE].rlim_cur / 512;		return 0;	case SVR4_SFILLIM:		{			int error;			struct sys_setrlimit_args srl;			struct rlimit krl;			caddr_t sg = stackgap_init(p->p_emul);			struct rlimit *url = (struct rlimit *) 				stackgap_alloc(&sg, sizeof *url);			krl.rlim_cur = SCARG(uap, newlimit) * 512;			krl.rlim_max = p->p_rlimit[RLIMIT_FSIZE].rlim_max;			error = copyout(&krl, url, sizeof(*url));			if (error)				return error;			srl.which = RLIMIT_FSIZE;			srl.rlp = url;			error = sys_setrlimit(p, &srl, retval);			if (error)				return error;			*retval = p->p_rlimit[RLIMIT_FSIZE].rlim_cur;			return 0;		}	case SVR4_GMEMLIM:		{			struct vmspace *vm = p->p_vmspace;			*retval = (long) vm->vm_daddr +				  p->p_rlimit[RLIMIT_DATA].rlim_cur;			return 0;		}	case SVR4_GDESLIM:		*retval = p->p_rlimit[RLIMIT_NOFILE].rlim_cur;		return 0;	default:		return ENOSYS;	}}static struct proc *svr4_pfind(pid)	pid_t pid;{	struct proc *p;	/* look in the live processes */	if ((p = pfind(pid)) != NULL)		return p;	/* look in the zombies */	for (p = zombproc.lh_first; p != 0; p = p->p_list.le_next)		if (p->p_pid == pid)			return p;	return NULL;}