ibcs2_misc.c revision 3584
1/*-
2 * Copyright (c) 1994 S�ren Schmidt
3 * Copyright (c) 1994 Sean Eric Fagan
4 * All rights reserved.
5 *
6 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer
14 *    in this position and unchanged.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by the University of
21 *	California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 *	$Id: ibcs2_misc.c,v 1.16 1994/10/13 23:10:58 sos Exp $
39 */
40
41#include <i386/ibcs2/ibcs2.h>
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/proc.h>
45#include <sys/exec.h>
46#include <sys/sysent.h>
47#include <sys/ioctl.h>
48#include <sys/resource.h>
49#include <sys/resourcevar.h>
50#include <sys/stat.h>
51#include <sys/time.h>
52#include <sys/times.h>
53#include <sys/unistd.h>
54#include <sys/wait.h>
55#include <vm/vm.h>
56#include <machine/cpu.h>
57#include <machine/psl.h>
58#include <machine/reg.h>
59
60int ibcs2_trace = 0;
61
62struct ibcs2_traceemu_args {
63	int options;
64};
65
66int
67ibcs2_traceemu(struct proc *p, struct ibcs2_traceemu_args *args, int *retval)
68{
69	*retval = ibcs2_trace;
70	ibcs2_trace = args->options;
71	return 0;
72}
73
74int
75ibcs2_access(struct proc *p, void *args, int *retval)
76{
77	if (ibcs2_trace & IBCS2_TRACE_MISC)
78		printf("IBCS2: 'access'\n");
79	return access(p, args, retval);
80}
81
82struct ibcs2_alarm_args {
83	unsigned int secs;
84};
85
86int
87ibcs2_alarm(struct proc *p, struct ibcs2_alarm_args *args, int *retval)
88{
89	extern struct timeval time;
90	struct itimerval it, oit;
91	int s;
92
93	if (ibcs2_trace & IBCS2_TRACE_MISC)
94		printf("IBCS2: 'alarm' secs=%d\n", args->secs);
95	it.it_value.tv_sec = (long)args->secs;
96	it.it_value.tv_usec = 0;
97	it.it_interval.tv_sec = 0;
98	it.it_interval.tv_usec = 0;
99	s = splclock();
100	oit = p->p_realtimer;
101	if (timerisset(&oit.it_value))
102		if (timercmp(&oit.it_value, &time, <))
103			timerclear(&oit.it_value);
104		else
105			timevalsub(&oit.it_value, &time);
106	splx(s);
107	if (itimerfix(&it.it_value) || itimerfix(&it.it_interval))
108		return EINVAL;
109	s = splclock();
110	untimeout(realitexpire, (caddr_t)p);
111	if (timerisset(&it.it_value)) {
112		timevaladd(&it.it_value, &time);
113		timeout(realitexpire, (caddr_t)p, hzto(&it.it_value));
114	}
115	p->p_realtimer = it;
116	splx(s);
117	if (oit.it_value.tv_usec)
118		oit.it_value.tv_sec++;
119	*retval = oit.it_value.tv_sec;
120	return 0;
121}
122
123struct ibcs2_break_args {
124  	char *dsend;
125};
126
127int
128ibcs2_break(struct proc *p, struct ibcs2_break_args *args, int *retval)
129{
130	struct vmspace *vm = p->p_vmspace;
131	vm_offset_t new, old;
132	int rv, diff;
133	extern int swap_pager_full;
134
135	if (ibcs2_trace & IBCS2_TRACE_MISC)
136		printf("IBCS2: 'break' dsend=%x\n",
137			(unsigned int)args->dsend);
138
139	if ((vm_offset_t)args->dsend < (vm_offset_t)vm->vm_daddr)
140		return EINVAL;
141	if (((caddr_t)args->dsend - (caddr_t)vm->vm_daddr)
142	    > p->p_rlimit[RLIMIT_DATA].rlim_cur)
143		return ENOMEM;
144
145	old = round_page((vm_offset_t)vm->vm_daddr) + ctob(vm->vm_dsize);
146	new = round_page((vm_offset_t)args->dsend);
147
148	diff = new - old;
149	if (diff > 0) {
150		if (swap_pager_full) {
151			return ENOMEM;
152		}
153		rv = vm_allocate(&vm->vm_map, &old, diff, FALSE);
154		if (rv != KERN_SUCCESS) {
155			return ENOMEM;
156		}
157		vm->vm_dsize += btoc(diff);
158	}
159	else if (diff < 0) {
160		diff = -diff;
161		rv = vm_deallocate(&vm->vm_map, new, diff);
162		if (rv != KERN_SUCCESS)
163			return ENOMEM;
164		vm->vm_dsize -= btoc(diff);
165	}
166	return 0;
167}
168
169int
170ibcs2_chdir(struct proc *p, void *args, int *retval)
171{
172	if (ibcs2_trace & IBCS2_TRACE_MISC)
173		printf("IBCS2: 'chdir'\n");
174	return chdir(p, args, retval);
175}
176
177int
178ibcs2_chmod(struct proc *p, void *args, int *retval)
179{
180	if (ibcs2_trace & IBCS2_TRACE_MISC)
181		printf("IBCS2: 'chmod'\n");
182	return chmod(p, args, retval);
183}
184
185int
186ibcs2_chown(struct proc *p, void *args, int *retval)
187{
188	if (ibcs2_trace & IBCS2_TRACE_MISC)
189		printf("IBCS2: 'chown'\n");
190	return chown(p, args, retval);
191}
192
193int
194ibcs2_chroot(struct proc *p, void *args, int *retval)
195{
196	if (ibcs2_trace & IBCS2_TRACE_MISC)
197		printf("IBCS2: 'chroot'\n");
198	return chroot(p, args, retval);
199}
200
201struct ibcs2_close_args {
202	int fd;
203};
204
205int
206ibcs2_close(struct proc *p, struct ibcs2_close_args *args, int *retval)
207{
208	if (ibcs2_trace & IBCS2_TRACE_MISC)
209		printf("IBCS2: 'close' fd=%d\n", args->fd);
210	return close(p, args, retval);
211}
212
213struct exec_args {
214	char *name;
215	char **argv;
216};
217
218int
219ibcs2_exec(struct proc *p, struct exec_args *args, int *retval)
220{
221	struct execve_args {
222		char *name;
223		char **argv;
224		char **envp;
225	} execve_args;
226
227	if (ibcs2_trace & IBCS2_TRACE_MISC)
228		printf("IBCS2: 'exec' name=%s\n", args->name);
229	execve_args.name = args->name;
230	execve_args.argv = args->argv;
231	execve_args.envp = 0;
232	return execve(p, &execve_args, retval);
233}
234
235struct ibcs2_exece_args {
236		char *name;
237		char **argv;
238		char **envp;
239};
240
241int
242ibcs2_exece(struct proc *p, struct ibcs2_exece_args *args, int *retval)
243{
244	if (ibcs2_trace & IBCS2_TRACE_MISC)
245		printf("IBCS2: 'exece' name=%s\n", args->name);
246	return execve(p, args, retval);
247}
248
249int
250ibcs2_exit(struct proc *p, void *args, int *retval)
251{
252	if (ibcs2_trace & IBCS2_TRACE_MISC)
253		printf("IBCS2: 'exit'\n");
254	return exit(p, args, retval);
255}
256
257int
258ibcs2_fork(struct proc *p, void *args, int *retval)
259{
260	if (ibcs2_trace & IBCS2_TRACE_MISC)
261		printf("IBCS2: 'fork'\n");
262	return fork(p, args, retval);
263}
264
265int
266ibcs2_fsync(struct proc *p, void *args, int *retval)
267{
268	if (ibcs2_trace & IBCS2_TRACE_MISC)
269		printf("IBCS2: 'fsync'\n");
270	return fsync(p, args, retval);
271}
272
273int
274ibcs2_getgid(struct proc *p, void *args, int *retval)
275{
276	if (ibcs2_trace & IBCS2_TRACE_MISC)
277		printf("IBCS2: 'getgid'\n");
278	return getgid(p, args, retval);
279}
280
281struct ibcs2_getgroups_args {
282	int gidsetsize;
283	ibcs2_gid_t *gidset;
284};
285
286int
287ibcs2_getgroups(struct proc *p, struct ibcs2_getgroups_args *args, int *retval)
288{
289	struct getgroups_args {
290		u_int	gidsetsize;
291		gid_t	*gidset;
292	} tmp;
293	ibcs2_gid_t *ibcs2_gidset;
294	int i, error;
295
296	if (ibcs2_trace & IBCS2_TRACE_MISC)
297		printf("IBCS2: 'getgroups'\n");
298
299	tmp.gidsetsize = args->gidsetsize;
300	tmp.gidset = (gid_t *)UA_ALLOC();
301	ibcs2_gidset = (ibcs2_gid_t *)&tmp.gidset[NGROUPS_MAX];
302	if (error = getgroups(p, &tmp, retval))
303		return error;
304	for (i = 0; i < retval[0]; i++)
305		ibcs2_gidset[i] = (ibcs2_gid_t)tmp.gidset[i];
306	return copyout((caddr_t)ibcs2_gidset, (caddr_t)args->gidset,
307		       sizeof(ibcs2_gid_t) * retval[0]);
308}
309
310int
311ibcs2_getpid(struct proc *p, void *args, int *retval)
312{
313	if (ibcs2_trace & IBCS2_TRACE_MISC)
314		printf("IBCS2: 'getpid'\n");
315	return getpid(p, args, retval);
316}
317
318int
319ibcs2_getuid(struct proc *p, void *args, int *retval)
320{
321	if (ibcs2_trace & IBCS2_TRACE_MISC)
322		printf("IBCS2: 'getuid'\n");
323	return getuid(p, args, retval);
324}
325
326struct gtime_args {
327	long *timeptr;
328};
329
330int
331ibcs2_gtime(struct proc *p, struct gtime_args *args, int *retval)
332{
333	int error = 0;
334	struct timeval tv;
335
336	if (ibcs2_trace & IBCS2_TRACE_MISC)
337		printf("IBCS2: 'gtime'\n");
338	microtime(&tv);
339	*retval = tv.tv_sec;
340	if (args)
341		(long)args->timeptr = tv.tv_sec;
342	return error;
343}
344
345int
346ibcs2_link(struct proc *p, void *args, int *retval)
347{
348	if (ibcs2_trace & IBCS2_TRACE_MISC)
349		printf("IBCS2: 'link'\n");
350	return link(p, args, retval);
351}
352
353int
354ibcs2_mkdir(struct proc *p, void *args, int *retval)
355{
356	if (ibcs2_trace & IBCS2_TRACE_MISC)
357		printf("IBCS2: 'mkdir'\n");
358	return mkdir(p, args, retval);
359}
360
361struct ibcs2_mknod_args {
362	char		*fname;
363	int		fmode;
364	ibcs2_dev_t	dev;
365};
366
367int
368ibcs2_mknod(struct proc *p, struct ibcs2_mknod_args *args, int *retval)
369{
370	if (ibcs2_trace & IBCS2_TRACE_MISC)
371		printf("IBCS2: 'mknod'\n");
372	if (S_ISFIFO(args->fmode))
373		return mkfifo(p, args, retval);
374	return mknod(p, args, retval);
375}
376
377struct ibcs2_nice_args {
378	int niceval;
379};
380
381int
382ibcs2_nice(struct proc *p, struct ibcs2_nice_args *args, int *retval)
383{
384	int error;
385
386	if (ibcs2_trace & IBCS2_TRACE_MISC)
387		printf("IBCS2: 'nice'\n");
388	error = donice(p, p, args->niceval);
389	*retval = p->p_nice;
390	return error;
391}
392
393struct ibcs2_pathconf_args {
394	long unused;
395	int cmd;
396};
397int
398ibcs2_pathconf(struct proc *p, struct ibcs2_pathconf_args *args, int *retval)
399{
400		if (ibcs2_trace & IBCS2_TRACE_MISC)
401			printf("IBCS2: '(f)pathconf'\n");
402	    	switch (args->cmd) {
403	    	case 0:	/* _PC_LINK_MAX */
404			*retval = (LINK_MAX);
405			break;
406	    	case 1:	/* _PC_MAX_CANON */
407			*retval = (MAX_CANON);
408			break;
409	    	case 2:	/* _PC_MAX_INPUT */
410			*retval = (MAX_INPUT);
411			break;
412	    	case 5:	/* _PC_PATH_MAX */
413			*retval = (PATH_MAX);
414			break;
415	    	case 8:	/* _PC_VDISABLE */
416	      		*retval = (_POSIX_VDISABLE);
417	      		break;
418	    	case 3:	/* _PC_NAME_MAX */
419			*retval = (NAME_MAX);
420			break;
421	    	case 4:	/* _PC_PATH_MAX */
422	      		*retval = (PATH_MAX);
423	      		break;
424	    	case 6:	/* _PC_CHOWN_RESTRICTED */
425#ifdef _POSIX_CHOWN_RESTRICTED
426	      		*retval = _POSIX_CHOWN_RESTRICTED;
427#else
428			*retval = (0);
429#endif
430	      		break;
431	    	case 7:	/* _PC_NO_TRUNC */
432#ifdef _POSIX_NO_TRUNC
433	      		*retval = _POSIX_NO_TRUNC;
434#else
435			*retval = (1);
436#endif
437	      		break;
438		default:
439			*retval = -1;
440	      		return EINVAL;
441		}
442	      	return 0;
443}
444
445int
446ibcs2_pause(struct proc *p, void *args, int *retval)
447{
448	int mask = 0;
449
450	if (ibcs2_trace & IBCS2_TRACE_MISC)
451		printf("IBCS2: 'pause'\n");
452	return sigsuspend(p, &mask, retval);
453}
454
455int
456ibcs2_pipe(struct proc *p, void *args, int *retval)
457{
458	if (ibcs2_trace & IBCS2_TRACE_MISC)
459		printf("IBCS2: 'pipe'\n");
460	return pipe(p, args, retval);
461}
462
463struct ibcs2_poll {
464	int fd;
465	short events;
466	short revents;
467};
468
469struct ibcs2_poll_args {
470	struct ibcs2_poll *fds;
471	unsigned long nfds;
472	int timeout;
473};
474
475int
476ibcs2_poll(struct proc *p, struct ibcs2_poll_args *args, int *retval)
477{
478	struct ibcs2_poll conv;
479	fd_set *readfds, *writefds, *exceptfds;
480	struct timeval *timeout;
481	struct select_args {
482		u_int	nd;
483		fd_set	*in, *ou, *ex;
484		struct	timeval *tv;
485	} tmp_select;
486	int i, error;
487
488	if (ibcs2_trace & IBCS2_TRACE_MISC)
489		printf("IBCS2: 'poll'\n");
490	if (args->nfds > FD_SETSIZE)
491		return EINVAL;
492	readfds = (fd_set *)UA_ALLOC();
493	FD_ZERO(readfds);
494	writefds = (fd_set *)UA_ALLOC() + sizeof(fd_set *);
495	FD_ZERO(writefds);
496	exceptfds = (fd_set *)UA_ALLOC() + 2*sizeof(fd_set *);
497	FD_ZERO(exceptfds);
498	timeout = (struct timeval *)UA_ALLOC() + 3*sizeof(fd_set *);
499	if (args->timeout == -1)
500		timeout = NULL;
501	else {
502		timeout->tv_usec = (args->timeout % 1000)*1000;
503		timeout->tv_sec  = args->timeout / 1000;
504	}
505	tmp_select.nd = 0;
506	tmp_select.in = readfds;
507	tmp_select.ou = writefds;
508	tmp_select.ex = exceptfds;
509	tmp_select.tv = timeout;
510	for (i = 0; i < args->nfds; i++) {
511		if (error = copyin(args->fds + i*sizeof(struct ibcs2_poll),
512				   &conv, sizeof(conv)))
513			return error;
514		conv.revents = 0;
515		if (conv.fd < 0 || conv.fd > FD_SETSIZE)
516			continue;
517		if (conv.fd >= tmp_select.nd)
518			tmp_select.nd = conv.fd + 1;
519		if (conv.events & IBCS2_READPOLL)
520			FD_SET(conv.fd, readfds);
521		if (conv.events & IBCS2_WRITEPOLL)
522			FD_SET(conv.fd, writefds);
523		FD_SET(conv.fd, exceptfds);
524	}
525	if (error = select(p, &tmp_select, retval))
526		return error;
527	if (*retval == 0)
528		return 0;
529	*retval = 0;
530	for (*retval = 0, i = 0; i < args->nfds; i++) {
531		copyin(args->fds + i*sizeof(struct ibcs2_poll),
532		       &conv, sizeof(conv));
533		conv.revents = 0;
534		if (conv.fd < 0 || conv.fd > FD_SETSIZE)
535			/* should check for open as well */
536			conv.revents |= IBCS2_POLLNVAL;
537		else {
538			if (FD_ISSET(conv.fd, readfds))
539				conv.revents |= IBCS2_POLLIN;
540			if (FD_ISSET(conv.fd, writefds))
541				conv.revents |= IBCS2_POLLOUT;
542			if (FD_ISSET(conv.fd, exceptfds))
543				conv.revents |= IBCS2_POLLERR;
544			if (conv.revents)
545				++*retval;
546		}
547		if (error = copyout(&conv,
548				    args->fds + i*sizeof(struct ibcs2_poll),
549				    sizeof(conv)))
550			return error;
551	}
552	return 0;
553}
554
555struct ibcs2_procids_args {
556  	int req;
557  	int eax;
558};
559
560int
561ibcs2_procids(struct proc *p, struct ibcs2_procids_args *args, int *retval)
562{
563	if (ibcs2_trace & IBCS2_TRACE_MISC)
564		printf("IBCS2: 'procids' request=%d,  eax=%x\n",
565  			args->req, args->eax);
566  	switch (args->req) {
567  	case 0:	/* getpgrp */
568    		return getpgrp(p, args, retval);
569  	case 1:	/* setpgrp */
570		{
571    			struct setpgid_args {
572				int pid;
573				int pgid;
574			} tmp;
575    			tmp.pid = tmp.pgid = 0;
576    			return setpgid(p, &tmp, retval);
577  		}
578  	case 2:	/* setpgid */
579    		return setpgid(p, args, retval);
580  	case 3:	/* setsid */
581    		return setsid(p, args, retval);
582  	default:
583    		return EINVAL;
584  	}
585}
586
587int
588ibcs2_profil(struct proc *p, void *args, int *retval)
589{
590	if (ibcs2_trace & IBCS2_TRACE_MISC)
591		printf("IBCS2: 'profil'\n");
592	return profil(p, args, retval);
593}
594
595int
596ibcs2_ptrace(struct proc *p, void *args, int *retval)
597{
598	if (ibcs2_trace & IBCS2_TRACE_MISC)
599		printf("IBCS2: 'ptrace'\n");
600	return ptrace(p, args, retval);
601}
602
603int
604ibcs2_readlink(struct proc *p, void *args, int *retval)
605{
606	if (ibcs2_trace & IBCS2_TRACE_MISC)
607		printf("IBCS2: 'readlink'\n");
608	return readlink(p, args, retval);
609}
610
611int
612ibcs2_rename(struct proc *p, void *args, int *retval)
613{
614	if (ibcs2_trace & IBCS2_TRACE_MISC)
615		printf("IBCS2: 'rename'\n");
616	return rename(p, args, retval);
617}
618
619int
620ibcs2_rmdir(struct proc *p, void *args, int *retval)
621{
622	if (ibcs2_trace & IBCS2_TRACE_MISC)
623		printf("IBCS2: 'rmdir'\n");
624	return rmdir(p, args, retval);
625}
626
627struct ibcs2_secure_args {
628	int	cmd;
629	int	arg1;
630	int	arg2;
631	int	arg3;
632	int	arg4;
633	int	arg5;
634};
635
636int
637ibcs2_secure(struct proc *p, struct ibcs2_secure_args *args, int *retval)
638{
639  	struct trapframe *tf = (struct trapframe *)p->p_md.md_regs;
640
641	if (ibcs2_trace & IBCS2_TRACE_MISC)
642		printf("IBCS2: 'secure'\n");
643
644	switch (args->cmd) {
645
646	case 1:		/* get login uid */
647		*retval = p->p_ucred->cr_uid;
648		return EPERM;
649
650	case 2:		/* set login uid */
651
652	default:
653		printf("IBCS2: 'secure' cmd=%d not implemented\n",args->cmd);
654	}
655	return EINVAL;
656}
657
658struct ibcs2_setgid_args {
659	ibcs2_gid_t gid;
660};
661
662int
663ibcs2_setgid(struct proc *p, struct ibcs2_setgid_args *args, int *retval)
664{
665	struct setgid_args {
666		gid_t gid;
667	} tmp;
668
669	if (ibcs2_trace & IBCS2_TRACE_MISC)
670		printf("IBCS2: 'setgid'\n");
671	tmp.gid = (gid_t) args->gid;
672	return setgid(p, &tmp, retval);
673}
674
675struct ibcs2_setgroups_args {
676	int gidsetsize;
677	ibcs2_gid_t *gidset;
678};
679
680int
681ibcs2_setgroups(struct proc *p, struct ibcs2_setgroups_args *args, int *retval)
682{
683	struct setgroups_args {
684		u_int	gidsetsize;
685		gid_t	*gidset;
686	} tmp;
687	ibcs2_gid_t *ibcs2_gidset;
688	int i, error;
689
690	if (ibcs2_trace & IBCS2_TRACE_MISC)
691		printf("IBCS2: 'setgroups'\n");
692	tmp.gidsetsize = args->gidsetsize;
693	tmp.gidset = (gid_t *)UA_ALLOC();
694	ibcs2_gidset = (ibcs2_gid_t *)&tmp.gidset[NGROUPS_MAX];
695	if (error = copyin((caddr_t)args->gidset, (caddr_t)ibcs2_gidset,
696		           sizeof(ibcs2_gid_t) * tmp.gidsetsize))
697		return error;
698	for (i = 0; i < tmp.gidsetsize; i++)
699		tmp.gidset[i] = (gid_t)ibcs2_gidset[i];
700	return setgroups(p, &tmp, retval);
701}
702
703struct ibcs2_setuid_args {
704	ibcs2_uid_t uid;
705};
706
707int
708ibcs2_setuid(struct proc *p, struct ibcs2_setuid_args *args, int *retval)
709{
710	struct setuid_args {
711		uid_t uid;
712	} tmp;
713
714	if (ibcs2_trace & IBCS2_TRACE_MISC)
715		printf("IBCS2: 'setuid'\n");
716	tmp.uid = (uid_t) args->uid;
717	return setuid(p, &tmp, retval);
718}
719
720int
721ibcs2_smount(struct proc *p, void *args, int *retval)
722{
723	if (ibcs2_trace & IBCS2_TRACE_MISC)
724		printf("IBCS2: 'smount'\n");
725	return mount(p, args, retval);
726}
727
728struct ibcs2_stime_args {
729	long *timeptr;
730};
731
732int
733ibcs2_stime(struct proc *p, struct ibcs2_stime_args *args, int *retval)
734{
735	int error;
736
737	if (ibcs2_trace & IBCS2_TRACE_MISC)
738		printf("IBCS2: 'stime'\n");
739	if (error = suser(p->p_ucred, &p->p_acflag))
740		return error;
741	if (args->timeptr) {
742#if 0
743		/* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
744		boottime.tv_sec += (long)args->timeptr - time.tv_sec;
745		s = splhigh();
746		time.tv_sec = (long)args->timeptr;
747		time.tv_usec = 0;
748		splx(s);
749		resettodr();
750#else
751		printf("IBCS2: trying to set system time %d\n",
752		       (long)args->timeptr);
753#endif
754	}
755	return 0;
756}
757
758int
759ibcs2_sumount(struct proc *p, void *args, int *retval)
760{
761	if (ibcs2_trace & IBCS2_TRACE_MISC)
762		printf("IBCS2: 'sumount'\n");
763	return unmount(p, args, retval);
764}
765
766int
767ibcs2_symlink(struct proc *p, void *args, int *retval)
768{
769	if (ibcs2_trace & IBCS2_TRACE_MISC)
770		printf("IBCS2: 'symlink'\n");
771	return symlink(p, args, retval);
772}
773
774int
775ibcs2_sync(struct proc *p, void *args, int *retval)
776{
777	if (ibcs2_trace & IBCS2_TRACE_MISC)
778		printf("IBCS2: 'sync'\n");
779	return sync(p, args, retval);
780}
781
782int
783ibcs2_sysacct(struct proc *p, void *args, int *retval)
784{
785	if (ibcs2_trace & IBCS2_TRACE_MISC)
786		printf("IBCS2: 'sysacct'\n");
787	return acct(p, args, retval);
788}
789
790struct ibcs2_tms {
791	long	tms_utime;
792	long	tms_stime;
793	long	tms_cutime;
794	long	tms_cstime;
795};
796
797int
798ibcs2_times(struct proc *p, struct ibcs2_tms *args, int *retval)
799{
800	extern int hz;
801	struct timeval tv;
802	struct ibcs2_tms tms;
803
804	if (ibcs2_trace & IBCS2_TRACE_MISC)
805		printf("IBCS2: 'times'\n");
806	tms.tms_utime = p->p_uticks;
807	tms.tms_stime = p->p_sticks;
808	tms.tms_cutime = p->p_stats->p_cru.ru_utime.tv_sec * hz +
809			((p->p_stats->p_cru.ru_utime.tv_usec * hz)/1000000);
810	tms.tms_cstime = p->p_stats->p_cru.ru_stime.tv_sec * hz +
811			((p->p_stats->p_cru.ru_stime.tv_usec * hz)/1000000);
812	microtime(&tv);
813	*retval = tv.tv_sec * hz + (tv.tv_usec * hz)/1000000;
814	return (copyout((caddr_t)&tms,
815				    (caddr_t)args->tms_utime,
816				    sizeof(struct ibcs2_tms)));
817}
818
819struct ibcs2_ulimit_args {
820	int cmd;
821	long limit;
822};
823
824int
825ibcs2_ulimit(struct proc *p, struct ibcs2_ulimit_args *args, int *retval)
826{
827	if (ibcs2_trace & IBCS2_TRACE_MISC)
828		printf("IBCS2: 'ulimit'\n");
829	switch (args->cmd) {
830	case IBCS2_GETFSIZE:
831		*retval = p->p_rlimit[RLIMIT_FSIZE].rlim_cur;
832		return 0;
833
834	case IBCS2_SETFSIZE:
835		return EINVAL;
836
837	case IBCS2_GETPSIZE:
838		*retval = p->p_rlimit[RLIMIT_RSS].rlim_cur;
839		return 0;
840	case IBCS2_GETMOPEN:
841		*retval = p->p_rlimit[RLIMIT_NOFILE].rlim_cur;
842		return 0;
843	}
844	return EINVAL;
845}
846
847int
848ibcs2_umask(struct proc *p, void *args, int *retval)
849{
850	if (ibcs2_trace & IBCS2_TRACE_MISC)
851		printf("IBCS2: 'umask'\n");
852	return umask(p, args, retval);
853}
854
855int
856ibcs2_unlink(struct proc *p, void *args, int *retval)
857{
858	if (ibcs2_trace & IBCS2_TRACE_MISC)
859		printf("IBCS2: 'unlink'\n");
860	return unlink(p, args, retval);
861}
862
863struct ibcs2_utime_args {
864	char		*fname;
865	ibcs2_time_t	*timeptr;
866};
867
868int
869ibcs2_utime(struct proc *p, struct ibcs2_utime_args *args, int *retval)
870{
871	struct bsd_utimes_args {
872		char	*fname;
873		struct	timeval *tptr;
874	} bsdutimes;
875	struct timeval tv;
876
877	if (ibcs2_trace & IBCS2_TRACE_MISC)
878		printf("IBCS2: 'utime'\n");
879	tv.tv_sec = (long)args->timeptr;
880	tv.tv_usec = 0;
881	bsdutimes.tptr = &tv;
882	bsdutimes.fname = args->fname;
883	return utimes(p, &bsdutimes, retval);
884}
885
886struct ibcs2_utssys_args {
887	char *buf;
888	int mv;
889	int cmd;
890};
891
892int
893ibcs2_utssys(struct proc *p, struct ibcs2_utssys_args *args, int *retval)
894{
895	struct ibcs2_utsname {
896		char	sysname[9];
897		char	nodename[9];
898		char	release[9];
899		char	version[9];
900		char	machine[9];
901	} ibcs2_uname;
902	extern char ostype[], hostname[], osrelease[], machine[];
903
904	if (ibcs2_trace & IBCS2_TRACE_MISC)
905		printf("IBCS2: 'utssys' cmd=%d\n", args->cmd);
906	switch(args->cmd) {
907	case 0:	/* uname */
908		bzero(&ibcs2_uname, sizeof(struct ibcs2_utsname));
909		strncpy(ibcs2_uname.sysname, ostype, 8);
910		strncpy(ibcs2_uname.nodename, hostname, 8);
911		strncpy(ibcs2_uname.release, osrelease, 8);
912		strncpy(ibcs2_uname.version, version, 8);
913		strncpy(ibcs2_uname.machine, machine, 8);
914		return (copyout((caddr_t)&ibcs2_uname,
915				    (caddr_t)args->buf,
916				    sizeof(struct ibcs2_utsname)));
917
918	case 2: /* ustat */
919		printf("IBCS2: utssys(ustat) not implemented yet\n");
920		return EINVAL;
921
922	case 1: /* umask, obsolete */
923	default:
924		printf("IBCS2: 'utssys cmd (%d) not implemented yet'\n",
925			args->cmd);
926		return EINVAL;
927	}
928}
929
930int
931ibcs2_wait(struct proc *p, void *args, int *retval)
932{
933  	struct trapframe *tf = (struct trapframe *)p->p_md.md_regs;
934    	struct ibcs2_waitpid_args {
935      		int pid;
936      		int *status;
937      		int options;
938    	} *t = args;
939    	struct wait4_args {
940      		int pid;
941      		int *status;
942      		int options;
943      		struct rusage *rusage;
944      		int compat;
945    	} tmp;
946
947	tmp.compat = 1;
948	tmp.rusage = 0;
949	if (ibcs2_trace & IBCS2_TRACE_MISC)
950		printf("IBCS2: 'wait'\n");
951
952  	if ((tf->tf_eflags & (PSL_Z|PSL_PF|PSL_N|PSL_V))
953      	    == (PSL_Z|PSL_PF|PSL_N|PSL_V)) {
954    		tmp.pid = t->pid;
955    		tmp.status = t->status;
956		tmp.options = 0;
957		if (t->options & 02)
958		  	tmp.options |= WUNTRACED;
959		if (t->options & 01)
960		  	tmp.options |= WNOHANG;
961    		tmp.options = t->options;
962  	} else {
963		tmp.pid = WAIT_ANY;
964		tmp.status = (int*)t->pid;
965		tmp.options = 0;
966	}
967	return wait1(p, &tmp, retval);
968}
969