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