]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/compat/svr4/svr4_misc.c
This commit was generated by cvs2svn to compensate for changes in r167817,
[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/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_EXCLUSIVE | 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_EXCLUSIVE | 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_cred(td->td_ucred, PRIV_VFS_FCHROOT,
616             SUSER_ALLOWJAIL)) != 0)
617                 return error;
618         if ((error = getvnode(fdp, uap->fd, &fp)) != 0)
619                 return error;
620         vp = fp->f_vnode;
621         VREF(vp);
622         fdrop(fp, td);
623         vfslocked = VFS_LOCK_GIANT(vp->v_mount);
624         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
625         error = change_dir(vp, td);
626         if (error)
627                 goto fail;
628 #ifdef MAC
629         error = mac_check_vnode_chroot(td->td_ucred, vp);
630         if (error)
631                 goto fail;
632 #endif
633         VOP_UNLOCK(vp, 0, td);
634         error = change_root(vp, td);
635         vrele(vp);
636         VFS_UNLOCK_GIANT(vfslocked);
637         return (error);
638 fail:
639         vput(vp);
640         VFS_UNLOCK_GIANT(vfslocked);
641         return (error);
642 }
643
644
645 static int
646 svr4_mknod(td, retval, path, mode, dev)
647         struct thread *td;
648         register_t *retval;
649         char *path;
650         svr4_mode_t mode;
651         svr4_dev_t dev;
652 {
653         char *newpath;
654         int error;
655
656         CHECKALTEXIST(td, path, &newpath);
657
658         if (S_ISFIFO(mode))
659                 error = kern_mkfifo(td, newpath, UIO_SYSSPACE, mode);
660         else
661                 error = kern_mknod(td, newpath, UIO_SYSSPACE, mode, dev);
662         free(newpath, M_TEMP);
663         return (error);
664 }
665
666
667 int
668 svr4_sys_mknod(td, uap)
669         register struct thread *td;
670         struct svr4_sys_mknod_args *uap;
671 {
672         int *retval = td->td_retval;
673         return svr4_mknod(td, retval,
674                           uap->path, uap->mode,
675                           (svr4_dev_t)svr4_to_bsd_odev_t(uap->dev));
676 }
677
678
679 int
680 svr4_sys_xmknod(td, uap)
681         struct thread *td;
682         struct svr4_sys_xmknod_args *uap;
683 {
684         int *retval = td->td_retval;
685         return svr4_mknod(td, retval,
686                           uap->path, uap->mode,
687                           (svr4_dev_t)svr4_to_bsd_dev_t(uap->dev));
688 }
689
690
691 int
692 svr4_sys_vhangup(td, uap)
693         struct thread *td;
694         struct svr4_sys_vhangup_args *uap;
695 {
696         return 0;
697 }
698
699
700 int
701 svr4_sys_sysconfig(td, uap)
702         struct thread *td;
703         struct svr4_sys_sysconfig_args *uap;
704 {
705         int *retval;
706
707         retval = &(td->td_retval[0]);
708
709         switch (uap->name) {
710         case SVR4_CONFIG_UNUSED:
711                 *retval = 0;
712                 break;
713         case SVR4_CONFIG_NGROUPS:
714                 *retval = NGROUPS_MAX;
715                 break;
716         case SVR4_CONFIG_CHILD_MAX:
717                 *retval = maxproc;
718                 break;
719         case SVR4_CONFIG_OPEN_FILES:
720                 *retval = maxfiles;
721                 break;
722         case SVR4_CONFIG_POSIX_VER:
723                 *retval = 198808;
724                 break;
725         case SVR4_CONFIG_PAGESIZE:
726                 *retval = PAGE_SIZE;
727                 break;
728         case SVR4_CONFIG_CLK_TCK:
729                 *retval = 60;   /* should this be `hz', ie. 100? */
730                 break;
731         case SVR4_CONFIG_XOPEN_VER:
732                 *retval = 2;    /* XXX: What should that be? */
733                 break;
734         case SVR4_CONFIG_PROF_TCK:
735                 *retval = 60;   /* XXX: What should that be? */
736                 break;
737         case SVR4_CONFIG_NPROC_CONF:
738                 *retval = 1;    /* Only one processor for now */
739                 break;
740         case SVR4_CONFIG_NPROC_ONLN:
741                 *retval = 1;    /* And it better be online */
742                 break;
743         case SVR4_CONFIG_AIO_LISTIO_MAX:
744         case SVR4_CONFIG_AIO_MAX:
745         case SVR4_CONFIG_AIO_PRIO_DELTA_MAX:
746                 *retval = 0;    /* No aio support */
747                 break;
748         case SVR4_CONFIG_DELAYTIMER_MAX:
749                 *retval = 0;    /* No delaytimer support */
750                 break;
751         case SVR4_CONFIG_MQ_OPEN_MAX:
752                 *retval = msginfo.msgmni;
753                 break;
754         case SVR4_CONFIG_MQ_PRIO_MAX:
755                 *retval = 0;    /* XXX: Don't know */
756                 break;
757         case SVR4_CONFIG_RTSIG_MAX:
758                 *retval = 0;
759                 break;
760         case SVR4_CONFIG_SEM_NSEMS_MAX:
761                 *retval = seminfo.semmni;
762                 break;
763         case SVR4_CONFIG_SEM_VALUE_MAX:
764                 *retval = seminfo.semvmx;
765                 break;
766         case SVR4_CONFIG_SIGQUEUE_MAX:
767                 *retval = 0;    /* XXX: Don't know */
768                 break;
769         case SVR4_CONFIG_SIGRT_MIN:
770         case SVR4_CONFIG_SIGRT_MAX:
771                 *retval = 0;    /* No real time signals */
772                 break;
773         case SVR4_CONFIG_TIMER_MAX:
774                 *retval = 3;    /* XXX: real, virtual, profiling */
775                 break;
776 #if defined(NOTYET)
777         case SVR4_CONFIG_PHYS_PAGES:
778 #if defined(UVM)
779                 *retval = uvmexp.free;  /* XXX: free instead of total */
780 #else
781                 *retval = cnt.v_free_count;     /* XXX: free instead of total */
782 #endif
783                 break;
784         case SVR4_CONFIG_AVPHYS_PAGES:
785 #if defined(UVM)
786                 *retval = uvmexp.active;        /* XXX: active instead of avg */
787 #else
788                 *retval = cnt.v_active_count;   /* XXX: active instead of avg */
789 #endif
790                 break;
791 #endif /* NOTYET */
792
793         default:
794                 return EINVAL;
795         }
796         return 0;
797 }
798
799 /* ARGSUSED */
800 int
801 svr4_sys_break(td, uap)
802         struct thread *td;
803         struct svr4_sys_break_args *uap;
804 {
805         struct obreak_args ap;
806
807         ap.nsize = uap->nsize;
808         return (obreak(td, &ap));
809 }
810
811 static __inline clock_t
812 timeval_to_clock_t(tv)
813         struct timeval *tv;
814 {
815         return tv->tv_sec * hz + tv->tv_usec / (1000000 / hz);
816 }
817
818
819 int
820 svr4_sys_times(td, uap)
821         struct thread *td;
822         struct svr4_sys_times_args *uap;
823 {
824         struct timeval tv, utime, stime, cutime, cstime;
825         struct tms tms;
826         struct proc *p;
827         int error;
828
829         p = td->td_proc;
830         PROC_LOCK(p);
831         calcru(p, &utime, &stime);
832         calccru(p, &cutime, &cstime);
833         PROC_UNLOCK(p);
834
835         tms.tms_utime = timeval_to_clock_t(&utime);
836         tms.tms_stime = timeval_to_clock_t(&stime);
837
838         tms.tms_cutime = timeval_to_clock_t(&cutime);
839         tms.tms_cstime = timeval_to_clock_t(&cstime);
840
841         error = copyout(&tms, uap->tp, sizeof(tms));
842         if (error)
843                 return (error);
844
845         microtime(&tv);
846         td->td_retval[0] = (int)timeval_to_clock_t(&tv);
847         return (0);
848 }
849
850
851 int
852 svr4_sys_ulimit(td, uap)
853         struct thread *td;
854         struct svr4_sys_ulimit_args *uap;
855 {
856         int *retval = td->td_retval;
857         int error;
858
859         switch (uap->cmd) {
860         case SVR4_GFILLIM:
861                 PROC_LOCK(td->td_proc);
862                 *retval = lim_cur(td->td_proc, RLIMIT_FSIZE) / 512;
863                 PROC_UNLOCK(td->td_proc);
864                 if (*retval == -1)
865                         *retval = 0x7fffffff;
866                 return 0;
867
868         case SVR4_SFILLIM:
869                 {
870                         struct rlimit krl;
871
872                         krl.rlim_cur = uap->newlimit * 512;
873                         PROC_LOCK(td->td_proc);
874                         krl.rlim_max = lim_max(td->td_proc, RLIMIT_FSIZE);
875                         PROC_UNLOCK(td->td_proc);
876
877                         error = kern_setrlimit(td, RLIMIT_FSIZE, &krl);
878                         if (error)
879                                 return error;
880
881                         PROC_LOCK(td->td_proc);
882                         *retval = lim_cur(td->td_proc, RLIMIT_FSIZE);
883                         PROC_UNLOCK(td->td_proc);
884                         if (*retval == -1)
885                                 *retval = 0x7fffffff;
886                         return 0;
887                 }
888
889         case SVR4_GMEMLIM:
890                 {
891                         struct vmspace *vm = td->td_proc->p_vmspace;
892                         register_t r;
893
894                         PROC_LOCK(td->td_proc);
895                         r = lim_cur(td->td_proc, RLIMIT_DATA);
896                         PROC_UNLOCK(td->td_proc);
897
898                         if (r == -1)
899                                 r = 0x7fffffff;
900                         mtx_lock(&Giant);       /* XXX */
901                         r += (long) vm->vm_daddr;
902                         mtx_unlock(&Giant);
903                         if (r < 0)
904                                 r = 0x7fffffff;
905                         *retval = r;
906                         return 0;
907                 }
908
909         case SVR4_GDESLIM:
910                 PROC_LOCK(td->td_proc);
911                 *retval = lim_cur(td->td_proc, RLIMIT_NOFILE);
912                 PROC_UNLOCK(td->td_proc);
913                 if (*retval == -1)
914                         *retval = 0x7fffffff;
915                 return 0;
916
917         default:
918                 return EINVAL;
919         }
920 }
921
922 static struct proc *
923 svr4_pfind(pid)
924         pid_t pid;
925 {
926         struct proc *p;
927
928         /* look in the live processes */
929         if ((p = pfind(pid)) == NULL)
930                 /* look in the zombies */
931                 p = zpfind(pid);
932
933         return p;
934 }
935
936
937 int
938 svr4_sys_pgrpsys(td, uap)
939         struct thread *td;
940         struct svr4_sys_pgrpsys_args *uap;
941 {
942         int *retval = td->td_retval;
943         struct proc *p = td->td_proc;
944
945         switch (uap->cmd) {
946         case 1:                 /* setpgrp() */
947                 /*
948                  * SVR4 setpgrp() (which takes no arguments) has the
949                  * semantics that the session ID is also created anew, so
950                  * in almost every sense, setpgrp() is identical to
951                  * setsid() for SVR4.  (Under BSD, the difference is that
952                  * a setpgid(0,0) will not create a new session.)
953                  */
954                 setsid(td, NULL);
955                 /*FALLTHROUGH*/
956
957         case 0:                 /* getpgrp() */
958                 PROC_LOCK(p);
959                 *retval = p->p_pgrp->pg_id;
960                 PROC_UNLOCK(p);
961                 return 0;
962
963         case 2:                 /* getsid(pid) */
964                 if (uap->pid == 0)
965                         PROC_LOCK(p);
966                 else if ((p = svr4_pfind(uap->pid)) == NULL)
967                         return ESRCH;
968                 /*
969                  * This has already been initialized to the pid of
970                  * the session leader.
971                  */
972                 *retval = (register_t) p->p_session->s_sid;
973                 PROC_UNLOCK(p);
974                 return 0;
975
976         case 3:                 /* setsid() */
977                 return setsid(td, NULL);
978
979         case 4:                 /* getpgid(pid) */
980
981                 if (uap->pid == 0)
982                         PROC_LOCK(p);
983                 else if ((p = svr4_pfind(uap->pid)) == NULL)
984                         return ESRCH;
985
986                 *retval = (int) p->p_pgrp->pg_id;
987                 PROC_UNLOCK(p);
988                 return 0;
989
990         case 5:                 /* setpgid(pid, pgid); */
991                 {
992                         struct setpgid_args sa;
993
994                         sa.pid = uap->pid;
995                         sa.pgid = uap->pgid;
996                         return setpgid(td, &sa);
997                 }
998
999         default:
1000                 return EINVAL;
1001         }
1002 }
1003
1004 struct svr4_hrtcntl_args {
1005         int                     cmd;
1006         int                     fun;
1007         int                     clk;
1008         svr4_hrt_interval_t *   iv;
1009         svr4_hrt_time_t *       ti;
1010 };
1011
1012
1013 static int
1014 svr4_hrtcntl(td, uap, retval)
1015         struct thread *td;
1016         struct svr4_hrtcntl_args *uap;
1017         register_t *retval;
1018 {
1019         switch (uap->fun) {
1020         case SVR4_HRT_CNTL_RES:
1021                 DPRINTF(("htrcntl(RES)\n"));
1022                 *retval = SVR4_HRT_USEC;
1023                 return 0;
1024
1025         case SVR4_HRT_CNTL_TOFD:
1026                 DPRINTF(("htrcntl(TOFD)\n"));
1027                 {
1028                         struct timeval tv;
1029                         svr4_hrt_time_t t;
1030                         if (uap->clk != SVR4_HRT_CLK_STD) {
1031                                 DPRINTF(("clk == %d\n", uap->clk));
1032                                 return EINVAL;
1033                         }
1034                         if (uap->ti == NULL) {
1035                                 DPRINTF(("ti NULL\n"));
1036                                 return EINVAL;
1037                         }
1038                         microtime(&tv);
1039                         t.h_sec = tv.tv_sec;
1040                         t.h_rem = tv.tv_usec;
1041                         t.h_res = SVR4_HRT_USEC;
1042                         return copyout(&t, uap->ti, sizeof(t));
1043                 }
1044
1045         case SVR4_HRT_CNTL_START:
1046                 DPRINTF(("htrcntl(START)\n"));
1047                 return ENOSYS;
1048
1049         case SVR4_HRT_CNTL_GET:
1050                 DPRINTF(("htrcntl(GET)\n"));
1051                 return ENOSYS;
1052         default:
1053                 DPRINTF(("Bad htrcntl command %d\n", uap->fun));
1054                 return ENOSYS;
1055         }
1056 }
1057
1058
1059 int
1060 svr4_sys_hrtsys(td, uap) 
1061         struct thread *td;
1062         struct svr4_sys_hrtsys_args *uap;
1063 {
1064         int *retval = td->td_retval;
1065
1066         switch (uap->cmd) {
1067         case SVR4_HRT_CNTL:
1068                 return svr4_hrtcntl(td, (struct svr4_hrtcntl_args *) uap,
1069                                     retval);
1070
1071         case SVR4_HRT_ALRM:
1072                 DPRINTF(("hrtalarm\n"));
1073                 return ENOSYS;
1074
1075         case SVR4_HRT_SLP:
1076                 DPRINTF(("hrtsleep\n"));
1077                 return ENOSYS;
1078
1079         case SVR4_HRT_CAN:
1080                 DPRINTF(("hrtcancel\n"));
1081                 return ENOSYS;
1082
1083         default:
1084                 DPRINTF(("Bad hrtsys command %d\n", uap->cmd));
1085                 return EINVAL;
1086         }
1087 }
1088
1089
1090 static int
1091 svr4_setinfo(pid, ru, st, s)
1092         pid_t pid;
1093         struct rusage *ru;
1094         int st;
1095         svr4_siginfo_t *s;
1096 {
1097         svr4_siginfo_t i;
1098         int sig;
1099
1100         memset(&i, 0, sizeof(i));
1101
1102         i.svr4_si_signo = SVR4_SIGCHLD;
1103         i.svr4_si_errno = 0;    /* XXX? */
1104
1105         i.svr4_si_pid = pid;
1106         if (ru) {
1107                 i.svr4_si_stime = ru->ru_stime.tv_sec;
1108                 i.svr4_si_utime = ru->ru_utime.tv_sec;
1109         }
1110
1111         if (WIFEXITED(st)) {
1112                 i.svr4_si_status = WEXITSTATUS(st);
1113                 i.svr4_si_code = SVR4_CLD_EXITED;
1114         } else if (WIFSTOPPED(st)) {
1115                 sig = WSTOPSIG(st);
1116                 if (sig >= 0 && sig < NSIG)
1117                         i.svr4_si_status = SVR4_BSD2SVR4_SIG(sig);
1118
1119                 if (i.svr4_si_status == SVR4_SIGCONT)
1120                         i.svr4_si_code = SVR4_CLD_CONTINUED;
1121                 else
1122                         i.svr4_si_code = SVR4_CLD_STOPPED;
1123         } else {
1124                 sig = WTERMSIG(st);
1125                 if (sig >= 0 && sig < NSIG)
1126                         i.svr4_si_status = SVR4_BSD2SVR4_SIG(sig);
1127
1128                 if (WCOREDUMP(st))
1129                         i.svr4_si_code = SVR4_CLD_DUMPED;
1130                 else
1131                         i.svr4_si_code = SVR4_CLD_KILLED;
1132         }
1133
1134         DPRINTF(("siginfo [pid %ld signo %d code %d errno %d status %d]\n",
1135                  i.svr4_si_pid, i.svr4_si_signo, i.svr4_si_code, i.svr4_si_errno,
1136                  i.svr4_si_status));
1137
1138         return copyout(&i, s, sizeof(i));
1139 }
1140
1141
1142 int
1143 svr4_sys_waitsys(td, uap)
1144         struct thread *td;
1145         struct svr4_sys_waitsys_args *uap;
1146 {
1147         struct rusage ru;
1148         pid_t pid;
1149         int nfound, status;
1150         int error, *retval = td->td_retval;
1151         struct proc *p, *q;
1152
1153         DPRINTF(("waitsys(%d, %d, %p, %x)\n", 
1154                  uap->grp, uap->id,
1155                  uap->info, uap->options));
1156
1157         q = td->td_proc;
1158         switch (uap->grp) {
1159         case SVR4_P_PID:
1160                 pid = uap->id;
1161                 break;
1162
1163         case SVR4_P_PGID:
1164                 PROC_LOCK(q);
1165                 pid = -q->p_pgid;
1166                 PROC_UNLOCK(q);
1167                 break;
1168
1169         case SVR4_P_ALL:
1170                 pid = WAIT_ANY;
1171                 break;
1172
1173         default:
1174                 return EINVAL;
1175         }
1176
1177         /* Hand off the easy cases to kern_wait(). */
1178         if (!(uap->options & (SVR4_WNOWAIT)) &&
1179             (uap->options & (SVR4_WEXITED | SVR4_WTRAPPED))) {
1180                 int options;
1181
1182                 options = 0;
1183                 if (uap->options & SVR4_WSTOPPED)
1184                         options |= WUNTRACED;
1185                 if (uap->options & SVR4_WCONTINUED)
1186                         options |= WCONTINUED;
1187                 if (uap->options & SVR4_WNOHANG)
1188                         options |= WNOHANG;
1189
1190                 error = kern_wait(td, pid, &status, options, &ru);
1191                 if (error)
1192                         return (error);
1193                 if (uap->options & SVR4_WNOHANG && *retval == 0)
1194                         error = svr4_setinfo(*retval, NULL, 0, uap->info);
1195                 else
1196                         error = svr4_setinfo(*retval, &ru, status, uap->info);
1197                 *retval = 0;
1198                 return (error);
1199         }
1200
1201         /*
1202          * Ok, handle the weird cases.  Either WNOWAIT is set (meaning we
1203          * just want to see if there is a process to harvest, we dont'
1204          * want to actually harvest it), or WEXIT and WTRAPPED are clear
1205          * meaning we want to ignore zombies.  Either way, we don't have
1206          * to handle harvesting zombies here.  We do have to duplicate the
1207          * other portions of kern_wait() though, especially for the
1208          * WCONTINUED and WSTOPPED.
1209          */
1210 loop:
1211         nfound = 0;
1212         sx_slock(&proctree_lock);
1213         LIST_FOREACH(p, &q->p_children, p_sibling) {
1214                 PROC_LOCK(p);
1215                 if (pid != WAIT_ANY &&
1216                     p->p_pid != pid && p->p_pgid != -pid) {
1217                         PROC_UNLOCK(p);
1218                         DPRINTF(("pid %d pgid %d != %d\n", p->p_pid,
1219                                  p->p_pgid, pid));
1220                         continue;
1221                 }
1222                 if (p_canwait(td, p)) {
1223                         PROC_UNLOCK(p);
1224                         continue;
1225                 }
1226
1227                 nfound++;
1228
1229                 /*
1230                  * See if we have a zombie.  If so, WNOWAIT should be set,
1231                  * as otherwise we should have called kern_wait() up above.
1232                  */
1233                 if ((p->p_state == PRS_ZOMBIE) && 
1234                     ((uap->options & (SVR4_WEXITED|SVR4_WTRAPPED)))) {
1235                         KASSERT(uap->options & SVR4_WNOWAIT,
1236                             ("WNOWAIT is clear"));
1237
1238                         /* Found a zombie, so cache info in local variables. */
1239                         pid = p->p_pid;
1240                         status = p->p_xstat;
1241                         ru = *p->p_ru;
1242                         calcru(p, &ru.ru_utime, &ru.ru_stime);
1243                         PROC_UNLOCK(p);
1244                         sx_sunlock(&proctree_lock);
1245
1246                         /* Copy the info out to userland. */
1247                         *retval = 0;
1248                         DPRINTF(("found %d\n", pid));
1249                         return (svr4_setinfo(pid, &ru, status, uap->info));
1250                 }
1251
1252                 /*
1253                  * See if we have a stopped or continued process.
1254                  * XXX: This duplicates the same code in kern_wait().
1255                  */
1256                 mtx_lock_spin(&sched_lock);
1257                 if ((p->p_flag & P_STOPPED_SIG) &&
1258                     (p->p_suspcount == p->p_numthreads) &&
1259                     (p->p_flag & P_WAITED) == 0 &&
1260                     (p->p_flag & P_TRACED || uap->options & SVR4_WSTOPPED)) {
1261                         mtx_unlock_spin(&sched_lock);
1262                         if (((uap->options & SVR4_WNOWAIT)) == 0)
1263                                 p->p_flag |= P_WAITED;
1264                         sx_sunlock(&proctree_lock);
1265                         pid = p->p_pid;
1266                         status = W_STOPCODE(p->p_xstat);
1267                         ru = *p->p_ru;
1268                         calcru(p, &ru.ru_utime, &ru.ru_stime);
1269                         PROC_UNLOCK(p);
1270
1271                         if (((uap->options & SVR4_WNOWAIT)) == 0) {
1272                                 PROC_LOCK(q);
1273                                 sigqueue_take(p->p_ksi);
1274                                 PROC_UNLOCK(q);
1275                         }
1276
1277                         *retval = 0;
1278                         DPRINTF(("jobcontrol %d\n", pid));
1279                         return (svr4_setinfo(pid, &ru, status, uap->info));
1280                 }
1281                 mtx_unlock_spin(&sched_lock);
1282                 if (uap->options & SVR4_WCONTINUED &&
1283                     (p->p_flag & P_CONTINUED)) {
1284                         sx_sunlock(&proctree_lock);
1285                         if (((uap->options & SVR4_WNOWAIT)) == 0)
1286                                 p->p_flag &= ~P_CONTINUED;
1287                         pid = p->p_pid;
1288                         ru = *p->p_ru;
1289                         status = SIGCONT;
1290                         calcru(p, &ru.ru_utime, &ru.ru_stime);
1291                         PROC_UNLOCK(p);
1292
1293                         if (((uap->options & SVR4_WNOWAIT)) == 0) {
1294                                 PROC_LOCK(q);
1295                                 sigqueue_take(p->p_ksi);
1296                                 PROC_UNLOCK(q);
1297                         }
1298
1299                         *retval = 0;
1300                         DPRINTF(("jobcontrol %d\n", pid));
1301                         return (svr4_setinfo(pid, &ru, status, uap->info));
1302                 }
1303                 PROC_UNLOCK(p);
1304         }
1305
1306         if (nfound == 0) {
1307                 sx_sunlock(&proctree_lock);
1308                 return (ECHILD);
1309         }
1310
1311         if (uap->options & SVR4_WNOHANG) {
1312                 sx_sunlock(&proctree_lock);
1313                 *retval = 0;
1314                 return (svr4_setinfo(0, NULL, 0, uap->info));
1315         }
1316
1317         PROC_LOCK(q);
1318         sx_sunlock(&proctree_lock);
1319         if (q->p_flag & P_STATCHILD) {
1320                 q->p_flag &= ~P_STATCHILD;
1321                 error = 0;
1322         } else
1323                 error = msleep(q, &q->p_mtx, PWAIT | PCATCH, "svr4_wait", 0);
1324         PROC_UNLOCK(q);
1325         if (error)
1326                 return error;
1327         goto loop;
1328 }
1329
1330
1331 static void
1332 bsd_statfs_to_svr4_statvfs(bfs, sfs)
1333         const struct statfs *bfs;
1334         struct svr4_statvfs *sfs;
1335 {
1336         sfs->f_bsize = bfs->f_iosize; /* XXX */
1337         sfs->f_frsize = bfs->f_bsize;
1338         sfs->f_blocks = bfs->f_blocks;
1339         sfs->f_bfree = bfs->f_bfree;
1340         sfs->f_bavail = bfs->f_bavail;
1341         sfs->f_files = bfs->f_files;
1342         sfs->f_ffree = bfs->f_ffree;
1343         sfs->f_favail = bfs->f_ffree;
1344         sfs->f_fsid = bfs->f_fsid.val[0];
1345         memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1346         sfs->f_flag = 0;
1347         if (bfs->f_flags & MNT_RDONLY)
1348                 sfs->f_flag |= SVR4_ST_RDONLY;
1349         if (bfs->f_flags & MNT_NOSUID)
1350                 sfs->f_flag |= SVR4_ST_NOSUID;
1351         sfs->f_namemax = MAXNAMLEN;
1352         memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1353         memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1354 }
1355
1356
1357 static void
1358 bsd_statfs_to_svr4_statvfs64(bfs, sfs)
1359         const struct statfs *bfs;
1360         struct svr4_statvfs64 *sfs;
1361 {
1362         sfs->f_bsize = bfs->f_iosize; /* XXX */
1363         sfs->f_frsize = bfs->f_bsize;
1364         sfs->f_blocks = bfs->f_blocks;
1365         sfs->f_bfree = bfs->f_bfree;
1366         sfs->f_bavail = bfs->f_bavail;
1367         sfs->f_files = bfs->f_files;
1368         sfs->f_ffree = bfs->f_ffree;
1369         sfs->f_favail = bfs->f_ffree;
1370         sfs->f_fsid = bfs->f_fsid.val[0];
1371         memcpy(sfs->f_basetype, bfs->f_fstypename, sizeof(sfs->f_basetype));
1372         sfs->f_flag = 0;
1373         if (bfs->f_flags & MNT_RDONLY)
1374                 sfs->f_flag |= SVR4_ST_RDONLY;
1375         if (bfs->f_flags & MNT_NOSUID)
1376                 sfs->f_flag |= SVR4_ST_NOSUID;
1377         sfs->f_namemax = MAXNAMLEN;
1378         memcpy(sfs->f_fstr, bfs->f_fstypename, sizeof(sfs->f_fstr)); /* XXX */
1379         memset(sfs->f_filler, 0, sizeof(sfs->f_filler));
1380 }
1381
1382
1383 int
1384 svr4_sys_statvfs(td, uap)
1385         struct thread *td;
1386         struct svr4_sys_statvfs_args *uap;
1387 {
1388         struct svr4_statvfs sfs;
1389         struct statfs bfs;
1390         char *path;
1391         int error;
1392
1393         CHECKALTEXIST(td, uap->path, &path);
1394
1395         error = kern_statfs(td, path, UIO_SYSSPACE, &bfs);
1396         free(path, M_TEMP);
1397         if (error)
1398                 return (error);
1399         bsd_statfs_to_svr4_statvfs(&bfs, &sfs);
1400         return copyout(&sfs, uap->fs, sizeof(sfs));
1401 }
1402
1403
1404 int
1405 svr4_sys_fstatvfs(td, uap)
1406         struct thread *td;
1407         struct svr4_sys_fstatvfs_args *uap;
1408 {
1409         struct svr4_statvfs sfs;
1410         struct statfs bfs;
1411         int error;
1412
1413         error = kern_fstatfs(td, uap->fd, &bfs);
1414         if (error)
1415                 return (error);
1416         bsd_statfs_to_svr4_statvfs(&bfs, &sfs);
1417         return copyout(&sfs, uap->fs, sizeof(sfs));
1418 }
1419
1420
1421 int
1422 svr4_sys_statvfs64(td, uap)
1423         struct thread *td;
1424         struct svr4_sys_statvfs64_args *uap;
1425 {
1426         struct svr4_statvfs64 sfs;
1427         struct statfs bfs;
1428         char *path;
1429         int error;
1430
1431         CHECKALTEXIST(td, uap->path, &path);
1432
1433         error = kern_statfs(td, path, UIO_SYSSPACE, &bfs);
1434         free(path, M_TEMP);
1435         if (error)
1436                 return (error);
1437         bsd_statfs_to_svr4_statvfs64(&bfs, &sfs);
1438         return copyout(&sfs, uap->fs, sizeof(sfs));
1439 }
1440
1441
1442 int
1443 svr4_sys_fstatvfs64(td, uap) 
1444         struct thread *td;
1445         struct svr4_sys_fstatvfs64_args *uap;
1446 {
1447         struct svr4_statvfs64 sfs;
1448         struct statfs bfs;
1449         int error;
1450
1451         error = kern_fstatfs(td, uap->fd, &bfs);
1452         if (error)
1453                 return (error);
1454         bsd_statfs_to_svr4_statvfs64(&bfs, &sfs);
1455         return copyout(&sfs, uap->fs, sizeof(sfs));
1456 }
1457
1458 int
1459 svr4_sys_alarm(td, uap)
1460         struct thread *td;
1461         struct svr4_sys_alarm_args *uap;
1462 {
1463         struct itimerval itv, oitv;
1464         int error;
1465
1466         timevalclear(&itv.it_interval);
1467         itv.it_value.tv_sec = uap->sec;
1468         itv.it_value.tv_usec = 0;
1469         error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv);
1470         if (error)
1471                 return (error);
1472         if (oitv.it_value.tv_usec != 0)
1473                 oitv.it_value.tv_sec++;
1474         td->td_retval[0] = oitv.it_value.tv_sec;
1475         return (0);
1476 }
1477
1478 int
1479 svr4_sys_gettimeofday(td, uap)
1480         struct thread *td;
1481         struct svr4_sys_gettimeofday_args *uap;
1482 {
1483         if (uap->tp) {
1484                 struct timeval atv;
1485
1486                 microtime(&atv);
1487                 return copyout(&atv, uap->tp, sizeof (atv));
1488         }
1489
1490         return 0;
1491 }
1492
1493 int
1494 svr4_sys_facl(td, uap)
1495         struct thread *td;
1496         struct svr4_sys_facl_args *uap;
1497 {
1498         int *retval;
1499
1500         retval = td->td_retval;
1501         *retval = 0;
1502
1503         switch (uap->cmd) {
1504         case SVR4_SYS_SETACL:
1505                 /* We don't support acls on any filesystem */
1506                 return ENOSYS;
1507
1508         case SVR4_SYS_GETACL:
1509                 return copyout(retval, &uap->num,
1510                     sizeof(uap->num));
1511
1512         case SVR4_SYS_GETACLCNT:
1513                 return 0;
1514
1515         default:
1516                 return EINVAL;
1517         }
1518 }
1519
1520
1521 int
1522 svr4_sys_acl(td, uap)
1523         struct thread *td;
1524         struct svr4_sys_acl_args *uap;
1525 {
1526         /* XXX: for now the same */
1527         return svr4_sys_facl(td, (struct svr4_sys_facl_args *)uap);
1528 }
1529
1530 int
1531 svr4_sys_auditsys(td, uap)
1532         struct thread *td;
1533         struct svr4_sys_auditsys_args *uap;
1534 {
1535         /*
1536          * XXX: Big brother is *not* watching.
1537          */
1538         return 0;
1539 }
1540
1541 int
1542 svr4_sys_memcntl(td, uap)
1543         struct thread *td;
1544         struct svr4_sys_memcntl_args *uap;
1545 {
1546         switch (uap->cmd) {
1547         case SVR4_MC_SYNC:
1548                 {
1549                         struct msync_args msa;
1550
1551                         msa.addr = uap->addr;
1552                         msa.len = uap->len;
1553                         msa.flags = (int)uap->arg;
1554
1555                         return msync(td, &msa);
1556                 }
1557         case SVR4_MC_ADVISE:
1558                 {
1559                         struct madvise_args maa;
1560
1561                         maa.addr = uap->addr;
1562                         maa.len = uap->len;
1563                         maa.behav = (int)uap->arg;
1564
1565                         return madvise(td, &maa);
1566                 }
1567         case SVR4_MC_LOCK:
1568         case SVR4_MC_UNLOCK:
1569         case SVR4_MC_LOCKAS:
1570         case SVR4_MC_UNLOCKAS:
1571                 return EOPNOTSUPP;
1572         default:
1573                 return ENOSYS;
1574         }
1575 }
1576
1577
1578 int
1579 svr4_sys_nice(td, uap)
1580         struct thread *td;
1581         struct svr4_sys_nice_args *uap;
1582 {
1583         struct setpriority_args ap;
1584         int error;
1585
1586         ap.which = PRIO_PROCESS;
1587         ap.who = 0;
1588         ap.prio = uap->prio;
1589
1590         if ((error = setpriority(td, &ap)) != 0)
1591                 return error;
1592
1593         /* the cast is stupid, but the structures are the same */
1594         if ((error = getpriority(td, (struct getpriority_args *)&ap)) != 0)
1595                 return error;
1596
1597         return 0;
1598 }
1599
1600 int
1601 svr4_sys_resolvepath(td, uap)
1602         struct thread *td;
1603         struct svr4_sys_resolvepath_args *uap;
1604 {
1605         struct nameidata nd;
1606         int error, *retval = td->td_retval;
1607         unsigned int ncopy;
1608         int vfslocked;
1609
1610         NDINIT(&nd, LOOKUP, NOFOLLOW | SAVENAME | MPSAFE, UIO_USERSPACE,
1611             uap->path, td);
1612
1613         if ((error = namei(&nd)) != 0)
1614                 return error;
1615         vfslocked = NDHASGIANT(&nd);
1616
1617         ncopy = min(uap->bufsiz, strlen(nd.ni_cnd.cn_pnbuf) + 1);
1618         if ((error = copyout(nd.ni_cnd.cn_pnbuf, uap->buf, ncopy)) != 0)
1619                 goto bad;
1620
1621         *retval = ncopy;
1622 bad:
1623         NDFREE(&nd, NDF_ONLY_PNBUF);
1624         vput(nd.ni_vp);
1625         VFS_UNLOCK_GIANT(vfslocked);
1626         return error;
1627 }