]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/compat/svr4/svr4_misc.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / compat / svr4 / svr4_misc.c
1 /*-
2  * Copyright (c) 1998 Mark Newton
3  * Copyright (c) 1994 Christos Zoulas
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 /*
29  * SVR4 compatibility module.
30  *
31  * SVR4 system calls that are implemented differently in BSD are
32  * handled here.
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include "opt_mac.h"
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/dirent.h>
43 #include <sys/fcntl.h>
44 #include <sys/filedesc.h>
45 #include <sys/imgact.h>
46 #include <sys/kernel.h>
47 #include <sys/lock.h>
48 #include <sys/malloc.h>
49 #include <sys/file.h>           /* Must come after sys/malloc.h */
50 #include <sys/mman.h>
51 #include <sys/mount.h>
52 #include <sys/msg.h>
53 #include <sys/mutex.h>
54 #include <sys/namei.h>
55 #include <sys/priv.h>
56 #include <sys/proc.h>
57 #include <sys/ptrace.h>
58 #include <sys/resource.h>
59 #include <sys/resourcevar.h>
60 #include <sys/sem.h>
61 #include <sys/signalvar.h>
62 #include <sys/stat.h>
63 #include <sys/sx.h>
64 #include <sys/syscallsubr.h>
65 #include <sys/sysproto.h>
66 #include <sys/time.h>
67 #include <sys/times.h>
68 #include <sys/uio.h>
69 #include <sys/vnode.h>
70 #include <sys/wait.h>
71
72 #include <compat/svr4/svr4.h>
73 #include <compat/svr4/svr4_types.h>
74 #include <compat/svr4/svr4_signal.h>
75 #include <compat/svr4/svr4_proto.h>
76 #include <compat/svr4/svr4_util.h>
77 #include <compat/svr4/svr4_sysconfig.h>
78 #include <compat/svr4/svr4_dirent.h>
79 #include <compat/svr4/svr4_acl.h>
80 #include <compat/svr4/svr4_ulimit.h>
81 #include <compat/svr4/svr4_statvfs.h>
82 #include <compat/svr4/svr4_hrt.h>
83 #include <compat/svr4/svr4_mman.h>
84 #include <compat/svr4/svr4_wait.h>
85
86 #include <security/mac/mac_framework.h>
87
88 #include <machine/vmparam.h>
89 #include <vm/vm.h>
90 #include <vm/vm_param.h>
91 #include <vm/vm_map.h>
92 #if defined(__FreeBSD__)
93 #include <vm/uma.h>
94 #include <vm/vm_extern.h>
95 #endif
96
97 #if defined(NetBSD)
98 # if defined(UVM)
99 #  include <uvm/uvm_extern.h>
100 # endif
101 #endif
102
103 #define BSD_DIRENT(cp)          ((struct dirent *)(cp))
104
105 static int svr4_mknod(struct thread *, register_t *, char *,
106     svr4_mode_t, svr4_dev_t);
107
108 static __inline clock_t timeval_to_clock_t(struct timeval *);
109 static int svr4_setinfo (pid_t , struct rusage *, int, svr4_siginfo_t *);
110
111 struct svr4_hrtcntl_args;
112 static int svr4_hrtcntl (struct thread *, struct svr4_hrtcntl_args *,
113     register_t *);
114 static void bsd_statfs_to_svr4_statvfs(const struct statfs *,
115     struct svr4_statvfs *);
116 static void bsd_statfs_to_svr4_statvfs64(const struct statfs *,
117     struct svr4_statvfs64 *);
118 static struct proc *svr4_pfind(pid_t pid);
119
120 /* BOGUS noop */
121 #if defined(BOGUS)
122 int
123 svr4_sys_setitimer(td, uap)
124         register struct thread *td;
125         struct svr4_sys_setitimer_args *uap;
126 {
127         td->td_retval[0] = 0;
128         return 0;
129 }
130 #endif
131
132 int
133 svr4_sys_wait(td, uap)
134         struct thread *td;
135         struct svr4_sys_wait_args *uap;
136 {
137         int error, st, sig;
138
139         error = kern_wait(td, WAIT_ANY, &st, 0, NULL);
140         if (error)
141                 return (error);
142       
143         if (WIFSIGNALED(st)) {
144                 sig = WTERMSIG(st);
145                 if (sig >= 0 && sig < NSIG)
146                         st = (st & ~0177) | SVR4_BSD2SVR4_SIG(sig);
147         } else if (WIFSTOPPED(st)) {
148                 sig = WSTOPSIG(st);
149                 if (sig >= 0 && sig < NSIG)
150                         st = (st & ~0xff00) | (SVR4_BSD2SVR4_SIG(sig) << 8);
151         }
152
153         /*
154          * It looks like wait(2) on svr4/solaris/2.4 returns
155          * the status in retval[1], and the pid on retval[0].
156          */
157         td->td_retval[1] = st;
158
159         if (uap->status)
160                 error = copyout(&st, uap->status, sizeof(st));
161
162         return (error);
163 }
164
165 int
166 svr4_sys_execv(td, uap)
167         struct thread *td;
168         struct svr4_sys_execv_args *uap;
169 {
170         struct image_args eargs;
171         char *path;
172         int error;
173
174         CHECKALTEXIST(td, uap->path, &path);
175
176         error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, NULL);
177         free(path, M_TEMP);
178         if (error == 0)
179                 error = kern_execve(td, &eargs, NULL);
180         return (error);
181 }
182
183 int
184 svr4_sys_execve(td, uap)
185         struct thread *td;
186         struct svr4_sys_execve_args *uap;
187 {
188         struct image_args eargs;
189         char *path;
190         int error;
191
192         CHECKALTEXIST(td, uap->path, &path);
193
194         error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp,
195             uap->envp);
196         free(path, M_TEMP);
197         if (error == 0)
198                 error = kern_execve(td, &eargs, NULL);
199         return (error);
200 }
201
202 int
203 svr4_sys_time(td, v)
204         struct thread *td;
205         struct svr4_sys_time_args *v;
206 {
207         struct svr4_sys_time_args *uap = v;
208         int error = 0;
209         struct timeval tv;
210
211         microtime(&tv);
212         if (uap->t)
213                 error = copyout(&tv.tv_sec, uap->t,
214                                 sizeof(*(uap->t)));
215         td->td_retval[0] = (int) tv.tv_sec;
216
217         return error;
218 }
219
220
221 /*
222  * Read SVR4-style directory entries.  We suck them into kernel space so
223  * that they can be massaged before being copied out to user code.  
224  *
225  * This code is ported from the Linux emulator:  Changes to the VFS interface
226  * between FreeBSD and NetBSD have made it simpler to port it from there than
227  * to adapt the NetBSD version.
228  */
229 int
230 svr4_sys_getdents64(td, uap)
231         struct thread *td;
232         struct svr4_sys_getdents64_args *uap;
233 {
234         register struct dirent *bdp;
235         struct vnode *vp;
236         caddr_t inp, buf;               /* BSD-format */
237         int len, reclen;                /* BSD-format */
238         caddr_t outp;                   /* SVR4-format */
239         int resid, svr4reclen=0;        /* SVR4-format */
240         struct file *fp;
241         struct uio auio;
242         struct iovec aiov;
243         off_t off;
244         struct svr4_dirent64 svr4_dirent;
245         int buflen, error, eofflag, nbytes, justone, vfslocked;
246         u_long *cookies = NULL, *cookiep;
247         int ncookies;
248
249         DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n",
250                 uap->fd, uap->nbytes));
251         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) {
252                 return (error);
253         }
254
255         if ((fp->f_flag & FREAD) == 0) {
256                 fdrop(fp, td);
257                 return (EBADF);
258         }
259
260         vp = fp->f_vnode;
261         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
262         if (vp->v_type != VDIR) {
263                 VFS_UNLOCK_GIANT(vfslocked);
264                 fdrop(fp, td);
265                 return (EINVAL);
266         }
267
268         nbytes = uap->nbytes;
269         if (nbytes == 1) {
270                 nbytes = sizeof (struct svr4_dirent64);
271                 justone = 1;
272         }
273         else
274                 justone = 0;
275
276         off = fp->f_offset;
277 #define DIRBLKSIZ       512             /* XXX we used to use ufs's DIRBLKSIZ */
278         buflen = max(DIRBLKSIZ, nbytes);
279         buflen = min(buflen, MAXBSIZE);
280         buf = malloc(buflen, M_TEMP, M_WAITOK);
281         vn_lock(vp, LK_SHARED | LK_RETRY, td);
282 again:
283         aiov.iov_base = buf;
284         aiov.iov_len = buflen;
285         auio.uio_iov = &aiov;
286         auio.uio_iovcnt = 1;
287         auio.uio_rw = UIO_READ;
288         auio.uio_segflg = UIO_SYSSPACE;
289         auio.uio_td = td;
290         auio.uio_resid = buflen;
291         auio.uio_offset = off;
292
293         if (cookies) {
294                 free(cookies, M_TEMP);
295                 cookies = NULL;
296         }
297
298 #ifdef MAC
299         error = mac_check_vnode_readdir(td->td_ucred, vp);
300         if (error)
301                 goto out;
302 #endif
303
304         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
305                                                 &ncookies, &cookies);
306         if (error) {
307                 goto out;
308         }
309
310         inp = buf;
311         outp = (caddr_t) uap->dp;
312         resid = nbytes;
313         if ((len = buflen - auio.uio_resid) <= 0) {
314                 goto eof;
315         }
316
317         cookiep = cookies;
318
319         if (cookies) {
320                 /*
321                  * When using cookies, the vfs has the option of reading from
322                  * a different offset than that supplied (UFS truncates the
323                  * offset to a block boundary to make sure that it never reads
324                  * partway through a directory entry, even if the directory
325                  * has been compacted).
326                  */
327                 while (len > 0 && ncookies > 0 && *cookiep <= off) {
328                         bdp = (struct dirent *) inp;
329                         len -= bdp->d_reclen;
330                         inp += bdp->d_reclen;
331                         cookiep++;
332                         ncookies--;
333                 }
334         }
335
336         while (len > 0) {
337                 if (cookiep && ncookies == 0)
338                         break;
339                 bdp = (struct dirent *) inp;
340                 reclen = bdp->d_reclen;
341                 if (reclen & 3) {
342                         DPRINTF(("svr4_readdir: reclen=%d\n", reclen));
343                         error = EFAULT;
344                         goto out;
345                 }
346   
347                 if (bdp->d_fileno == 0) {
348                         inp += reclen;
349                         if (cookiep) {
350                                 off = *cookiep++;
351                                 ncookies--;
352                         } else
353                                 off += reclen;
354                         len -= reclen;
355                         continue;
356                 }
357                 svr4reclen = SVR4_RECLEN(&svr4_dirent, bdp->d_namlen);
358                 if (reclen > len || resid < svr4reclen) {
359                         outp++;
360                         break;
361                 }
362                 svr4_dirent.d_ino = (long) bdp->d_fileno;
363                 if (justone) {
364                         /*
365                          * old svr4-style readdir usage.
366                          */
367                         svr4_dirent.d_off = (svr4_off_t) svr4reclen;
368                         svr4_dirent.d_reclen = (u_short) bdp->d_namlen;
369                 } else {
370                         svr4_dirent.d_off = (svr4_off_t)(off + reclen);
371                         svr4_dirent.d_reclen = (u_short) svr4reclen;
372                 }
373                 strcpy(svr4_dirent.d_name, bdp->d_name);
374                 if ((error = copyout((caddr_t)&svr4_dirent, outp, svr4reclen)))
375                         goto out;
376                 inp += reclen;
377                 if (cookiep) {
378                         off = *cookiep++;
379                         ncookies--;
380                 } else
381                         off += reclen;
382                 outp += svr4reclen;
383                 resid -= svr4reclen;
384                 len -= reclen;
385                 if (justone)
386                         break;
387         }
388
389         if (outp == (caddr_t) uap->dp)
390                 goto again;
391         fp->f_offset = off;
392
393         if (justone)
394                 nbytes = resid + svr4reclen;
395
396 eof:
397         td->td_retval[0] = nbytes - resid;
398 out:
399         VOP_UNLOCK(vp, 0, td);
400         VFS_UNLOCK_GIANT(vfslocked);
401         fdrop(fp, td);
402         if (cookies)
403                 free(cookies, M_TEMP);
404         free(buf, M_TEMP);
405         return error;
406 }
407
408
409 int
410 svr4_sys_getdents(td, uap)
411         struct thread *td;
412         struct svr4_sys_getdents_args *uap;
413 {
414         struct dirent *bdp;
415         struct vnode *vp;
416         caddr_t inp, buf;       /* BSD-format */
417         int len, reclen;        /* BSD-format */
418         caddr_t outp;           /* SVR4-format */
419         int resid, svr4_reclen; /* SVR4-format */
420         struct file *fp;
421         struct uio auio;
422         struct iovec aiov;
423         struct svr4_dirent idb;
424         off_t off;              /* true file offset */
425         int buflen, error, eofflag, vfslocked;
426         u_long *cookiebuf = NULL, *cookie;
427         int ncookies = 0, *retval = td->td_retval;
428
429         if (uap->nbytes < 0)
430                 return (EINVAL);
431
432         if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
433                 return (error);
434
435         if ((fp->f_flag & FREAD) == 0) {
436                 fdrop(fp, td);
437                 return (EBADF);
438         }
439
440         vp = fp->f_vnode;
441         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
442         if (vp->v_type != VDIR) {
443                 VFS_UNLOCK_GIANT(vfslocked);
444                 fdrop(fp, td);
445                 return (EINVAL);
446         }
447
448         buflen = min(MAXBSIZE, uap->nbytes);
449         buf = malloc(buflen, M_TEMP, M_WAITOK);
450         vn_lock(vp, LK_SHARED | LK_RETRY, td);
451         off = fp->f_offset;
452 again:
453         aiov.iov_base = buf;
454         aiov.iov_len = buflen;
455         auio.uio_iov = &aiov;
456         auio.uio_iovcnt = 1;
457         auio.uio_rw = UIO_READ;
458         auio.uio_segflg = UIO_SYSSPACE;
459         auio.uio_td = td;
460         auio.uio_resid = buflen;
461         auio.uio_offset = off;
462
463 #ifdef MAC
464         error = mac_check_vnode_readdir(td->td_ucred, vp);
465         if (error)
466                 goto out;
467 #endif
468
469         /*
470          * First we read into the malloc'ed buffer, then
471          * we massage it into user space, one record at a time.
472          */
473         error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies,
474             &cookiebuf);
475         if (error) {
476                 goto out;
477         }
478
479         inp = buf;
480         outp = uap->buf;
481         resid = uap->nbytes;
482         if ((len = buflen - auio.uio_resid) == 0)
483                 goto eof;
484
485         for (cookie = cookiebuf; len > 0; len -= reclen) {
486                 bdp = (struct dirent *)inp;
487                 reclen = bdp->d_reclen;
488                 if (reclen & 3)
489                         panic("svr4_sys_getdents64: bad reclen");
490                 off = *cookie++;        /* each entry points to the next */
491                 if ((off >> 32) != 0) {
492                         uprintf("svr4_sys_getdents64: dir offset too large for emulated program");
493                         error = EINVAL;
494                         goto out;
495                 }
496                 if (bdp->d_fileno == 0) {
497                         inp += reclen;  /* it is a hole; squish it out */
498                         continue;
499                 }
500                 svr4_reclen = SVR4_RECLEN(&idb, bdp->d_namlen);
501                 if (reclen > len || resid < svr4_reclen) {
502                         /* entry too big for buffer, so just stop */
503                         outp++;
504                         break;
505                 }
506                 /*
507                  * Massage in place to make a SVR4-shaped dirent (otherwise
508                  * we have to worry about touching user memory outside of
509                  * the copyout() call).
510                  */
511                 idb.d_ino = (svr4_ino_t)bdp->d_fileno;
512                 idb.d_off = (svr4_off_t)off;
513                 idb.d_reclen = (u_short)svr4_reclen;
514                 strcpy(idb.d_name, bdp->d_name);
515                 if ((error = copyout((caddr_t)&idb, outp, svr4_reclen)))
516                         goto out;
517                 /* advance past this real entry */
518                 inp += reclen;
519                 /* advance output past SVR4-shaped entry */
520                 outp += svr4_reclen;
521                 resid -= svr4_reclen;
522         }
523
524         /* if we squished out the whole block, try again */
525         if (outp == uap->buf)
526                 goto again;
527         fp->f_offset = off;     /* update the vnode offset */
528
529 eof:
530         *retval = uap->nbytes - resid;
531 out:
532         VOP_UNLOCK(vp, 0, td);
533         VFS_UNLOCK_GIANT(vfslocked);
534         fdrop(fp, td);
535         if (cookiebuf)
536                 free(cookiebuf, M_TEMP);
537         free(buf, M_TEMP);
538         return error;
539 }
540
541
542 int
543 svr4_sys_mmap(td, uap)
544         struct thread *td;
545         struct svr4_sys_mmap_args *uap;
546 {
547         struct mmap_args         mm;
548         int             *retval;
549
550         retval = td->td_retval;
551 #define _MAP_NEW        0x80000000
552         /*
553          * Verify the arguments.
554          */
555         if (uap->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
556                 return EINVAL;  /* XXX still needed? */
557
558         if (uap->len == 0)
559                 return EINVAL;
560
561         mm.prot = uap->prot;
562         mm.len = uap->len;
563         mm.flags = uap->flags & ~_MAP_NEW;
564         mm.fd = uap->fd;
565         mm.addr = uap->addr;
566         mm.pos = uap->pos;
567
568         return mmap(td, &mm);
569 }
570
571 int
572 svr4_sys_mmap64(td, uap)
573         struct thread *td;
574         struct svr4_sys_mmap64_args *uap;
575 {
576         struct mmap_args         mm;
577         void            *rp;
578
579 #define _MAP_NEW        0x80000000
580         /*
581          * Verify the arguments.
582          */
583         if (uap->prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
584                 return EINVAL;  /* XXX still needed? */
585
586         if (uap->len == 0)
587                 return EINVAL;
588
589         mm.prot = uap->prot;
590         mm.len = uap->len;
591         mm.flags = uap->flags & ~_MAP_NEW;
592         mm.fd = uap->fd;
593         mm.addr = uap->addr;
594         mm.pos = uap->pos;
595
596         rp = (void *) round_page((vm_offset_t)(td->td_proc->p_vmspace->vm_daddr + maxdsiz));
597         if ((mm.flags & MAP_FIXED) == 0 &&
598             mm.addr != 0 && (void *)mm.addr < rp)
599                 mm.addr = rp;
600
601         return mmap(td, &mm);
602 }
603
604
605 int
606 svr4_sys_fchroot(td, uap)
607         struct thread *td;
608         struct svr4_sys_fchroot_args *uap;
609 {
610         struct filedesc *fdp = td->td_proc->p_fd;
611         struct vnode    *vp;
612         struct file     *fp;
613         int              error, vfslocked;
614
615         if ((error = priv_check(td, PRIV_VFS_FCHROOT)) != 0)
616                 return error;
617         if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
618                 return error;
619         vp = fp->f_vnode;
620         VREF(vp);
621         fdrop(fp, td);
622         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
623         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
624         error = change_dir(vp, td);
625         if (error)
626                 goto fail;
627 #ifdef MAC
628         error = mac_check_vnode_chroot(td->td_ucred, vp);
629         if (error)
630                 goto fail;
631 #endif
632         VOP_UNLOCK(vp, 0, td);
633         error = change_root(vp, td);
634         vrele(vp);
635         VFS_UNLOCK_GIANT(vfslocked);
636         return (error);
637 fail:
638         vput(vp);
639         VFS_UNLOCK_GIANT(vfslocked);
640         return (error);
641 }
642
643
644 static int
645 svr4_mknod(td, retval, path, mode, dev)
646         struct thread *td;
647         register_t *retval;
648         char *path;
649         svr4_mode_t mode;
650         svr4_dev_t dev;
651 {
652         char *newpath;
653         int error;
654
655         CHECKALTEXIST(td, path, &newpath);
656
657         if (S_ISFIFO(mode))
658                 error = kern_mkfifo(td, newpath, UIO_SYSSPACE, mode);
659         else
660                 error = kern_mknod(td, newpath, UIO_SYSSPACE, mode, dev);
661         free(newpath, M_TEMP);
662         return (error);
663 }
664
665
666 int
667 svr4_sys_mknod(td, uap)
668         register struct thread *td;
669         struct svr4_sys_mknod_args *uap;
670 {
671         int *retval = td->td_retval;
672         return svr4_mknod(td, retval,
673                           uap->path, uap->mode,
674                           (svr4_dev_t)svr4_to_bsd_odev_t(uap->dev));
675 }
676
677
678 int
679 svr4_sys_xmknod(td, uap)
680         struct thread *td;
681         struct svr4_sys_xmknod_args *uap;
682 {
683         int *retval = td->td_retval;
684         return svr4_mknod(td, retval,
685                           uap->path, uap->mode,
686                           (svr4_dev_t)svr4_to_bsd_dev_t(uap->dev));
687 }
688
689
690 int
691 svr4_sys_vhangup(td, uap)
692         struct thread *td;
693         struct svr4_sys_vhangup_args *uap;
694 {
695         return 0;
696 }
697
698
699 int
700 svr4_sys_sysconfig(td, uap)
701         struct thread *td;
702         struct svr4_sys_sysconfig_args *uap;
703 {
704         int *retval;
705
706         retval = &(td->td_retval[0]);
707
708         switch (uap->name) {
709         case SVR4_CONFIG_UNUSED:
710                 *retval = 0;
711                 break;
712         case SVR4_CONFIG_NGROUPS:
713                 *retval = NGROUPS_MAX;
714                 break;
715         case SVR4_CONFIG_CHILD_MAX:
716                 *retval = maxproc;
717                 break;
718         case SVR4_CONFIG_OPEN_FILES:
719                 *retval = maxfiles;
720                 break;
721         case SVR4_CONFIG_POSIX_VER:
722                 *retval = 198808;
723                 break;
724         case SVR4_CONFIG_PAGESIZE:
725                 *retval = PAGE_SIZE;
726                 break;
727         case SVR4_CONFIG_CLK_TCK:
728                 *retval = 60;   /* should this be `hz', ie. 100? */
729                 break;
730         case SVR4_CONFIG_XOPEN_VER:
731                 *retval = 2;    /* XXX: What should that be? */
732                 break;
733         case SVR4_CONFIG_PROF_TCK:
734                 *retval = 60;   /* XXX: What should that be? */
735                 break;
736         case SVR4_CONFIG_NPROC_CONF:
737                 *retval = 1;    /* Only one processor for now */
738                 break;
739         case SVR4_CONFIG_NPROC_ONLN:
740                 *retval = 1;    /* And it better be online */
741                 break;
742         case SVR4_CONFIG_AIO_LISTIO_MAX:
743         case SVR4_CONFIG_AIO_MAX:
744         case SVR4_CONFIG_AIO_PRIO_DELTA_MAX:
745                 *retval = 0;    /* No aio support */
746                 break;
747         case SVR4_CONFIG_DELAYTIMER_MAX:
748                 *retval = 0;    /* No delaytimer support */
749                 break;
750         case SVR4_CONFIG_MQ_OPEN_MAX:
751                 *retval = msginfo.msgmni;
752                 break;
753         case SVR4_CONFIG_MQ_PRIO_MAX:
754                 *retval = 0;    /* XXX: Don't know */
755                 break;
756         case SVR4_CONFIG_RTSIG_MAX:
757                 *retval = 0;
758                 break;
759         case SVR4_CONFIG_SEM_NSEMS_MAX:
760                 *retval = seminfo.semmni;
761                 break;
762         case SVR4_CONFIG_SEM_VALUE_MAX:
763                 *retval = seminfo.semvmx;
764                 break;
765         case SVR4_CONFIG_SIGQUEUE_MAX:
766                 *retval = 0;    /* XXX: Don't know */
767                 break;
768         case SVR4_CONFIG_SIGRT_MIN:
769         case SVR4_CONFIG_SIGRT_MAX:
770                 *retval = 0;    /* No real time signals */
771                 break;
772         case SVR4_CONFIG_TIMER_MAX:
773                 *retval = 3;    /* XXX: real, virtual, profiling */
774                 break;
775 #if defined(NOTYET)
776         case SVR4_CONFIG_PHYS_PAGES:
777 #if defined(UVM)
778                 *retval = uvmexp.free;  /* XXX: free instead of total */
779 #else
780                 *retval = cnt.v_free_count;     /* XXX: free instead of total */
781 #endif
782                 break;
783         case SVR4_CONFIG_AVPHYS_PAGES:
784 #if defined(UVM)
785                 *retval = uvmexp.active;        /* XXX: active instead of avg */
786 #else
787                 *retval = cnt.v_active_count;   /* XXX: active instead of avg */
788 #endif
789                 break;
790 #endif /* NOTYET */
791
792         default:
793                 return EINVAL;
794         }
795         return 0;
796 }
797
798 /* ARGSUSED */
799 int
800 svr4_sys_break(td, uap)
801         struct thread *td;
802         struct svr4_sys_break_args *uap;
803 {
804         struct obreak_args ap;
805
806         ap.nsize = uap->nsize;
807         return (obreak(td, &ap));
808 }
809
810 static __inline clock_t
811 timeval_to_clock_t(tv)
812         struct timeval *tv;
813 {
814         return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz);
815 }
816
817
818 int
819 svr4_sys_times(td, uap)
820         struct thread *td;
821         struct svr4_sys_times_args *uap;
822 {
823         struct timeval tv, utime, stime, cutime, cstime;
824         struct tms tms;
825         struct proc *p;
826         int error;
827
828         p = td->td_proc;
829         PROC_LOCK(p);
830         PROC_SLOCK(p);
831         calcru(p, &utime, &stime);
832         PROC_SUNLOCK(p);
833         calccru(p, &cutime, &cstime);
834         PROC_UNLOCK(p);
835
836         tms.tms_utime = timeval_to_clock_t(&utime);
837         tms.tms_stime = timeval_to_clock_t(&stime);
838
839         tms.tms_cutime = timeval_to_clock_t(&cutime);
840         tms.tms_cstime = timeval_to_clock_t(&cstime);
841
842         error = copyout(&tms, uap->tp, sizeof(tms));
843         if (error)
844                 return (error);
845
846         microtime(&tv);
847         td->td_retval[0] = (int)timeval_to_clock_t(&tv);
848         return (0);
849 }
850
851
852 int
853 svr4_sys_ulimit(td, uap)
854         struct thread *td;
855         struct svr4_sys_ulimit_args *uap;
856 {
857         int *retval = td->td_retval;
858         int error;
859
860         switch (uap->cmd) {
861         case SVR4_GFILLIM:
862                 PROC_LOCK(td->td_proc);
863                 *retval = lim_cur(td->td_proc, RLIMIT_FSIZE) / 512;
864                 PROC_UNLOCK(td->td_proc);
865                 if (*retval == -1)
866                         *retval = 0x7fffffff;
867                 return 0;
868
869         case SVR4_SFILLIM:
870                 {
871                         struct rlimit krl;
872
873                         krl.rlim_cur = uap->newlimit * 512;
874                         PROC_LOCK(td->td_proc);
875                         krl.rlim_max = lim_max(td->td_proc, RLIMIT_FSIZE);
876                         PROC_UNLOCK(td->td_proc);
877
878                         error = kern_setrlimit(td, RLIMIT_FSIZE, &krl);
879                         if (error)
880                                 return error;
881
882                         PROC_LOCK(td->td_proc);
883                         *retval = lim_cur(td->td_proc, RLIMIT_FSIZE);
884                         PROC_UNLOCK(td->td_proc);
885                         if (*retval == -1)
886                                 *retval = 0x7fffffff;
887                         return 0;
888                 }
889
890         case SVR4_GMEMLIM:
891                 {
892                         struct vmspace *vm = td->td_proc->p_vmspace;
893                         register_t r;
894
895                         PROC_LOCK(td->td_proc);
896                         r = lim_cur(td->td_proc, RLIMIT_DATA);
897                         PROC_UNLOCK(td->td_proc);
898
899                         if (r == -1)
900                                 r = 0x7fffffff;
901                         mtx_lock(&Giant);       /* XXX */
902                         r += (long) vm->vm_daddr;
903                         mtx_unlock(&Giant);
904                         if (r < 0)
905                                 r = 0x7fffffff;
906                         *retval = r;
907                         return 0;
908                 }
909
910         case SVR4_GDESLIM:
911                 PROC_LOCK(td->td_proc);
912                 *retval = lim_cur(td->td_proc, RLIMIT_NOFILE);
913                 PROC_UNLOCK(td->td_proc);
914                 if (*retval == -1)
915                         *retval = 0x7fffffff;
916                 return 0;
917
918         default:
919                 return EINVAL;
920         }
921 }
922
923 static struct proc *
924 svr4_pfind(pid)
925         pid_t pid;
926 {
927         struct proc *p;
928
929         /* look in the live processes */
930         if ((p = pfind(pid)) == NULL)
931                 /* look in the zombies */
932                 p = zpfind(pid);
933
934         return p;
935 }
936
937
938 int
939 svr4_sys_pgrpsys(td, uap)
940         struct thread *td;
941         struct svr4_sys_pgrpsys_args *uap;
942 {
943         int *retval = td->td_retval;
944         struct proc *p = td->td_proc;
945
946         switch (uap->cmd) {
947         case 1:                 /* setpgrp() */
948                 /*
949                  * SVR4 setpgrp() (which takes no arguments) has the
950                  * semantics that the session ID is also created anew, so
951                  * in almost every sense, setpgrp() is identical to
952                  * setsid() for SVR4.  (Under BSD, the difference is that
953                  * a setpgid(0,0) will not create a new session.)
954                  */
955                 setsid(td, NULL);
956                 /*FALLTHROUGH*/
957
958         case 0:                 /* getpgrp() */
959                 PROC_LOCK(p);
960                 *retval = p->p_pgrp->pg_id;
961                 PROC_UNLOCK(p);
962                 return 0;
963
964         case 2:                 /* getsid(pid) */
965                 if (uap->pid == 0)
966                         PROC_LOCK(p);
967                 else if ((p = svr4_pfind(uap->pid)) == NULL)
968                         return ESRCH;
969                 /*
970                  * This has already been initialized to the pid of
971                  * the session leader.
972                  */
973                 *retval = (register_t) p->p_session->s_sid;
974                 PROC_UNLOCK(p);
975                 return 0;
976
977         case 3:                 /* setsid() */
978                 return setsid(td, NULL);
979
980         case 4:                 /* getpgid(pid) */
981
982                 if (uap->pid == 0)
983                         PROC_LOCK(p);
984                 else if ((p = svr4_pfind(uap->pid)) == NULL)
985                         return ESRCH;
986
987                 *retval = (int) p->p_pgrp->pg_id;
988                 PROC_UNLOCK(p);
989                 return 0;
990
991         case 5:                 /* setpgid(pid, pgid); */
992                 {
993                         struct setpgid_args sa;
994
995                         sa.pid = uap->pid;
996                         sa.pgid = uap->pgid;
997                         return setpgid(td, &sa);
998                 }
999
1000         default:
1001                 return EINVAL;
1002         }
1003 }
1004
1005 struct svr4_hrtcntl_args {
1006         int                     cmd;
1007         int                     fun;
1008         int                     clk;
1009         svr4_hrt_interval_t *   iv;
1010         svr4_hrt_time_t *       ti;
1011 };
1012
1013
1014 static int
1015 svr4_hrtcntl(td, uap, retval)
1016         struct thread *td;
1017         struct svr4_hrtcntl_args *uap;
1018         register_t *retval;
1019 {
1020         switch (uap->fun) {
1021         case SVR4_HRT_CNTL_RES:
1022                 DPRINTF(("htrcntl(RES)\n"));
1023                 *retval = SVR4_HRT_USEC;
1024                 return 0;
1025
1026         case SVR4_HRT_CNTL_TOFD:
1027                 DPRINTF(("htrcntl(TOFD)\n"));
1028                 {
1029                         struct timeval tv;
1030                         svr4_hrt_time_t t;
1031                         if (uap->clk != SVR4_HRT_CLK_STD) {
1032                                 DPRINTF(("clk == %d\n", uap->clk));
1033                                 return EINVAL;
1034                         }
1035                         if (uap->ti == NULL) {
1036                                 DPRINTF(("ti NULL\n"));
1037                                 return EINVAL;
1038                         }
1039                         microtime(&tv);
1040                         t.h_sec = tv.tv_sec;
1041                         t.h_rem = tv.tv_usec;
1042                         t.h_res = SVR4_HRT_USEC;
1043                         return copyout(&t, uap->ti, sizeof(t));
1044                 }
1045
1046         case SVR4_HRT_CNTL_START:
1047                 DPRINTF(("htrcntl(START)\n"));
1048                 return ENOSYS;
1049
1050         case SVR4_HRT_CNTL_GET:
1051                 DPRINTF(("htrcntl(GET)\n"));
1052                 return ENOSYS;
1053         default:
1054                 DPRINTF(("Bad htrcntl command %d\n", uap->fun));
1055                 return ENOSYS;
1056         }
1057 }
1058
1059
1060 int
1061 svr4_sys_hrtsys(td, uap) 
1062         struct thread *td;
1063         struct svr4_sys_hrtsys_args *uap;
1064 {
1065         int *retval = td->td_retval;
1066
1067         switch (uap->cmd) {
1068         case SVR4_HRT_CNTL:
1069                 return svr4_hrtcntl(td, (struct svr4_hrtcntl_args *) uap,
1070                                     retval);
1071
1072         case SVR4_HRT_ALRM:
1073                 DPRINTF(("hrtalarm\n"));
1074                 return ENOSYS;
1075
1076         case SVR4_HRT_SLP:
1077                 DPRINTF(("hrtsleep\n"));
1078                 return ENOSYS;
1079
1080         case SVR4_HRT_CAN:
1081                 DPRINTF(("hrtcancel\n"));
1082                 return ENOSYS;
1083
1084         default:
1085                 DPRINTF(("Bad hrtsys command %d\n", uap->cmd));
1086                 return EINVAL;
1087         }
1088 }
1089
1090
1091 static int
1092 svr4_setinfo(pid, ru, st, s)
1093         pid_t pid;
1094         struct rusage *ru;
1095         int st;
1096         svr4_siginfo_t *s;
1097 {
1098         svr4_siginfo_t i;
1099         int sig;
1100
1101         memset(&i, 0, sizeof(i));
1102
1103         i.svr4_si_signo = SVR4_SIGCHLD;
1104         i.svr4_si_errno = 0;    /* XXX? */
1105
1106         i.svr4_si_pid = pid;
1107         if (ru) {
1108                 i.svr4_si_stime = ru->ru_stime.tv_sec;
1109                 i.svr4_si_utime = ru->ru_utime.tv_sec;
1110         }
1111
1112         if (WIFEXITED(st)) {
1113                 i.svr4_si_status = WEXITSTATUS(st);
1114                 i.svr4_si_code = SVR4_CLD_EXITED;
1115         } else if (WIFSTOPPED(st)) {
1116                 sig = WSTOPSIG(st);
1117                 if (sig >= 0 && sig < NSIG)
1118                         i.svr4_si_status = SVR4_BSD2SVR4_SIG(sig);
1119
1120                 if (i.svr4_si_status == SVR4_SIGCONT)
1121                         i.svr4_si_code = SVR4_CLD_CONTINUED;
1122                 else
1123                         i.svr4_si_code = SVR4_CLD_STOPPED;
1124         } else {
1125                 sig = WTERMSIG(st);
1126                 if (sig >= 0 && sig < NSIG)
1127                         i.svr4_si_status = SVR4_BSD2SVR4_SIG(sig);
1128
1129                 if (WCOREDUMP(st))
1130                         i.svr4_si_code = SVR4_CLD_DUMPED;
1131                 else
1132                         i.svr4_si_code = SVR4_CLD_KILLED;
1133         }
1134
1135         DPRINTF(("siginfo [pid %ld signo %d code %d errno %d status %d]\n",
1136                  i.svr4_si_pid, i.svr4_si_signo, i.svr4_si_code, i.svr4_si_errno,
1137                  i.svr4_si_status));
1138
1139         return copyout(&i, s, sizeof(i));
1140 }
1141
1142
1143 int
1144 svr4_sys_waitsys(td, uap)
1145         struct thread *td;
1146         struct svr4_sys_waitsys_args *uap;
1147 {
1148         struct rusage ru;
1149         pid_t pid;
1150         int nfound, status;
1151         int error, *retval = td->td_retval;
1152         struct proc *p, *q;
1153
1154         DPRINTF(("waitsys(%d, %d, %p, %x)\n", 
1155                  uap->grp, uap->id,
1156                  uap->info, uap->options));
1157
1158         q = td->td_proc;
1159         switch (uap->grp) {
1160         case SVR4_P_PID:
1161                 pid = uap->id;
1162                 break;
1163
1164         case SVR4_P_PGID:
1165                 PROC_LOCK(q);
1166                 pid = -q->p_pgid;
1167                 PROC_UNLOCK(q);
1168                 break;
1169
1170         case SVR4_P_ALL:
1171                 pid = WAIT_ANY;
1172                 break;
1173
1174         default:
1175                 return EINVAL;
1176         }
1177
1178         /* Hand off the easy cases to kern_wait(). */
1179         if (!(uap->options & (SVR4_WNOWAIT)) &&
1180             (uap->options & (SVR4_WEXITED | SVR4_WTRAPPED))) {
1181                 int options;
1182
1183                 options = 0;
1184                 if (uap->options & SVR4_WSTOPPED)
1185                         options |= WUNTRACED;
1186                 if (uap->options & SVR4_WCONTINUED)
1187                         options |= WCONTINUED;
1188                 if (uap->options & SVR4_WNOHANG)
1189                         options |= WNOHANG;
1190
1191                 error = kern_wait(td, pid, &status, options, &ru);
1192                 if (error)
1193                         return (error);
1194                 if (uap->options & SVR4_WNOHANG && *retval == 0)
1195                         error = svr4_setinfo(*retval, NULL, 0, uap->info);
1196                 else
1197                         error = svr4_setinfo(*retval, &ru, status, uap->info);
1198                 *retval = 0;
1199                 return (error);
1200         }
1201
1202         /*
1203          * Ok, handle the weird cases.  Either WNOWAIT is set (meaning we
1204          * just want to see if there is a process to harvest, we dont'
1205          * want to actually harvest it), or WEXIT and WTRAPPED are clear
1206          * meaning we want to ignore zombies.  Either way, we don't have
1207          * to handle harvesting zombies here.  We do have to duplicate the
1208          * other portions of kern_wait() though, especially for the
1209          * WCONTINUED and WSTOPPED.
1210          */
1211 loop:
1212         nfound = 0;
1213         sx_slock(&proctree_lock);
1214         LIST_FOREACH(p, &q->p_children, p_sibling) {
1215                 PROC_LOCK(p);
1216                 if (pid != WAIT_ANY &&
1217                     p->p_pid != pid && p->p_pgid != -pid) {
1218                         PROC_UNLOCK(p);
1219                         DPRINTF(("pid %d pgid %d != %d\n", p->p_pid,
1220                                  p->p_pgid, pid));
1221                         continue;
1222                 }
1223                 if (p_canwait(td, p)) {
1224                         PROC_UNLOCK(p);
1225                         continue;
1226                 }
1227
1228                 nfound++;
1229
1230                 PROC_SLOCK(p);
1231                 /*
1232                  * See if we have a zombie.  If so, WNOWAIT should be set,
1233                  * as otherwise we should have called kern_wait() up above.
1234                  */
1235                 if ((p->p_state == PRS_ZOMBIE) && 
1236                     ((uap->options & (SVR4_WEXITED|SVR4_WTRAPPED)))) {
1237                         PROC_SUNLOCK(p);
1238                         KASSERT(uap->options & SVR4_WNOWAIT,
1239                             ("WNOWAIT is clear"));
1240
1241                         /* Found a zombie, so cache info in local variables. */
1242                         pid = p->p_pid;
1243                         status = p->p_xstat;
1244                         ru = p->p_ru;
1245                         PROC_SLOCK(p);
1246                         calcru(p, &ru.ru_utime, &ru.ru_stime);
1247                         PROC_SUNLOCK(p);
1248                         PROC_UNLOCK(p);
1249                         sx_sunlock(&proctree_lock);
1250
1251                         /* Copy the info out to userland. */
1252                         *retval = 0;
1253                         DPRINTF(("found %d\n", pid));
1254                         return (svr4_setinfo(pid, &ru, status, uap->info));
1255                 }
1256
1257                 /*
1258                  * See if we have a stopped or continued process.
1259                  * XXX: This duplicates the same code in kern_wait().
1260                  */
1261                 if ((p->p_flag & P_STOPPED_SIG) &&
1262                     (p->p_suspcount == p->p_numthreads) &&
1263                     (p->p_flag & P_WAITED) == 0 &&
1264                     (p->p_flag & P_TRACED || uap->options & SVR4_WSTOPPED)) {
1265                         PROC_SUNLOCK(p);
1266                         if (((uap->options & SVR4_WNOWAIT)) == 0)
1267                                 p->p_flag |= P_WAITED;
1268                         sx_sunlock(&proctree_lock);
1269                         pid = p->p_pid;
1270                         status = W_STOPCODE(p->p_xstat);
1271                         ru = p->p_ru;
1272                         PROC_SLOCK(p);
1273                         calcru(p, &ru.ru_utime, &ru.ru_stime);
1274                         PROC_SUNLOCK(p);
1275                         PROC_UNLOCK(p);
1276
1277                         if (((uap->options & SVR4_WNOWAIT)) == 0) {
1278                                 PROC_LOCK(q);
1279                                 sigqueue_take(p->p_ksi);
1280                                 PROC_UNLOCK(q);
1281                         }
1282
1283                         *retval = 0;
1284                         DPRINTF(("jobcontrol %d\n", pid));
1285                         return (svr4_setinfo(pid, &ru, status, uap->info));
1286                 }
1287                 PROC_SUNLOCK(p);
1288                 if (uap->options & SVR4_WCONTINUED &&
1289                     (p->p_flag & P_CONTINUED)) {
1290                         sx_sunlock(&proctree_lock);
1291                         if (((uap->options & SVR4_WNOWAIT)) == 0)
1292                                 p->p_flag &= ~P_CONTINUED;
1293                         pid = p->p_pid;
1294                         ru = p->p_ru;
1295                         status = SIGCONT;
1296                         PROC_SLOCK(p);
1297                         calcru(p, &ru.ru_utime, &ru.ru_stime);
1298                         PROC_SUNLOCK(p);
1299                         PROC_UNLOCK(p);
1300
1301                         if (((uap->options & SVR4_WNOWAIT)) == 0) {
1302                                 PROC_LOCK(q);
1303                                 sigqueue_take(p->p_ksi);
1304                                 PROC_UNLOCK(q);
1305                         }
1306
1307                         *retval = 0;
1308                         DPRINTF(("jobcontrol %d\n", pid));
1309                         return (svr4_setinfo(pid, &ru, status, uap->info));
1310                 }
1311                 PROC_UNLOCK(p);
1312         }
1313
1314         if (nfound == 0) {
1315                 sx_sunlock(&proctree_lock);
1316                 return (ECHILD);
1317         }
1318
1319         if (uap->options & SVR4_WNOHANG) {
1320                 sx_sunlock(&proctree_lock);
1321                 *retval = 0;
1322                 return (svr4_setinfo(0, NULL, 0, uap->info));
1323         }
1324
1325         PROC_LOCK(q);
1326         sx_sunlock(&proctree_lock);
1327         if (q->p_flag & P_STATCHILD) {
1328                 q->p_flag &= ~P_STATCHILD;
1329                 error = 0;
1330         } else
1331                 error = msleep(q, &q->p_mtx, PWAIT | PCATCH, "svr4_wait", 0);
1332         PROC_UNLOCK(q);
1333         if (error)
1334                 return error;
1335         goto loop;
1336 }
1337
1338
1339 static void
1340 bsd_statfs_to_svr4_statvfs(bfs, sfs)
1341         const struct statfs *bfs;
1342         struct svr4_statvfs *sfs;
1343 {
1344         sfs->f_bsize = bfs->f_iosize; /* XXX */
1345         sfs->f_frsize = bfs->f_bsize;
1346         sfs->f_blocks = bfs->f_blocks;
1347         sfs->f_bfree = bfs->f_bfree;
1348         sfs->f_bavail = bfs->f_bavail;
1349         sfs->f_files = bfs->f_files;
1350         sfs->f_ffree = bfs->f_ffree;
1351         sfs->f_favail = bfs->f_ffree;
1352         sfs->f_fsid = bfs->f_fsid.val[0];
1353         memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1354         sfs->f_flag = 0;
1355         if (bfs->f_flags & MNT_RDONLY)
1356                 sfs->f_flag |= SVR4_ST_RDONLY;
1357         if (bfs->f_flags & MNT_NOSUID)
1358                 sfs->f_flag |= SVR4_ST_NOSUID;
1359         sfs->f_namemax = MAXNAMLEN;
1360         memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1361         memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1362 }
1363
1364
1365 static void
1366 bsd_statfs_to_svr4_statvfs64(bfs, sfs)
1367         const struct statfs *bfs;
1368         struct svr4_statvfs64 *sfs;
1369 {
1370         sfs->f_bsize = bfs->f_iosize; /* XXX */
1371         sfs->f_frsize = bfs->f_bsize;
1372         sfs->f_blocks = bfs->f_blocks;
1373         sfs->f_bfree = bfs->f_bfree;
1374         sfs->f_bavail = bfs->f_bavail;
1375         sfs->f_files = bfs->f_files;
1376         sfs->f_ffree = bfs->f_ffree;
1377         sfs->f_favail = bfs->f_ffree;
1378         sfs->f_fsid = bfs->f_fsid.val[0];
1379         memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1380         sfs->f_flag = 0;
1381         if (bfs->f_flags & MNT_RDONLY)
1382                 sfs->f_flag |= SVR4_ST_RDONLY;
1383         if (bfs->f_flags & MNT_NOSUID)
1384                 sfs->f_flag |= SVR4_ST_NOSUID;
1385         sfs->f_namemax = MAXNAMLEN;
1386         memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1387         memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1388 }
1389
1390
1391 int
1392 svr4_sys_statvfs(td, uap)
1393         struct thread *td;
1394         struct svr4_sys_statvfs_args *uap;
1395 {
1396         struct svr4_statvfs sfs;
1397         struct statfs bfs;
1398         char *path;
1399         int error;
1400
1401         CHECKALTEXIST(td, uap->path, &path);
1402
1403         error = kern_statfs(td, path, UIO_SYSSPACE, &bfs);
1404         free(path, M_TEMP);
1405         if (error)
1406                 return (error);
1407         bsd_statfs_to_svr4_statvfs(&bfs, &sfs);
1408         return copyout(&sfs, uap->fs, sizeof(sfs));
1409 }
1410
1411
1412 int
1413 svr4_sys_fstatvfs(td, uap)
1414         struct thread *td;
1415         struct svr4_sys_fstatvfs_args *uap;
1416 {
1417         struct svr4_statvfs sfs;
1418         struct statfs bfs;
1419         int error;
1420
1421         error = kern_fstatfs(td, uap->fd, &bfs);
1422         if (error)
1423                 return (error);
1424         bsd_statfs_to_svr4_statvfs(&bfs, &sfs);
1425         return copyout(&sfs, uap->fs, sizeof(sfs));
1426 }
1427
1428
1429 int
1430 svr4_sys_statvfs64(td, uap)
1431         struct thread *td;
1432         struct svr4_sys_statvfs64_args *uap;
1433 {
1434         struct svr4_statvfs64 sfs;
1435         struct statfs bfs;
1436         char *path;
1437         int error;
1438
1439         CHECKALTEXIST(td, uap->path, &path);
1440
1441         error = kern_statfs(td, path, UIO_SYSSPACE, &bfs);
1442         free(path, M_TEMP);
1443         if (error)
1444                 return (error);
1445         bsd_statfs_to_svr4_statvfs64(&bfs, &sfs);
1446         return copyout(&sfs, uap->fs, sizeof(sfs));
1447 }
1448
1449
1450 int
1451 svr4_sys_fstatvfs64(td, uap) 
1452         struct thread *td;
1453         struct svr4_sys_fstatvfs64_args *uap;
1454 {
1455         struct svr4_statvfs64 sfs;
1456         struct statfs bfs;
1457         int error;
1458
1459         error = kern_fstatfs(td, uap->fd, &bfs);
1460         if (error)
1461                 return (error);
1462         bsd_statfs_to_svr4_statvfs64(&bfs, &sfs);
1463         return copyout(&sfs, uap->fs, sizeof(sfs));
1464 }
1465
1466 int
1467 svr4_sys_alarm(td, uap)
1468         struct thread *td;
1469         struct svr4_sys_alarm_args *uap;
1470 {
1471         struct itimerval itv, oitv;
1472         int error;
1473
1474         timevalclear(&itv.it_interval);
1475         itv.it_value.tv_sec = uap->sec;
1476         itv.it_value.tv_usec = 0;
1477         error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv);
1478         if (error)
1479                 return (error);
1480         if (oitv.it_value.tv_usec != 0)
1481                 oitv.it_value.tv_sec++;
1482         td->td_retval[0] = oitv.it_value.tv_sec;
1483         return (0);
1484 }
1485
1486 int
1487 svr4_sys_gettimeofday(td, uap)
1488         struct thread *td;
1489         struct svr4_sys_gettimeofday_args *uap;
1490 {
1491         if (uap->tp) {
1492                 struct timeval atv;
1493
1494                 microtime(&atv);
1495                 return copyout(&atv, uap->tp, sizeof (atv));
1496         }
1497
1498         return 0;
1499 }
1500
1501 int
1502 svr4_sys_facl(td, uap)
1503         struct thread *td;
1504         struct svr4_sys_facl_args *uap;
1505 {
1506         int *retval;
1507
1508         retval = td->td_retval;
1509         *retval = 0;
1510
1511         switch (uap->cmd) {
1512         case SVR4_SYS_SETACL:
1513                 /* We don't support acls on any filesystem */
1514                 return ENOSYS;
1515
1516         case SVR4_SYS_GETACL:
1517                 return copyout(retval, &uap->num,
1518                     sizeof(uap->num));
1519
1520         case SVR4_SYS_GETACLCNT:
1521                 return 0;
1522
1523         default:
1524                 return EINVAL;
1525         }
1526 }
1527
1528
1529 int
1530 svr4_sys_acl(td, uap)
1531         struct thread *td;
1532         struct svr4_sys_acl_args *uap;
1533 {
1534         /* XXX: for now the same */
1535         return svr4_sys_facl(td, (struct svr4_sys_facl_args *)uap);
1536 }
1537
1538 int
1539 svr4_sys_auditsys(td, uap)
1540         struct thread *td;
1541         struct svr4_sys_auditsys_args *uap;
1542 {
1543         /*
1544          * XXX: Big brother is *not* watching.
1545          */
1546         return 0;
1547 }
1548
1549 int
1550 svr4_sys_memcntl(td, uap)
1551         struct thread *td;
1552         struct svr4_sys_memcntl_args *uap;
1553 {
1554         switch (uap->cmd) {
1555         case SVR4_MC_SYNC:
1556                 {
1557                         struct msync_args msa;
1558
1559                         msa.addr = uap->addr;
1560                         msa.len = uap->len;
1561                         msa.flags = (int)uap->arg;
1562
1563                         return msync(td, &msa);
1564                 }
1565         case SVR4_MC_ADVISE:
1566                 {
1567                         struct madvise_args maa;
1568
1569                         maa.addr = uap->addr;
1570                         maa.len = uap->len;
1571                         maa.behav = (int)uap->arg;
1572
1573                         return madvise(td, &maa);
1574                 }
1575         case SVR4_MC_LOCK:
1576         case SVR4_MC_UNLOCK:
1577         case SVR4_MC_LOCKAS:
1578         case SVR4_MC_UNLOCKAS:
1579                 return EOPNOTSUPP;
1580         default:
1581                 return ENOSYS;
1582         }
1583 }
1584
1585
1586 int
1587 svr4_sys_nice(td, uap)
1588         struct thread *td;
1589         struct svr4_sys_nice_args *uap;
1590 {
1591         struct setpriority_args ap;
1592         int error;
1593
1594         ap.which = PRIO_PROCESS;
1595         ap.who = 0;
1596         ap.prio = uap->prio;
1597
1598         if ((error = setpriority(td, &ap)) != 0)
1599                 return error;
1600
1601         /* the cast is stupid, but the structures are the same */
1602         if ((error = getpriority(td, (struct getpriority_args *)&ap)) != 0)
1603                 return error;
1604
1605         return 0;
1606 }
1607
1608 int
1609 svr4_sys_resolvepath(td, uap)
1610         struct thread *td;
1611         struct svr4_sys_resolvepath_args *uap;
1612 {
1613         struct nameidata nd;
1614         int error, *retval = td->td_retval;
1615         unsigned int ncopy;
1616         int vfslocked;
1617
1618         NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME | MPSAFE, UIO_USERSPACE,
1619             uap->path, td);
1620
1621         if ((error = namei(&nd)) != 0)
1622                 return error;
1623         vfslocked = NDHASGIANT(&nd);
1624
1625         ncopy = min(uap->bufsiz, strlen(nd.ni_cnd.cn_pnbuf) + 1);
1626         if ((error = copyout(nd.ni_cnd.cn_pnbuf, uap->buf, ncopy)) != 0)
1627                 goto bad;
1628
1629         *retval = ncopy;
1630 bad:
1631         NDFREE(&nd, NDF_ONLY_PNBUF);
1632         vput(nd.ni_vp);
1633         VFS_UNLOCK_GIANT(vfslocked);
1634         return error;
1635 }