sunos_misc.c revision 1.149 1 /* $NetBSD: sunos_misc.c,v 1.149 2007/05/12 20:27:56 dsl Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
10 *
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratory.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * @(#)sunos_misc.c 8.1 (Berkeley) 6/18/93
41 *
42 * Header: sunos_misc.c,v 1.16 93/04/07 02:46:27 torek Exp
43 */
44
45 /*
46 * SunOS compatibility module.
47 *
48 * SunOS system calls that are implemented differently in BSD are
49 * handled here.
50 */
51
52 #include <sys/cdefs.h>
53 __KERNEL_RCSID(0, "$NetBSD: sunos_misc.c,v 1.149 2007/05/12 20:27:56 dsl Exp $");
54
55 #if defined(_KERNEL_OPT)
56 #include "opt_nfsserver.h"
57 #include "opt_ptrace.h"
58 #include "fs_nfs.h"
59 #endif
60
61 #include <sys/param.h>
62 #include <sys/systm.h>
63 #include <sys/namei.h>
64 #include <sys/proc.h>
65 #include <sys/dirent.h>
66 #include <sys/file.h>
67 #include <sys/stat.h>
68 #include <sys/filedesc.h>
69 #include <sys/ioctl.h>
70 #include <sys/kernel.h>
71 #include <sys/reboot.h>
72 #include <sys/malloc.h>
73 #include <sys/mbuf.h>
74 #include <sys/mman.h>
75 #include <sys/mount.h>
76 #include <sys/ptrace.h>
77 #include <sys/resource.h>
78 #include <sys/resourcevar.h>
79 #include <sys/signal.h>
80 #include <sys/signalvar.h>
81 #include <sys/socket.h>
82 #include <sys/tty.h>
83 #include <sys/vnode.h>
84 #include <sys/uio.h>
85 #include <sys/wait.h>
86 #include <sys/utsname.h>
87 #include <sys/unistd.h>
88 #include <sys/syscall.h>
89 #include <sys/syscallargs.h>
90 #include <sys/conf.h>
91 #include <sys/socketvar.h>
92 #include <sys/exec.h>
93 #include <sys/swap.h>
94 #include <sys/kauth.h>
95
96 #include <compat/sys/signal.h>
97
98 #include <compat/sunos/sunos.h>
99 #include <compat/sunos/sunos_syscallargs.h>
100 #include <compat/common/compat_util.h>
101 #include <compat/sunos/sunos_dirent.h>
102
103 #include <netinet/in.h>
104
105 #include <miscfs/specfs/specdev.h>
106
107 #include <nfs/rpcv2.h>
108 #include <nfs/nfsproto.h>
109 #include <nfs/nfs.h>
110 #include <nfs/nfsmount.h>
111
112 static int sunstatfs __P((struct statvfs *, void *));
113
114 int
115 sunos_sys_stime(l, v, retval)
116 struct lwp *l;
117 void *v;
118 register_t *retval;
119 {
120 struct sunos_sys_stime_args *uap = v;
121 struct timeval tv;
122 int error;
123
124 error = copyin(SCARG(uap, tp), &tv.tv_sec, sizeof(tv.tv_sec));
125 if (error)
126 return error;
127 tv.tv_usec = 0;
128
129 return settimeofday1(&tv, false, NULL, l, true);
130 }
131
132 int
133 sunos_sys_wait4(l, v, retval)
134 struct lwp *l;
135 void *v;
136 register_t *retval;
137 {
138 struct sunos_sys_wait4_args *uap = v;
139 if (SCARG(uap, pid) == 0)
140 SCARG(uap, pid) = WAIT_ANY;
141 return (sys_wait4(l, uap, retval));
142 }
143
144 int
145 sunos_sys_creat(l, v, retval)
146 struct lwp *l;
147 void *v;
148 register_t *retval;
149 {
150 struct sunos_sys_creat_args *uap = v;
151 struct sys_open_args ouap;
152
153 SCARG(&ouap, path) = SCARG(uap, path);
154 SCARG(&ouap, flags) = O_WRONLY | O_CREAT | O_TRUNC;
155 SCARG(&ouap, mode) = SCARG(uap, mode);
156
157 return (sys_open(l, &ouap, retval));
158 }
159
160 int
161 sunos_sys_access(l, v, retval)
162 struct lwp *l;
163 void *v;
164 register_t *retval;
165 {
166 struct sunos_sys_lstat_args *uap = v;
167
168 return (sys_access(l, uap, retval));
169 }
170
171 int
172 sunos_sys_stat(l, v, retval)
173 struct lwp *l;
174 void *v;
175 register_t *retval;
176 {
177 struct sunos_sys_lstat_args *uap = v;
178
179 return (compat_43_sys_stat(l, uap, retval));
180 }
181
182 int
183 sunos_sys_lstat(l, v, retval)
184 struct lwp *l;
185 void *v;
186 register_t *retval;
187 {
188 struct sunos_sys_lstat_args *uap = v;
189
190 return (compat_43_sys_lstat(l, uap, retval));
191 }
192
193 int
194 sunos_sys_execv(l, v, retval)
195 struct lwp *l;
196 void *v;
197 register_t *retval;
198 {
199 struct sunos_sys_execv_args /* {
200 syscallarg(const char *) path;
201 syscallarg(char **) argv;
202 } */ *uap = v;
203 struct sys_execve_args ap;
204
205 SCARG(&ap, path) = SCARG(uap, path);
206 SCARG(&ap, argp) = SCARG(uap, argp);
207 SCARG(&ap, envp) = NULL;
208
209 return (sys_execve(l, &ap, retval));
210 }
211
212 int
213 sunos_sys_execve(l, v, retval)
214 struct lwp *l;
215 void *v;
216 register_t *retval;
217 {
218 struct sunos_sys_execve_args /* {
219 syscallarg(const char *) path;
220 syscallarg(char **) argv;
221 syscallarg(char **) envp;
222 } */ *uap = v;
223 struct sys_execve_args ap;
224
225 SCARG(&ap, path) = SCARG(uap, path);
226 SCARG(&ap, argp) = SCARG(uap, argp);
227 SCARG(&ap, envp) = SCARG(uap, envp);
228
229 return (sys_execve(l, &ap, retval));
230 }
231
232 int
233 sunos_sys_omsync(l, v, retval)
234 struct lwp *l;
235 void *v;
236 register_t *retval;
237 {
238 struct sunos_sys_omsync_args *uap = v;
239 struct sys___msync13_args ouap;
240
241 SCARG(&ouap, addr) = SCARG(uap, addr);
242 SCARG(&ouap, len) = SCARG(uap, len);
243 SCARG(&ouap, flags) = SCARG(uap, flags);
244
245 return (sys___msync13(l, &ouap, retval));
246 }
247
248 int
249 sunos_sys_unmount(l, v, retval)
250 struct lwp *l;
251 void *v;
252 register_t *retval;
253 {
254 struct sunos_sys_unmount_args *uap = v;
255 struct sys_unmount_args ouap;
256
257 SCARG(&ouap, path) = SCARG(uap, path);
258 SCARG(&ouap, flags) = 0;
259
260 return (sys_unmount(l, &ouap, retval));
261 }
262
263 /*
264 * Conversion table for SunOS NFS mount flags.
265 */
266 static struct {
267 int sun_flg;
268 int bsd_flg;
269 } sunnfs_flgtab[] = {
270 { SUNNFS_SOFT, NFSMNT_SOFT },
271 { SUNNFS_WSIZE, NFSMNT_WSIZE },
272 { SUNNFS_RSIZE, NFSMNT_RSIZE },
273 { SUNNFS_TIMEO, NFSMNT_TIMEO },
274 { SUNNFS_RETRANS, NFSMNT_RETRANS },
275 { SUNNFS_HOSTNAME, 0 }, /* Ignored */
276 { SUNNFS_INT, NFSMNT_INT },
277 { SUNNFS_NOAC, 0 }, /* Ignored */
278 { SUNNFS_ACREGMIN, 0 }, /* Ignored */
279 { SUNNFS_ACREGMAX, 0 }, /* Ignored */
280 { SUNNFS_ACDIRMIN, 0 }, /* Ignored */
281 { SUNNFS_ACDIRMAX, 0 }, /* Ignored */
282 { SUNNFS_SECURE, 0 }, /* Ignored */
283 { SUNNFS_NOCTO, 0 }, /* Ignored */
284 { SUNNFS_POSIX, 0 } /* Ignored */
285 };
286
287 int
288 sunos_sys_mount(l, v, retval)
289 struct lwp *l;
290 void *v;
291 register_t *retval;
292 {
293 struct sunos_sys_mount_args *uap = v;
294 struct proc *p = l->l_proc;
295 int oflags = SCARG(uap, flags), nflags, error;
296 char fsname[MFSNAMELEN];
297 void *sg = stackgap_init(p, 0);
298
299 if (oflags & (SUNM_NOSUB | SUNM_SYS5))
300 return (EINVAL);
301 if ((oflags & SUNM_NEWTYPE) == 0)
302 return (EINVAL);
303 nflags = 0;
304 if (oflags & SUNM_RDONLY)
305 nflags |= MNT_RDONLY;
306 if (oflags & SUNM_NOSUID)
307 nflags |= MNT_NOSUID;
308 if (oflags & SUNM_REMOUNT)
309 nflags |= MNT_UPDATE;
310 SCARG(uap, flags) = nflags;
311
312 error = copyinstr((void *)SCARG(uap, type), fsname,
313 sizeof fsname, (size_t *)0);
314 if (error)
315 return (error);
316
317 if (strncmp(fsname, "4.2", sizeof fsname) == 0) {
318 SCARG(uap, type) = stackgap_alloc(p, &sg, sizeof("ffs"));
319 error = copyout("ffs", SCARG(uap, type), sizeof("ffs"));
320 if (error)
321 return (error);
322 } else if (strncmp(fsname, "nfs", sizeof fsname) == 0) {
323 struct sunos_nfs_args sna;
324 struct sockaddr_in sain;
325 struct nfs_args na;
326 struct sockaddr sa;
327 int n;
328
329 error = copyin(SCARG(uap, data), &sna, sizeof sna);
330 if (error)
331 return (error);
332 error = copyin(sna.addr, &sain, sizeof sain);
333 if (error)
334 return (error);
335 memcpy(&sa, &sain, sizeof sa);
336 sa.sa_len = sizeof(sain);
337 SCARG(uap, data) = stackgap_alloc(p, &sg, sizeof(na));
338 na.version = NFS_ARGSVERSION;
339 na.addr = stackgap_alloc(p, &sg, sizeof(struct sockaddr));
340 na.addrlen = sizeof(struct sockaddr);
341 na.sotype = SOCK_DGRAM;
342 na.proto = IPPROTO_UDP;
343 na.fh = (void *)sna.fh;
344 na.fhsize = NFSX_V2FH;
345 na.flags = 0;
346 n = sizeof(sunnfs_flgtab) / sizeof(sunnfs_flgtab[0]);
347 while (--n >= 0)
348 if (sna.flags & sunnfs_flgtab[n].sun_flg)
349 na.flags |= sunnfs_flgtab[n].bsd_flg;
350 na.wsize = sna.wsize;
351 na.rsize = sna.rsize;
352 if (na.flags & NFSMNT_RSIZE) {
353 na.flags |= NFSMNT_READDIRSIZE;
354 na.readdirsize = na.rsize;
355 }
356 na.timeo = sna.timeo;
357 na.retrans = sna.retrans;
358 na.hostname = (char *)(u_long)sna.hostname;
359
360 error = copyout(&sa, na.addr, sizeof sa);
361 if (error)
362 return (error);
363 error = copyout(&na, SCARG(uap, data), sizeof na);
364 if (error)
365 return (error);
366 }
367 return (sys_mount(l, (struct sys_mount_args *)uap, retval));
368 }
369
370 #if defined(NFS)
371 int
372 async_daemon(l, v, retval)
373 struct lwp *l;
374 void *v;
375 register_t *retval;
376 {
377 struct sys_nfssvc_args ouap;
378
379 SCARG(&ouap, flag) = NFSSVC_BIOD;
380 SCARG(&ouap, argp) = NULL;
381
382 return (sys_nfssvc(l, &ouap, retval));
383 }
384 #endif /* NFS */
385
386 void native_to_sunos_sigset __P((const sigset_t *, int *));
387 void sunos_to_native_sigset __P((const int, sigset_t *));
388
389 inline void
390 native_to_sunos_sigset(ss, mask)
391 const sigset_t *ss;
392 int *mask;
393 {
394 *mask = ss->__bits[0];
395 }
396
397 inline void
398 sunos_to_native_sigset(mask, ss)
399 const int mask;
400 sigset_t *ss;
401 {
402
403 ss->__bits[0] = mask;
404 ss->__bits[1] = 0;
405 ss->__bits[2] = 0;
406 ss->__bits[3] = 0;
407 }
408
409 int
410 sunos_sys_sigpending(l, v, retval)
411 struct lwp *l;
412 void *v;
413 register_t *retval;
414 {
415 struct sunos_sys_sigpending_args *uap = v;
416 sigset_t ss;
417 int mask;
418
419 sigpending1(l, &ss);
420 native_to_sunos_sigset(&ss, &mask);
421
422 return (copyout((void *)&mask, (void *)SCARG(uap, mask), sizeof(int)));
423 }
424
425 int
426 sunos_sys_sigsuspend(l, v, retval)
427 struct lwp *l;
428 void *v;
429 register_t *retval;
430 {
431 struct sunos_sys_sigsuspend_args /* {
432 syscallarg(int) mask;
433 } */ *uap = v;
434 int mask;
435 sigset_t ss;
436
437 mask = SCARG(uap, mask);
438 sunos_to_native_sigset(mask, &ss);
439 return (sigsuspend1(l, &ss));
440 }
441
442 /*
443 * Read Sun-style directory entries. We suck them into kernel space so
444 * that they can be massaged before being copied out to user code. Like
445 * SunOS, we squish out `empty' entries.
446 *
447 * This is quite ugly, but what do you expect from compatibility code?
448 */
449 int
450 sunos_sys_getdents(l, v, retval)
451 struct lwp *l;
452 void *v;
453 register_t *retval;
454 {
455 struct sunos_sys_getdents_args *uap = v;
456 struct proc *p = l->l_proc;
457 struct dirent *bdp;
458 struct vnode *vp;
459 char *inp, *buf; /* BSD-format */
460 int len, reclen; /* BSD-format */
461 char *outp; /* Sun-format */
462 int resid, sunos_reclen;/* Sun-format */
463 struct file *fp;
464 struct uio auio;
465 struct iovec aiov;
466 struct sunos_dirent idb;
467 off_t off; /* true file offset */
468 int buflen, error, eofflag;
469 off_t *cookiebuf, *cookie;
470 int ncookies;
471
472 /* getvnode() will use the descriptor for us */
473 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
474 return (error);
475
476 if ((fp->f_flag & FREAD) == 0) {
477 error = EBADF;
478 goto out1;
479 }
480
481 vp = (struct vnode *)fp->f_data;
482 if (vp->v_type != VDIR) {
483 error = EINVAL;
484 goto out1;
485 }
486
487 buflen = min(MAXBSIZE, SCARG(uap, nbytes));
488 buf = malloc(buflen, M_TEMP, M_WAITOK);
489 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
490 off = fp->f_offset;
491 again:
492 aiov.iov_base = buf;
493 aiov.iov_len = buflen;
494 auio.uio_iov = &aiov;
495 auio.uio_iovcnt = 1;
496 auio.uio_rw = UIO_READ;
497 auio.uio_resid = buflen;
498 auio.uio_offset = off;
499 UIO_SETUP_SYSSPACE(&auio);
500 /*
501 * First we read into the malloc'ed buffer, then
502 * we massage it into user space, one record at a time.
503 */
504 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
505 &ncookies);
506 if (error)
507 goto out;
508
509 inp = buf;
510 outp = SCARG(uap, buf);
511 resid = SCARG(uap, nbytes);
512 if ((len = buflen - auio.uio_resid) == 0)
513 goto eof;
514
515 for (cookie = cookiebuf; len > 0; len -= reclen) {
516 bdp = (struct dirent *)inp;
517 reclen = bdp->d_reclen;
518 if (reclen & 3)
519 panic("sunos_getdents");
520 if ((*cookie >> 32) != 0) {
521 compat_offseterr(vp, "sunos_getdents");
522 error = EINVAL;
523 goto out;
524 }
525 if (bdp->d_fileno == 0) {
526 inp += reclen; /* it is a hole; squish it out */
527 if (cookie)
528 off = *cookie++;
529 else
530 off += reclen;
531 continue;
532 }
533 sunos_reclen = SUNOS_RECLEN(&idb, bdp->d_namlen);
534 if (reclen > len || resid < sunos_reclen) {
535 /* entry too big for buffer, so just stop */
536 outp++;
537 break;
538 }
539 if (cookie)
540 off = *cookie++; /* each entry points to next */
541 else
542 off += reclen;
543 /*
544 * Massage in place to make a Sun-shaped dirent (otherwise
545 * we have to worry about touching user memory outside of
546 * the copyout() call).
547 */
548 idb.d_fileno = bdp->d_fileno;
549 idb.d_off = off;
550 idb.d_reclen = sunos_reclen;
551 idb.d_namlen = bdp->d_namlen;
552 strlcpy(idb.d_name, bdp->d_name, sizeof(idb.d_name));
553 if ((error = copyout((void *)&idb, outp, sunos_reclen)) != 0)
554 goto out;
555 /* advance past this real entry */
556 inp += reclen;
557 /* advance output past Sun-shaped entry */
558 outp += sunos_reclen;
559 resid -= sunos_reclen;
560 }
561
562 /* if we squished out the whole block, try again */
563 if (outp == SCARG(uap, buf))
564 goto again;
565 fp->f_offset = off; /* update the vnode offset */
566
567 eof:
568 *retval = SCARG(uap, nbytes) - resid;
569 out:
570 VOP_UNLOCK(vp, 0);
571 free(cookiebuf, M_TEMP);
572 free(buf, M_TEMP);
573 out1:
574 FILE_UNUSE(fp, l);
575 return (error);
576 }
577
578 #define SUNOS__MAP_NEW 0x80000000 /* if not, old mmap & cannot handle */
579
580 int
581 sunos_sys_mmap(l, v, retval)
582 struct lwp *l;
583 void *v;
584 register_t *retval;
585 {
586 struct sunos_sys_mmap_args *uap = v;
587 struct sys_mmap_args ouap;
588
589 /*
590 * Verify the arguments.
591 */
592 if (SCARG(uap, prot) & ~(PROT_READ|PROT_WRITE|PROT_EXEC))
593 return (EINVAL); /* XXX still needed? */
594
595 if ((SCARG(uap, flags) & SUNOS__MAP_NEW) == 0)
596 return (EINVAL);
597
598 SCARG(&ouap, flags) = SCARG(uap, flags) & ~SUNOS__MAP_NEW;
599 SCARG(&ouap, addr) = SCARG(uap, addr);
600 SCARG(&ouap, len) = SCARG(uap, len);
601 SCARG(&ouap, prot) = SCARG(uap, prot);
602 SCARG(&ouap, fd) = SCARG(uap, fd);
603 SCARG(&ouap, pos) = SCARG(uap, pos);
604
605 return (sys_mmap(l, &ouap, retval));
606 }
607
608 #define MC_SYNC 1
609 #define MC_LOCK 2
610 #define MC_UNLOCK 3
611 #define MC_ADVISE 4
612 #define MC_LOCKAS 5
613 #define MC_UNLOCKAS 6
614
615 int
616 sunos_sys_mctl(l, v, retval)
617 struct lwp *l;
618 void *v;
619 register_t *retval;
620 {
621 struct sunos_sys_mctl_args *uap = v;
622
623 switch (SCARG(uap, func)) {
624 case MC_ADVISE: /* ignore for now */
625 return (0);
626 case MC_SYNC: /* translate to msync */
627 return (sys___msync13(l, uap, retval));
628 default:
629 return (EINVAL);
630 }
631 }
632
633 int
634 sunos_sys_setsockopt(l, v, retval)
635 struct lwp *l;
636 void *v;
637 register_t *retval;
638 {
639 struct sunos_sys_setsockopt_args *uap = v;
640 struct proc *p = l->l_proc;
641 struct file *fp;
642 struct mbuf *m = NULL;
643 int error;
644
645 /* getsock() will use the descriptor for us */
646 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
647 return (error);
648 #define SO_DONTLINGER (~SO_LINGER)
649 if (SCARG(uap, name) == SO_DONTLINGER) {
650 m = m_get(M_WAIT, MT_SOOPTS);
651 mtod(m, struct linger *)->l_onoff = 0;
652 m->m_len = sizeof(struct linger);
653 error = sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
654 SO_LINGER, m);
655 goto out;
656 }
657 if (SCARG(uap, level) == IPPROTO_IP) {
658 #define SUNOS_IP_MULTICAST_IF 2
659 #define SUNOS_IP_MULTICAST_TTL 3
660 #define SUNOS_IP_MULTICAST_LOOP 4
661 #define SUNOS_IP_ADD_MEMBERSHIP 5
662 #define SUNOS_IP_DROP_MEMBERSHIP 6
663 static const int ipoptxlat[] = {
664 IP_MULTICAST_IF,
665 IP_MULTICAST_TTL,
666 IP_MULTICAST_LOOP,
667 IP_ADD_MEMBERSHIP,
668 IP_DROP_MEMBERSHIP
669 };
670 if (SCARG(uap, name) >= SUNOS_IP_MULTICAST_IF &&
671 SCARG(uap, name) <= SUNOS_IP_DROP_MEMBERSHIP) {
672 SCARG(uap, name) =
673 ipoptxlat[SCARG(uap, name) - SUNOS_IP_MULTICAST_IF];
674 }
675 }
676 if (SCARG(uap, valsize) > MLEN) {
677 error = EINVAL;
678 goto out;
679 }
680 if (SCARG(uap, val)) {
681 m = m_get(M_WAIT, MT_SOOPTS);
682 error = copyin(SCARG(uap, val), mtod(m, void *),
683 (u_int)SCARG(uap, valsize));
684 if (error) {
685 (void) m_free(m);
686 goto out;
687 }
688 m->m_len = SCARG(uap, valsize);
689 }
690 error = sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
691 SCARG(uap, name), m);
692 out:
693 FILE_UNUSE(fp, l);
694 return (error);
695 }
696
697 static inline int sunos_sys_socket_common(struct lwp *, register_t *,
698 int type);
699 static inline int
700 sunos_sys_socket_common(l, retval, type)
701 struct lwp *l;
702 register_t *retval;
703 int type;
704 {
705 struct socket *so;
706 struct file *fp;
707 int error, fd;
708
709 /* getsock() will use the descriptor for us */
710 fd = (int)*retval;
711 if ((error = getsock(l->l_proc->p_fd, fd, &fp)) == 0) {
712 so = (struct socket *)fp->f_data;
713 if (type == SOCK_DGRAM)
714 so->so_options |= SO_BROADCAST;
715 }
716 FILE_UNUSE(fp, l);
717 return (error);
718 }
719
720 int
721 sunos_sys_socket(l, v, retval)
722 struct lwp *l;
723 void *v;
724 register_t *retval;
725 {
726 struct sunos_sys_socket_args /* {
727 syscallarg(int) domain;
728 syscallarg(int) type;
729 syscallarg(int) protocol;
730 } */ *uap = v;
731 int error;
732
733 error = compat_30_sys_socket(l, v, retval);
734 if (error)
735 return (error);
736 return sunos_sys_socket_common(l, retval, SCARG(uap, type));
737 }
738
739 int
740 sunos_sys_socketpair(l, v, retval)
741 struct lwp *l;
742 void *v;
743 register_t *retval;
744 {
745 struct sunos_sys_socketpair_args /* {
746 syscallarg(int) domain;
747 syscallarg(int) type;
748 syscallarg(int) protocol;
749 syscallarg(int *) rsv;
750 } */ *uap = v;
751 int error;
752
753 error = sys_socketpair(l, v, retval);
754 if (error)
755 return (error);
756 return sunos_sys_socket_common(l, retval, SCARG(uap, type));
757 }
758
759 /*
760 * XXX: This needs cleaning up.
761 */
762 int
763 sunos_sys_auditsys(l, v, retval)
764 struct lwp *l;
765 void *v;
766 register_t *retval;
767 {
768 return 0;
769 }
770
771 int
772 sunos_sys_uname(l, v, retval)
773 struct lwp *l;
774 void *v;
775 register_t *retval;
776 {
777 struct sunos_sys_uname_args *uap = v;
778 struct sunos_utsname sut;
779
780 memset(&sut, 0, sizeof(sut));
781
782 memcpy(sut.sysname, ostype, sizeof(sut.sysname) - 1);
783 memcpy(sut.nodename, hostname, sizeof(sut.nodename));
784 sut.nodename[sizeof(sut.nodename)-1] = '\0';
785 memcpy(sut.release, osrelease, sizeof(sut.release) - 1);
786 memcpy(sut.version, "1", sizeof(sut.version) - 1);
787 memcpy(sut.machine, machine, sizeof(sut.machine) - 1);
788
789 return copyout((void *)&sut, (void *)SCARG(uap, name),
790 sizeof(struct sunos_utsname));
791 }
792
793 int
794 sunos_sys_setpgrp(l, v, retval)
795 struct lwp *l;
796 void *v;
797 register_t *retval;
798 {
799 struct sunos_sys_setpgrp_args *uap = v;
800 struct proc *p = l->l_proc;
801
802 /*
803 * difference to our setpgid call is to include backwards
804 * compatibility to pre-setsid() binaries. Do setsid()
805 * instead of setpgid() in those cases where the process
806 * tries to create a new session the old way.
807 */
808 if (!SCARG(uap, pgid) &&
809 (!SCARG(uap, pid) || SCARG(uap, pid) == p->p_pid))
810 return sys_setsid(l, uap, retval);
811 else
812 return sys_setpgid(l, uap, retval);
813 }
814
815 int
816 sunos_sys_open(l, v, retval)
817 struct lwp *l;
818 void *v;
819 register_t *retval;
820 {
821 struct sunos_sys_open_args *uap = v;
822 struct proc *p = l->l_proc;
823 int smode, nmode;
824 int noctty;
825 int ret;
826
827 /* convert mode into NetBSD mode */
828 smode = SCARG(uap, flags);
829 noctty = smode & 0x8000;
830 nmode = smode &
831 (0x0001 | 0x0002 | 0x0008 | 0x0040 | 0x0200 | 0x0400 | 0x0800);
832 nmode |= ((smode & (0x0004 | 0x1000 | 0x4000)) ? O_NONBLOCK : 0);
833 nmode |= ((smode & 0x0080) ? O_SHLOCK : 0);
834 nmode |= ((smode & 0x0100) ? O_EXLOCK : 0);
835 nmode |= ((smode & 0x2000) ? O_FSYNC : 0);
836
837 SCARG(uap, flags) = nmode;
838 ret = sys_open(l, (struct sys_open_args *)uap, retval);
839
840 /* XXXSMP */
841 if (!ret && !noctty && SESS_LEADER(p) && !(p->p_lflag & PL_CONTROLT)) {
842 struct filedesc *fdp = p->p_fd;
843 struct file *fp;
844
845 fp = fd_getfile(fdp, *retval);
846 simple_unlock(&fp->f_slock);
847
848 /* ignore any error, just give it a try */
849 if (fp != NULL && fp->f_type == DTYPE_VNODE)
850 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (void *)0, l);
851 }
852 return ret;
853 }
854
855 #if defined (NFSSERVER)
856 int
857 sunos_sys_nfssvc(l, v, retval)
858 struct lwp *l;
859 void *v;
860 register_t *retval;
861 {
862 #if 0
863 struct sunos_sys_nfssvc_args *uap = v;
864 struct proc *p = l->l_proc;
865 struct emul *e = p->p_emul;
866 struct sys_nfssvc_args outuap;
867 struct sockaddr sa;
868 int error;
869 void *sg = stackgap_init(p, 0);
870
871 memset(&outuap, 0, sizeof outuap);
872 SCARG(&outuap, fd) = SCARG(uap, fd);
873 SCARG(&outuap, mskval) = stackgap_alloc(p, &sg, sizeof(sa));
874 SCARG(&outuap, msklen) = sizeof(sa);
875 SCARG(&outuap, mtchval) = stackgap_alloc(p, &sg, sizeof(sa));
876 SCARG(&outuap, mtchlen) = sizeof(sa);
877
878 memset(&sa, 0, sizeof sa);
879 if (error = copyout(&sa, SCARG(&outuap, mskval), SCARG(&outuap, msklen)))
880 return (error);
881 if (error = copyout(&sa, SCARG(&outuap, mtchval), SCARG(&outuap, mtchlen)))
882 return (error);
883
884 return nfssvc(l, &outuap, retval);
885 #else
886 return (ENOSYS);
887 #endif
888 }
889 #endif /* NFSSERVER */
890
891 int
892 sunos_sys_ustat(l, v, retval)
893 struct lwp *l;
894 void *v;
895 register_t *retval;
896 {
897 struct sunos_sys_ustat_args *uap = v;
898 struct sunos_ustat us;
899 int error;
900
901 memset(&us, 0, sizeof us);
902
903 /*
904 * XXX: should set f_tfree and f_tinode at least
905 * How do we translate dev -> fstat? (and then to sunos_ustat)
906 */
907
908 if ((error = copyout(&us, SCARG(uap, buf), sizeof us)) != 0)
909 return (error);
910 return 0;
911 }
912
913 int
914 sunos_sys_quotactl(l, v, retval)
915 struct lwp *l;
916 void *v;
917 register_t *retval;
918 {
919
920 return EINVAL;
921 }
922
923 int
924 sunos_sys_vhangup(l, v, retval)
925 struct lwp *l;
926 void *v;
927 register_t *retval;
928 {
929 struct proc *p = l->l_proc;
930 struct session *sp = p->p_session;
931
932 if (sp->s_ttyvp == 0)
933 return 0;
934
935 if (sp->s_ttyp && sp->s_ttyp->t_session == sp && sp->s_ttyp->t_pgrp)
936 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
937
938 (void) ttywait(sp->s_ttyp);
939 if (sp->s_ttyvp)
940 VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
941 if (sp->s_ttyvp)
942 vrele(sp->s_ttyvp);
943 sp->s_ttyvp = NULL;
944
945 return 0;
946 }
947
948 static int
949 sunstatfs(sp, buf)
950 struct statvfs *sp;
951 void *buf;
952 {
953 struct sunos_statfs ssfs;
954
955 memset(&ssfs, 0, sizeof ssfs);
956 ssfs.f_type = 0;
957 ssfs.f_bsize = sp->f_bsize;
958 ssfs.f_blocks = sp->f_blocks;
959 ssfs.f_bfree = sp->f_bfree;
960 ssfs.f_bavail = sp->f_bavail;
961 ssfs.f_files = sp->f_files;
962 ssfs.f_ffree = sp->f_ffree;
963 ssfs.f_fsid = sp->f_fsidx;
964 return copyout((void *)&ssfs, buf, sizeof ssfs);
965 }
966
967 int
968 sunos_sys_statfs(l, v, retval)
969 struct lwp *l;
970 void *v;
971 register_t *retval;
972 {
973 struct sunos_sys_statfs_args *uap = v;
974 struct mount *mp;
975 struct statvfs *sp;
976 int error;
977 struct nameidata nd;
978
979 NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, UIO_USERSPACE, SCARG(uap, path), l);
980 if ((error = namei(&nd)) != 0)
981 return (error);
982 mp = nd.ni_vp->v_mount;
983 sp = &mp->mnt_stat;
984 vrele(nd.ni_vp);
985 if ((error = VFS_STATVFS(mp, sp, l)) != 0)
986 return (error);
987 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
988 return sunstatfs(sp, (void *)SCARG(uap, buf));
989 }
990
991 int
992 sunos_sys_fstatfs(l, v, retval)
993 struct lwp *l;
994 void *v;
995 register_t *retval;
996 {
997 struct sunos_sys_fstatfs_args *uap = v;
998 struct proc *p = l->l_proc;
999 struct file *fp;
1000 struct mount *mp;
1001 struct statvfs *sp;
1002 int error;
1003
1004 /* getvnode() will use the descriptor for us */
1005 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1006 return (error);
1007 mp = ((struct vnode *)fp->f_data)->v_mount;
1008 sp = &mp->mnt_stat;
1009 if ((error = VFS_STATVFS(mp, sp, l)) != 0)
1010 goto out;
1011 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK;
1012 error = sunstatfs(sp, (void *)SCARG(uap, buf));
1013 out:
1014 FILE_UNUSE(fp, l);
1015 return (error);
1016 }
1017
1018 int
1019 sunos_sys_exportfs(l, v, retval)
1020 struct lwp *l;
1021 void *v;
1022 register_t *retval;
1023 {
1024 /*
1025 * XXX: should perhaps translate into a mount(2)
1026 * with MOUNT_EXPORT?
1027 */
1028 return 0;
1029 }
1030
1031 int
1032 sunos_sys_mknod(l, v, retval)
1033 struct lwp *l;
1034 void *v;
1035 register_t *retval;
1036 {
1037 struct sunos_sys_mknod_args *uap = v;
1038
1039 if (S_ISFIFO(SCARG(uap, mode)))
1040 return sys_mkfifo(l, uap, retval);
1041
1042 return sys_mknod(l, (struct sys_mknod_args *)uap, retval);
1043 }
1044
1045 #define SUNOS_SC_ARG_MAX 1
1046 #define SUNOS_SC_CHILD_MAX 2
1047 #define SUNOS_SC_CLK_TCK 3
1048 #define SUNOS_SC_NGROUPS_MAX 4
1049 #define SUNOS_SC_OPEN_MAX 5
1050 #define SUNOS_SC_JOB_CONTROL 6
1051 #define SUNOS_SC_SAVED_IDS 7
1052 #define SUNOS_SC_VERSION 8
1053
1054 int
1055 sunos_sys_sysconf(l, v, retval)
1056 struct lwp *l;
1057 void *v;
1058 register_t *retval;
1059 {
1060 struct sunos_sys_sysconf_args *uap = v;
1061 extern int maxfiles;
1062
1063 switch(SCARG(uap, name)) {
1064 case SUNOS_SC_ARG_MAX:
1065 *retval = ARG_MAX;
1066 break;
1067 case SUNOS_SC_CHILD_MAX:
1068 *retval = maxproc;
1069 break;
1070 case SUNOS_SC_CLK_TCK:
1071 *retval = 60; /* should this be `hz', ie. 100? */
1072 break;
1073 case SUNOS_SC_NGROUPS_MAX:
1074 *retval = NGROUPS_MAX;
1075 break;
1076 case SUNOS_SC_OPEN_MAX:
1077 *retval = maxfiles;
1078 break;
1079 case SUNOS_SC_JOB_CONTROL:
1080 *retval = 1;
1081 break;
1082 case SUNOS_SC_SAVED_IDS:
1083 #ifdef _POSIX_SAVED_IDS
1084 *retval = 1;
1085 #else
1086 *retval = 0;
1087 #endif
1088 break;
1089 case SUNOS_SC_VERSION:
1090 *retval = 198808;
1091 break;
1092 default:
1093 return EINVAL;
1094 }
1095 return 0;
1096 }
1097
1098 #define SUNOS_RLIMIT_NOFILE 6 /* Other RLIMIT_* are the same */
1099 #define SUNOS_RLIM_NLIMITS 7
1100
1101 int
1102 sunos_sys_getrlimit(l, v, retval)
1103 struct lwp *l;
1104 void *v;
1105 register_t *retval;
1106 {
1107 struct sunos_sys_getrlimit_args *uap = v;
1108
1109 if (SCARG(uap, which) >= SUNOS_RLIM_NLIMITS)
1110 return EINVAL;
1111
1112 if (SCARG(uap, which) == SUNOS_RLIMIT_NOFILE)
1113 SCARG(uap, which) = RLIMIT_NOFILE;
1114
1115 return compat_43_sys_getrlimit(l, uap, retval);
1116 }
1117
1118 int
1119 sunos_sys_setrlimit(l, v, retval)
1120 struct lwp *l;
1121 void *v;
1122 register_t *retval;
1123 {
1124 struct sunos_sys_getrlimit_args *uap = v;
1125
1126 if (SCARG(uap, which) >= SUNOS_RLIM_NLIMITS)
1127 return EINVAL;
1128
1129 if (SCARG(uap, which) == SUNOS_RLIMIT_NOFILE)
1130 SCARG(uap, which) = RLIMIT_NOFILE;
1131
1132 return compat_43_sys_setrlimit(l, uap, retval);
1133 }
1134
1135 #if defined(PTRACE) || defined(_LKM)
1136 /* for the m68k machines */
1137 #ifndef PT_GETFPREGS
1138 #define PT_GETFPREGS -1
1139 #endif
1140 #ifndef PT_SETFPREGS
1141 #define PT_SETFPREGS -1
1142 #endif
1143
1144 static const int sreq2breq[] = {
1145 PT_TRACE_ME, PT_READ_I, PT_READ_D, -1,
1146 PT_WRITE_I, PT_WRITE_D, -1, PT_CONTINUE,
1147 PT_KILL, -1, PT_ATTACH, PT_DETACH,
1148 PT_GETREGS, PT_SETREGS, PT_GETFPREGS, PT_SETFPREGS
1149 };
1150 static const int nreqs = sizeof(sreq2breq) / sizeof(sreq2breq[0]);
1151 #endif /* PTRACE || _LKM */
1152
1153 int
1154 sunos_sys_ptrace(l, v, retval)
1155 struct lwp *l;
1156 void *v;
1157 register_t *retval;
1158 {
1159 #if defined(PTRACE) || defined(_LKM)
1160 struct sunos_sys_ptrace_args *uap = v;
1161 struct sys_ptrace_args pa;
1162 int req;
1163
1164 #ifdef _LKM
1165 #define sys_ptrace sysent[SYS_ptrace].sy_call
1166 if (sys_ptrace == sys_nosys)
1167 return ENOSYS;
1168 #endif
1169
1170 req = SCARG(uap, req);
1171
1172 if (req < 0 || req >= nreqs)
1173 return (EINVAL);
1174
1175 req = sreq2breq[req];
1176 if (req == -1)
1177 return (EINVAL);
1178
1179 SCARG(&pa, req) = req;
1180 SCARG(&pa, pid) = (pid_t)SCARG(uap, pid);
1181 SCARG(&pa, addr) = (void *)SCARG(uap, addr);
1182 SCARG(&pa, data) = SCARG(uap, data);
1183
1184 return sys_ptrace(l, &pa, retval);
1185 #else
1186 return ENOSYS;
1187 #endif /* PTRACE || _LKM */
1188 }
1189
1190 /*
1191 * SunOS reboot system call (for compatibility).
1192 * Sun lets you pass in a boot string which the PROM
1193 * saves and provides to the next boot program.
1194 */
1195
1196 #define SUNOS_RB_ASKNAME 0x001
1197 #define SUNOS_RB_SINGLE 0x002
1198 #define SUNOS_RB_NOSYNC 0x004
1199 #define SUNOS_RB_HALT 0x008
1200 #define SUNOS_RB_DUMP 0x080
1201 #define SUNOS_RB_STRING 0x200
1202
1203 static struct sunos_howto_conv {
1204 int sun_howto;
1205 int bsd_howto;
1206 } sunos_howto_conv[] = {
1207 { SUNOS_RB_ASKNAME, RB_ASKNAME },
1208 { SUNOS_RB_SINGLE, RB_SINGLE },
1209 { SUNOS_RB_NOSYNC, RB_NOSYNC },
1210 { SUNOS_RB_HALT, RB_HALT },
1211 { SUNOS_RB_DUMP, RB_DUMP },
1212 { SUNOS_RB_STRING, RB_STRING },
1213 { 0x000, 0 },
1214 };
1215
1216 int
1217 sunos_sys_reboot(l, v, retval)
1218 struct lwp *l;
1219 void *v;
1220 register_t *retval;
1221 {
1222 struct sunos_sys_reboot_args *uap = v;
1223 struct sys_reboot_args ua;
1224 struct sunos_howto_conv *convp;
1225 int error, bsd_howto, sun_howto;
1226 char *bootstr;
1227
1228 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_REBOOT,
1229 0, NULL, NULL, NULL)) != 0)
1230 return (error);
1231
1232 /*
1233 * Convert howto bits to BSD format.
1234 */
1235 sun_howto = SCARG(uap, howto);
1236 bsd_howto = 0;
1237 convp = sunos_howto_conv;
1238 while (convp->sun_howto) {
1239 if (sun_howto & convp->sun_howto)
1240 bsd_howto |= convp->bsd_howto;
1241 convp++;
1242 }
1243
1244 /*
1245 * Sun RB_STRING (Get user supplied bootstring.)
1246 * If the machine supports passing a string to the
1247 * next booted kernel.
1248 */
1249 if (sun_howto & SUNOS_RB_STRING) {
1250 char bs[128];
1251
1252 error = copyinstr(SCARG(uap, bootstr), bs, sizeof(bs), 0);
1253
1254 if (error)
1255 bootstr = NULL;
1256 else
1257 bootstr = bs;
1258 } else
1259 bootstr = NULL;
1260
1261 SCARG(&ua, opt) = bsd_howto;
1262 SCARG(&ua, bootstr) = bootstr;
1263 sys_reboot(l, &ua, retval);
1264 return(0);
1265 }
1266
1267 /*
1268 * Generalized interface signal handler, 4.3-compatible.
1269 */
1270 /* ARGSUSED */
1271 int
1272 sunos_sys_sigvec(l, v, retval)
1273 struct lwp *l;
1274 void *v;
1275 register_t *retval;
1276 {
1277 struct sunos_sys_sigvec_args /* {
1278 syscallarg(int) signum;
1279 syscallarg(struct sigvec *) nsv;
1280 syscallarg(struct sigvec *) osv;
1281 } */ *uap = v;
1282 struct sigvec nsv, osv;
1283 struct sigaction nsa, osa;
1284 int error;
1285 /*XXX*/extern void compat_43_sigvec_to_sigaction
1286 __P((const struct sigvec *, struct sigaction *));
1287 /*XXX*/extern void compat_43_sigaction_to_sigvec
1288 __P((const struct sigaction *, struct sigvec *));
1289
1290 if (SCARG(uap, nsv)) {
1291 error = copyin(SCARG(uap, nsv), &nsv, sizeof(nsv));
1292 if (error != 0)
1293 return (error);
1294
1295 /*
1296 * SunOS uses the mask 0x0004 as SV_RESETHAND
1297 * meaning: `reset to SIG_DFL on delivery'.
1298 * We support only the bits in: 0xF
1299 * (those bits are the same as ours)
1300 */
1301 if (nsv.sv_flags & ~0xF)
1302 return (EINVAL);
1303
1304 compat_43_sigvec_to_sigaction(&nsv, &nsa);
1305 }
1306 error = sigaction1(l, SCARG(uap, signum),
1307 SCARG(uap, nsv) ? &nsa : 0,
1308 SCARG(uap, osv) ? &osa : 0,
1309 NULL, 0);
1310 if (error != 0)
1311 return (error);
1312
1313 if (SCARG(uap, osv)) {
1314 compat_43_sigaction_to_sigvec(&osa, &osv);
1315 error = copyout(&osv, SCARG(uap, osv), sizeof(osv));
1316 if (error != 0)
1317 return (error);
1318 }
1319
1320 return (0);
1321 }
1322