sunos32_misc.c revision 1.10 1 /* $NetBSD: sunos32_misc.c,v 1.10 2001/11/13 02:09:20 lukem Exp $ */
2 /* from :NetBSD: sunos_misc.c,v 1.107 2000/12/01 19:25:10 jdolecek Exp */
3
4 /*
5 * Copyright (c) 2001 Matthew R. Green
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 1992, 1993
34 * The Regents of the University of California. All rights reserved.
35 *
36 * This software was developed by the Computer Systems Engineering group
37 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
38 * contributed to Berkeley.
39 *
40 * All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Lawrence Berkeley Laboratory.
44 *
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
47 * are met:
48 * 1. Redistributions of source code must retain the above copyright
49 * notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 * notice, this list of conditions and the following disclaimer in the
52 * documentation and/or other materials provided with the distribution.
53 * 3. All advertising materials mentioning features or use of this software
54 * must display the following acknowledgement:
55 * This product includes software developed by the University of
56 * California, Berkeley and its contributors.
57 * 4. Neither the name of the University nor the names of its contributors
58 * may be used to endorse or promote products derived from this software
59 * without specific prior written permission.
60 *
61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71 * SUCH DAMAGE.
72 *
73 * @(#)sunos_misc.c 8.1 (Berkeley) 6/18/93
74 *
75 * Header: sunos_misc.c,v 1.16 93/04/07 02:46:27 torek Exp
76 */
77
78 /*
79 * SunOS compatibility module, 64-bit kernel version
80 *
81 * SunOS system calls that are implemented differently in BSD are
82 * handled here.
83 */
84
85 #include <sys/cdefs.h>
86 __KERNEL_RCSID(0, "$NetBSD: sunos32_misc.c,v 1.10 2001/11/13 02:09:20 lukem Exp $");
87
88 #define COMPAT_SUNOS 1
89
90 #if defined(_KERNEL_OPT)
91 #include "opt_nfsserver.h"
92 #include "opt_compat_43.h"
93 #include "opt_compat_netbsd.h"
94 #include "fs_nfs.h"
95 #endif
96
97 #include <sys/param.h>
98 #include <sys/systm.h>
99 #include <sys/namei.h>
100 #include <sys/proc.h>
101 #include <sys/dirent.h>
102 #include <sys/file.h>
103 #include <sys/stat.h>
104 #include <sys/filedesc.h>
105 #include <sys/ioctl.h>
106 #include <sys/kernel.h>
107 #include <sys/reboot.h>
108 #include <sys/malloc.h>
109 #include <sys/mbuf.h>
110 #include <sys/mman.h>
111 #include <sys/mount.h>
112 #include <sys/ptrace.h>
113 #include <sys/resource.h>
114 #include <sys/resourcevar.h>
115 #include <sys/signal.h>
116 #include <sys/signalvar.h>
117 #include <sys/socket.h>
118 #include <sys/tty.h>
119 #include <sys/vnode.h>
120 #include <sys/uio.h>
121 #include <sys/wait.h>
122 #include <sys/utsname.h>
123 #include <sys/unistd.h>
124 #include <sys/syscallargs.h>
125 #include <sys/conf.h>
126 #include <sys/socketvar.h>
127 #include <sys/exec.h>
128 #include <sys/swap.h>
129
130 #include <compat/netbsd32/netbsd32.h>
131 #include <compat/netbsd32/netbsd32_syscallargs.h>
132 #include <compat/sunos32/sunos32.h>
133 #include <compat/sunos32/sunos32_dirent.h>
134 #include <compat/sunos32/sunos32_syscallargs.h>
135 #include <compat/common/compat_util.h>
136
137 #include <netinet/in.h>
138
139 #include <miscfs/specfs/specdev.h>
140
141 #include <nfs/rpcv2.h>
142 #include <nfs/nfsproto.h>
143 #include <nfs/nfs.h>
144 #include <nfs/nfsmount.h>
145
146 static void sunos32_sigvec_to_sigaction(const struct netbsd32_sigvec *, struct sigaction *);
147 static void sunos32_sigvec_from_sigaction(struct netbsd32_sigvec *, const struct sigaction *);
148
149 static int sunstatfs __P((struct statfs *, caddr_t));
150
151 static void
152 sunos32_sigvec_to_sigaction(sv, sa)
153 const struct netbsd32_sigvec *sv;
154 struct sigaction *sa;
155 {
156 /*XXX*/ extern void compat_43_sigmask_to_sigset __P((const int *, sigset_t *));
157
158 sa->sa_handler = (void *)(u_long)sv->sv_handler;
159 compat_43_sigmask_to_sigset(&sv->sv_mask, &sa->sa_mask);
160 sa->sa_flags = sv->sv_flags ^ SA_RESTART;
161 }
162
163 static
164 void sunos32_sigvec_from_sigaction(sv, sa)
165 struct netbsd32_sigvec *sv;
166 const struct sigaction *sa;
167 {
168 /*XXX*/ extern void compat_43_sigset_to_sigmask __P((const sigset_t *, int *));
169
170 sv->sv_handler = (netbsd32_voidp)(u_long)sa->sa_handler;
171 compat_43_sigset_to_sigmask(&sa->sa_mask, &sv->sv_mask);
172 sv->sv_flags = sa->sa_flags ^ SA_RESTART;
173 }
174
175 int
176 sunos32_sys_stime(p, v, retval)
177 struct proc *p;
178 void *v;
179 register_t *retval;
180 {
181 struct sunos32_sys_stime_args /* {
182 syscallarg(sunos32_time_tp) tp;
183 } */ *uap = v;
184 struct sys_settimeofday_args ap;
185 caddr_t sg = stackgap_init(p->p_emul);
186 struct netbsd32_timeval ntv;
187 struct timeval tv, *sgtvp;
188 int error;
189
190 error = copyin((caddr_t)(u_long)SCARG(uap, tp), &ntv.tv_sec, sizeof(ntv.tv_sec));
191 if (error)
192 return error;
193 tv.tv_sec = ntv.tv_sec;
194 tv.tv_usec = 0;
195
196 SCARG(&ap, tv) = sgtvp = stackgap_alloc(&sg, sizeof(struct timeval));
197 SCARG(&ap, tzp) = NULL;
198
199 error = copyout(&tv, sgtvp, sizeof(struct timeval));
200 if (error)
201 return error;
202
203 return sys_settimeofday(p, &ap, retval);
204 }
205
206 int
207 sunos32_sys_wait4(p, v, retval)
208 struct proc *p;
209 void *v;
210 register_t *retval;
211 {
212 struct sunos32_sys_wait4_args /* {
213 syscallarg(int) pid;
214 syscallarg(netbsd32_intp) status;
215 syscallarg(int) options;
216 syscallarg(netbsd32_rusagep_t) rusage;
217 } */ *uap = v;
218
219 if (SCARG(uap, pid) == 0)
220 SCARG(uap, pid) = WAIT_ANY;
221 return (netbsd32_wait4(p, uap, retval));
222 }
223
224 int
225 sunos32_sys_creat(p, v, retval)
226 struct proc *p;
227 void *v;
228 register_t *retval;
229 {
230 struct sunos32_sys_creat_args /* {
231 syscallarg(const netbsd32_charp) path;
232 syscallarg(int) mode;
233 } */ *uap = v;
234 struct sys_open_args ua;
235 caddr_t sg = stackgap_init(p->p_emul);
236
237 SUNOS32TOP_UAP(path, const char);
238 SCARG(&ua, flags) = O_WRONLY | O_CREAT | O_TRUNC;
239 SUNOS32TO64_UAP(mode);
240
241 SUNOS32_CHECK_ALT_CREAT(p, &sg, SCARG(&ua, path));
242
243 return (sys_open(p, &ua, retval));
244 }
245
246 int
247 sunos32_sys_access(p, v, retval)
248 struct proc *p;
249 void *v;
250 register_t *retval;
251 {
252 struct sunos32_sys_access_args /* {
253 syscallarg(const netbsd32_charp) path;
254 syscallarg(int) flags;
255 } */ *uap = v;
256 struct sys_access_args ua;
257 caddr_t sg = stackgap_init(p->p_emul);
258
259 SUNOS32TOP_UAP(path, const char);
260 SUNOS32TO64_UAP(flags);
261 SUNOS32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path));
262
263 return (sys_access(p, &ua, retval));
264 }
265
266 static __inline void sunos32_from___stat13 __P((struct stat *, struct netbsd32_stat43 *));
267
268 static __inline void
269 sunos32_from___stat13(sbp, sb32p)
270 struct stat *sbp;
271 struct netbsd32_stat43 *sb32p;
272 {
273 sb32p->st_dev = sbp->st_dev;
274 sb32p->st_ino = sbp->st_ino;
275 sb32p->st_mode = sbp->st_mode;
276 sb32p->st_nlink = sbp->st_nlink;
277 sb32p->st_uid = sbp->st_uid;
278 sb32p->st_gid = sbp->st_gid;
279 sb32p->st_rdev = sbp->st_rdev;
280 if (sbp->st_size < (quad_t)1 << 32)
281 sb32p->st_size = sbp->st_size;
282 else
283 sb32p->st_size = -2;
284 sb32p->st_atimespec.tv_sec = (netbsd32_time_t)sbp->st_atimespec.tv_sec;
285 sb32p->st_atimespec.tv_nsec = (netbsd32_long)sbp->st_atimespec.tv_nsec;
286 sb32p->st_mtimespec.tv_sec = (netbsd32_time_t)sbp->st_mtimespec.tv_sec;
287 sb32p->st_mtimespec.tv_nsec = (netbsd32_long)sbp->st_mtimespec.tv_nsec;
288 sb32p->st_ctimespec.tv_sec = (netbsd32_time_t)sbp->st_ctimespec.tv_sec;
289 sb32p->st_ctimespec.tv_nsec = (netbsd32_long)sbp->st_ctimespec.tv_nsec;
290 sb32p->st_blksize = sbp->st_blksize;
291 sb32p->st_blocks = sbp->st_blocks;
292 sb32p->st_flags = sbp->st_flags;
293 sb32p->st_gen = sbp->st_gen;
294 }
295
296
297 int
298 sunos32_sys_stat(p, v, retval)
299 struct proc *p;
300 void *v;
301 register_t *retval;
302 {
303 struct sunos32_sys_stat_args /* {
304 syscallarg(const netbsd32_charp) path;
305 syscallarg(netbsd32_stat43p_t) ub;
306 } */ *uap = v;
307 struct netbsd32_stat43 sb32;
308 struct stat sb;
309 struct nameidata nd;
310 caddr_t sg;
311 const char *path;
312 int error;
313
314 path = (char *)(u_long)SCARG(uap, path);
315 sg = stackgap_init(p->p_emul);
316 SUNOS32_CHECK_ALT_EXIST(p, &sg, path);
317
318 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, path, p);
319 if ((error = namei(&nd)) != 0)
320 return (error);
321 error = vn_stat(nd.ni_vp, &sb, p);
322 vput(nd.ni_vp);
323 if (error)
324 return (error);
325 sunos32_from___stat13(&sb, &sb32);
326 error = copyout((caddr_t)&sb32, (caddr_t)(u_long)SCARG(uap, ub), sizeof (sb32));
327 return (error);
328 }
329
330 int
331 sunos32_sys_lstat(p, v, retval)
332 struct proc *p;
333 void *v;
334 register_t *retval;
335 {
336 struct sunos32_sys_lstat_args /* {
337 syscallarg(const netbsd32_charp) path;
338 syscallarg(netbsd32_stat43p_t) ub;
339 } */ *uap = v;
340 struct vnode *vp, *dvp;
341 struct stat sb, sb1;
342 struct netbsd32_stat43 sb32;
343 int error;
344 struct nameidata nd;
345 int ndflags;
346 const char *path;
347 caddr_t sg;
348
349 path = (char *)(u_long)SCARG(uap, path);
350 sg = stackgap_init(p->p_emul);
351 SUNOS32_CHECK_ALT_EXIST(p, &sg, path);
352
353 ndflags = NOFOLLOW | LOCKLEAF | LOCKPARENT;
354 again:
355 NDINIT(&nd, LOOKUP, ndflags, UIO_USERSPACE, path, p);
356 if ((error = namei(&nd))) {
357 if (error == EISDIR && (ndflags & LOCKPARENT) != 0) {
358 /*
359 * Should only happen on '/'. Retry without LOCKPARENT;
360 * this is safe since the vnode won't be a VLNK.
361 */
362 ndflags &= ~LOCKPARENT;
363 goto again;
364 }
365 return (error);
366 }
367 /*
368 * For symbolic links, always return the attributes of its
369 * containing directory, except for mode, size, and links.
370 */
371 vp = nd.ni_vp;
372 dvp = nd.ni_dvp;
373 if (vp->v_type != VLNK) {
374 if ((ndflags & LOCKPARENT) != 0) {
375 if (dvp == vp)
376 vrele(dvp);
377 else
378 vput(dvp);
379 }
380 error = vn_stat(vp, &sb, p);
381 vput(vp);
382 if (error)
383 return (error);
384 } else {
385 error = vn_stat(dvp, &sb, p);
386 vput(dvp);
387 if (error) {
388 vput(vp);
389 return (error);
390 }
391 error = vn_stat(vp, &sb1, p);
392 vput(vp);
393 if (error)
394 return (error);
395 sb.st_mode &= ~S_IFDIR;
396 sb.st_mode |= S_IFLNK;
397 sb.st_nlink = sb1.st_nlink;
398 sb.st_size = sb1.st_size;
399 sb.st_blocks = sb1.st_blocks;
400 }
401 sunos32_from___stat13(&sb, &sb32);
402 error = copyout((caddr_t)&sb32, (caddr_t)(u_long)SCARG(uap, ub), sizeof (sb32));
403 return (error);
404 }
405
406 int
407 sunos32_sys_execv(p, v, retval)
408 struct proc *p;
409 void *v;
410 register_t *retval;
411 {
412 struct sunos32_sys_execv_args /* {
413 syscallarg(const char *) path;
414 syscallarg(char **) argv;
415 } */ *uap = v;
416 struct sys_execve_args ua;
417 caddr_t sg;
418
419 SUNOS32TOP_UAP(path, const char);
420 SUNOS32TOP_UAP(argp, char *);
421 SCARG(&ua, envp) = NULL;
422 sg = stackgap_init(p->p_emul);
423 SUNOS32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path));
424
425 return netbsd32_execve2(p, &ua, retval);
426 }
427
428 int
429 sunos32_sys_execve(p, v, retval)
430 struct proc *p;
431 void *v;
432 register_t *retval;
433 {
434 struct sunos32_sys_execve_args /* {
435 syscallarg(const char *) path;
436 syscallarg(char **) argv;
437 syscallarg(char **) envp;
438 } */ *uap = v;
439 struct sys_execve_args ua;
440 caddr_t sg;
441
442 SUNOS32TOP_UAP(path, const char);
443 SUNOS32TOP_UAP(argp, char *);
444 SUNOS32TOP_UAP(envp, char *);
445 sg = stackgap_init(p->p_emul);
446 SUNOS32_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
447
448 return netbsd32_execve2(p, &ua, retval);
449 }
450
451 int
452 sunos32_sys_omsync(p, v, retval)
453 struct proc *p;
454 void *v;
455 register_t *retval;
456 {
457 struct sunos32_sys_omsync_args /* {
458 syscallarg(netbsd32_caddr_t) addr;
459 syscallarg(netbsd32_size_t) len;
460 syscallarg(int) flags;
461 } */ *uap = v;
462 struct netbsd32___msync13_args ouap;
463
464 SCARG(&ouap, addr) = SCARG(uap, addr);
465 SCARG(&ouap, len) = SCARG(uap, len);
466 SCARG(&ouap, flags) = SCARG(uap, flags);
467
468 return (netbsd32___msync13(p, &ouap, retval));
469 }
470
471 int
472 sunos32_sys_unmount(p, v, retval)
473 struct proc *p;
474 void *v;
475 register_t *retval;
476 {
477 struct sunos32_sys_unmount_args /* {
478 syscallarg(netbsd32_charp) path;
479 } */ *uap = v;
480 struct sys_unmount_args ua;
481
482 SUNOS32TOP_UAP(path, const char);
483 SCARG(&ua, flags) = 0;
484
485 return (sys_unmount(p, &ua, retval));
486 }
487
488 /*
489 * Conversion table for SunOS NFS mount flags.
490 */
491 static struct {
492 int sun_flg;
493 int bsd_flg;
494 } sunnfs_flgtab[] = {
495 { SUNNFS_SOFT, NFSMNT_SOFT },
496 { SUNNFS_WSIZE, NFSMNT_WSIZE },
497 { SUNNFS_RSIZE, NFSMNT_RSIZE },
498 { SUNNFS_TIMEO, NFSMNT_TIMEO },
499 { SUNNFS_RETRANS, NFSMNT_RETRANS },
500 { SUNNFS_HOSTNAME, 0 }, /* Ignored */
501 { SUNNFS_INT, NFSMNT_INT },
502 { SUNNFS_NOAC, 0 }, /* Ignored */
503 { SUNNFS_ACREGMIN, 0 }, /* Ignored */
504 { SUNNFS_ACREGMAX, 0 }, /* Ignored */
505 { SUNNFS_ACDIRMIN, 0 }, /* Ignored */
506 { SUNNFS_ACDIRMAX, 0 }, /* Ignored */
507 { SUNNFS_SECURE, 0 }, /* Ignored */
508 { SUNNFS_NOCTO, 0 }, /* Ignored */
509 { SUNNFS_POSIX, 0 } /* Ignored */
510 };
511
512 int
513 sunos32_sys_mount(p, v, retval)
514 struct proc *p;
515 void *v;
516 register_t *retval;
517 {
518 struct sunos32_sys_mount_args /* {
519 syscallarg(netbsd32_charp) type;
520 syscallarg(netbsd32_charp) path;
521 syscallarg(int) flags;
522 syscallarg(netbsd32_caddr_t) data;
523 } */ *uap = v;
524 struct sys_mount_args ua;
525 int oflags = SCARG(uap, flags), nflags, error;
526 char fsname[MFSNAMELEN];
527 caddr_t sg = stackgap_init(p->p_emul);
528
529 if (oflags & (SUNM_NOSUB | SUNM_SYS5))
530 return (EINVAL);
531 if ((oflags & SUNM_NEWTYPE) == 0)
532 return (EINVAL);
533 nflags = 0;
534 if (oflags & SUNM_RDONLY)
535 nflags |= MNT_RDONLY;
536 if (oflags & SUNM_NOSUID)
537 nflags |= MNT_NOSUID;
538 if (oflags & SUNM_REMOUNT)
539 nflags |= MNT_UPDATE;
540 SCARG(uap, flags) = nflags;
541
542 error = copyinstr((caddr_t)(u_long)SCARG(uap, type), fsname,
543 sizeof fsname, (size_t *)0);
544 if (error)
545 return (error);
546
547 if (strncmp(fsname, "4.2", sizeof fsname) == 0) {
548 SCARG(uap, type) = (netbsd32_charp)(u_long)stackgap_alloc(&sg, sizeof("ffs"));
549 error = copyout("ffs", (caddr_t)(u_long)SCARG(uap, type), sizeof("ffs"));
550 if (error)
551 return (error);
552 } else if (strncmp(fsname, "nfs", sizeof fsname) == 0) {
553 struct sunos_nfs_args sna;
554 struct sockaddr_in sain;
555 struct nfs_args na; /* XXX */
556 struct sockaddr sa;
557 int n;
558
559 error = copyin((caddr_t)(u_long)SCARG(uap, data), &sna, sizeof sna);
560 if (error)
561 return (error);
562 error = copyin(sna.addr, &sain, sizeof sain);
563 if (error)
564 return (error);
565 memcpy(&sa, &sain, sizeof sa);
566 sa.sa_len = sizeof(sain);
567 SCARG(uap, data) = (netbsd32_charp)(u_long)stackgap_alloc(&sg, sizeof(na));
568 na.version = NFS_ARGSVERSION;
569 na.addr = stackgap_alloc(&sg, sizeof(struct sockaddr));
570 na.addrlen = sizeof(struct sockaddr);
571 na.sotype = SOCK_DGRAM;
572 na.proto = IPPROTO_UDP;
573 na.fh = (void *)sna.fh;
574 na.fhsize = NFSX_V2FH;
575 na.flags = 0;
576 n = sizeof(sunnfs_flgtab) / sizeof(sunnfs_flgtab[0]);
577 while (--n >= 0)
578 if (sna.flags & sunnfs_flgtab[n].sun_flg)
579 na.flags |= sunnfs_flgtab[n].bsd_flg;
580 na.wsize = sna.wsize;
581 na.rsize = sna.rsize;
582 if (na.flags & NFSMNT_RSIZE) {
583 na.flags |= NFSMNT_READDIRSIZE;
584 na.readdirsize = na.rsize;
585 }
586 na.timeo = sna.timeo;
587 na.retrans = sna.retrans;
588 na.hostname = (char *)(u_long)sna.hostname;
589
590 error = copyout(&sa, na.addr, sizeof sa);
591 if (error)
592 return (error);
593 error = copyout(&na, (caddr_t)(u_long)SCARG(uap, data), sizeof na);
594 if (error)
595 return (error);
596 }
597 SUNOS32TOP_UAP(type, const char);
598 SUNOS32TOP_UAP(path, const char);
599 SUNOS32TO64_UAP(flags);
600 SUNOS32TOP_UAP(data, void);
601 return (sys_mount(p, &ua, retval));
602 }
603
604 #if defined(NFS)
605 int
606 async_daemon(p, v, retval)
607 struct proc *p;
608 void *v;
609 register_t *retval;
610 {
611 struct netbsd32_nfssvc_args ouap;
612
613 SCARG(&ouap, flag) = NFSSVC_BIOD;
614 SCARG(&ouap, argp) = NULL;
615
616 return (netbsd32_nfssvc(p, &ouap, retval));
617 }
618 #endif /* NFS */
619
620 void native_to_sunos_sigset __P((const sigset_t *, int *));
621 void sunos_to_native_sigset __P((const int, sigset_t *));
622
623 __inline__ void
624 native_to_sunos_sigset(ss, mask)
625 const sigset_t *ss;
626 int *mask;
627 {
628 *mask = ss->__bits[0];
629 }
630
631 __inline__ void
632 sunos_to_native_sigset(mask, ss)
633 const int mask;
634 sigset_t *ss;
635 {
636
637 ss->__bits[0] = mask;
638 ss->__bits[1] = 0;
639 ss->__bits[2] = 0;
640 ss->__bits[3] = 0;
641 }
642
643 int
644 sunos32_sys_sigpending(p, v, retval)
645 struct proc *p;
646 void *v;
647 register_t *retval;
648 {
649 struct sunos32_sys_sigpending_args /* {
650 syscallarg(netbsd32_intp) mask;
651 } */ *uap = v;
652 sigset_t ss;
653 int mask;
654
655 sigpending1(p, &ss);
656 native_to_sunos_sigset(&ss, &mask);
657
658 return (copyout((caddr_t)(u_long)&mask, (caddr_t)(u_long)SCARG(uap, mask), sizeof(int)));
659 }
660
661 int
662 sunos32_sys_sigsuspend(p, v, retval)
663 struct proc *p;
664 void *v;
665 register_t *retval;
666 {
667 struct sunos32_sys_sigsuspend_args /* {
668 syscallarg(int) mask;
669 } */ *uap = v;
670 int mask;
671 sigset_t ss;
672
673 mask = SCARG(uap, mask);
674 sunos_to_native_sigset(mask, &ss);
675 return (sigsuspend1(p, &ss));
676 }
677
678 /*
679 * Read Sun-style directory entries. We suck them into kernel space so
680 * that they can be massaged before being copied out to user code. Like
681 * SunOS, we squish out `empty' entries.
682 *
683 * This is quite ugly, but what do you expect from compatibility code?
684 */
685 int
686 sunos32_sys_getdents(p, v, retval)
687 struct proc *p;
688 void *v;
689 register_t *retval;
690 {
691 struct sunos32_sys_getdents_args /* {
692 syscallarg(int) fd;
693 syscallarg(netbsd32_charp) buf;
694 syscallarg(int) nbytes;
695 } */ *uap = v;
696 struct dirent *bdp;
697 struct vnode *vp;
698 caddr_t inp, buf; /* BSD-format */
699 int len, reclen; /* BSD-format */
700 caddr_t outp; /* Sun-format */
701 int resid, sunos_reclen;/* Sun-format */
702 struct file *fp;
703 struct uio auio;
704 struct iovec aiov;
705 struct sunos32_dirent idb;
706 off_t off; /* true file offset */
707 int buflen, error, eofflag;
708 off_t *cookiebuf, *cookie;
709 int ncookies;
710
711 /* getvnode() will use the descriptor for us */
712 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
713 return (error);
714
715 if ((fp->f_flag & FREAD) == 0) {
716 error = EBADF;
717 goto out1;
718 }
719
720 vp = (struct vnode *)fp->f_data;
721 if (vp->v_type != VDIR) {
722 error = EINVAL;
723 goto out1;
724 }
725
726 buflen = min(MAXBSIZE, SCARG(uap, nbytes));
727 buf = malloc(buflen, M_TEMP, M_WAITOK);
728 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
729 off = fp->f_offset;
730 again:
731 aiov.iov_base = buf;
732 aiov.iov_len = buflen;
733 auio.uio_iov = &aiov;
734 auio.uio_iovcnt = 1;
735 auio.uio_rw = UIO_READ;
736 auio.uio_segflg = UIO_SYSSPACE;
737 auio.uio_procp = p;
738 auio.uio_resid = buflen;
739 auio.uio_offset = off;
740 /*
741 * First we read into the malloc'ed buffer, then
742 * we massage it into user space, one record at a time.
743 */
744 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
745 &ncookies);
746 if (error)
747 goto out;
748
749 inp = buf;
750 outp = (caddr_t)(u_long)SCARG(uap, buf);
751 resid = SCARG(uap, nbytes);
752 if ((len = buflen - auio.uio_resid) == 0)
753 goto eof;
754
755 for (cookie = cookiebuf; len > 0; len -= reclen) {
756 bdp = (struct dirent *)inp;
757 reclen = bdp->d_reclen;
758 if (reclen & 3)
759 panic("sunos_getdents");
760 if ((*cookie >> 32) != 0) {
761 compat_offseterr(vp, "sunos_getdents");
762 error = EINVAL;
763 goto out;
764 }
765 if (bdp->d_fileno == 0) {
766 inp += reclen; /* it is a hole; squish it out */
767 off = *cookie++;
768 continue;
769 }
770 sunos_reclen = SUNOS32_RECLEN(&idb, bdp->d_namlen);
771 if (reclen > len || resid < sunos_reclen) {
772 /* entry too big for buffer, so just stop */
773 outp++;
774 break;
775 }
776 off = *cookie++; /* each entry points to next */
777 /*
778 * Massage in place to make a Sun-shaped dirent (otherwise
779 * we have to worry about touching user memory outside of
780 * the copyout() call).
781 */
782 idb.d_fileno = bdp->d_fileno;
783 idb.d_off = off;
784 idb.d_reclen = sunos_reclen;
785 idb.d_namlen = bdp->d_namlen;
786 strcpy(idb.d_name, bdp->d_name);
787 if ((error = copyout((caddr_t)&idb, outp, sunos_reclen)) != 0)
788 goto out;
789 /* advance past this real entry */
790 inp += reclen;
791 /* advance output past Sun-shaped entry */
792 outp += sunos_reclen;
793 resid -= sunos_reclen;
794 }
795
796 /* if we squished out the whole block, try again */
797 if (outp == (caddr_t)(u_long)SCARG(uap, buf))
798 goto again;
799 fp->f_offset = off; /* update the vnode offset */
800
801 eof:
802 *retval = SCARG(uap, nbytes) - resid;
803 out:
804 VOP_UNLOCK(vp, 0);
805 free(cookiebuf, M_TEMP);
806 free(buf, M_TEMP);
807 out1:
808 FILE_UNUSE(fp, p);
809 return (error);
810 }
811
812 #define SUNOS32__MAP_NEW 0x80000000 /* if not, old mmap & cannot handle */
813
814 int
815 sunos32_sys_mmap(p, v, retval)
816 struct proc *p;
817 void *v;
818 register_t *retval;
819 {
820 struct sunos32_sys_mmap_args /* {
821 syscallarg(netbsd32_voidp) addr;
822 syscallarg(netbsd32_size_t) len;
823 syscallarg(int) prot;
824 syscallarg(int) flags;
825 syscallarg(int) fd;
826 syscallarg(netbsd32_long) pos;
827 } */ *uap = v;
828 struct sys_mmap_args ua;
829 struct filedesc *fdp;
830 struct file *fp;
831 struct vnode *vp;
832 void *rt;
833 int error;
834
835 /*
836 * Verify the arguments.
837 */
838 if (SCARG(uap, prot) & ~(PROT_READ|PROT_WRITE|PROT_EXEC))
839 return (EINVAL); /* XXX still needed? */
840
841 if ((SCARG(uap, flags) & SUNOS32__MAP_NEW) == 0)
842 return (EINVAL);
843
844 SUNOS32TOP_UAP(addr, void);
845 SUNOS32TOX_UAP(len, size_t);
846 SUNOS32TO64_UAP(prot);
847 SCARG(&ua, flags) = SCARG(uap, flags) & ~SUNOS32__MAP_NEW;
848 SUNOS32TO64_UAP(fd);
849 SCARG(&ua, pad) = 0;
850 SUNOS32TOX_UAP(pos, off_t);
851
852 if ((SCARG(&ua, flags) & MAP_FIXED) == 0 &&
853 SCARG(&ua, addr) != 0 &&
854 SCARG(&ua, addr) < (void *)round_page((vaddr_t)p->p_vmspace->vm_daddr+MAXDSIZ))
855 SCARG(&ua, addr) = (void *)round_page((vaddr_t)p->p_vmspace->vm_daddr+MAXDSIZ);
856
857 /*
858 * Special case: if fd refers to /dev/zero, map as MAP_ANON. (XXX)
859 */
860 fdp = p->p_fd;
861 if ((fp = fd_getfile(fdp, SCARG(&ua, fd))) != NULL && /*XXX*/
862 fp->f_type == DTYPE_VNODE && /*XXX*/
863 (vp = (struct vnode *)fp->f_data)->v_type == VCHR && /*XXX*/
864 iszerodev(vp->v_rdev)) { /*XXX*/
865 SCARG(&ua, flags) |= MAP_ANON;
866 SCARG(&ua, fd) = -1;
867 }
868
869 error = sys_mmap(p, &ua, (register_t *)&rt);
870 if ((long)rt > (long)UINT_MAX)
871 printf("sunos32_mmap: retval out of range: %p", rt);
872 *retval = (netbsd32_voidp)(u_long)rt;
873 return (error);
874 }
875
876 #define MC_SYNC 1
877 #define MC_LOCK 2
878 #define MC_UNLOCK 3
879 #define MC_ADVISE 4
880 #define MC_LOCKAS 5
881 #define MC_UNLOCKAS 6
882
883 int
884 sunos32_sys_mctl(p, v, retval)
885 struct proc *p;
886 void *v;
887 register_t *retval;
888 {
889 struct sunos32_sys_mctl_args /* {
890 syscallarg(netbsd32_voidp) addr;
891 syscallarg(int) len;
892 syscallarg(int) func;
893 syscallarg(netbsd32_voidp) arg;
894 } */ *uap = v;
895
896 switch (SCARG(uap, func)) {
897 case MC_ADVISE: /* ignore for now */
898 return (0);
899 case MC_SYNC: /* translate to msync */
900 return (netbsd32___msync13(p, uap, retval));
901 default:
902 return (EINVAL);
903 }
904 }
905
906 int
907 sunos32_sys_setsockopt(p, v, retval)
908 struct proc *p;
909 void *v;
910 register_t *retval;
911 {
912 struct sunos32_sys_setsockopt_args /* {
913 syscallarg(int) s;
914 syscallarg(int) level;
915 syscallarg(int) name;
916 syscallarg(netbsd32_caddr_t) val;
917 syscallarg(int) valsize;
918 } */ *uap = v;
919 struct file *fp;
920 struct mbuf *m = NULL;
921 int error;
922
923 /* getsock() will use the descriptor for us */
924 if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
925 return (error);
926 #define SO_DONTLINGER (~SO_LINGER)
927 if (SCARG(uap, name) == SO_DONTLINGER) {
928 m = m_get(M_WAIT, MT_SOOPTS);
929 mtod(m, struct linger *)->l_onoff = 0;
930 m->m_len = sizeof(struct linger);
931 error = sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
932 SO_LINGER, m);
933 goto out;
934 }
935 if (SCARG(uap, level) == IPPROTO_IP) {
936 #define SUNOS_IP_MULTICAST_IF 2
937 #define SUNOS_IP_MULTICAST_TTL 3
938 #define SUNOS_IP_MULTICAST_LOOP 4
939 #define SUNOS_IP_ADD_MEMBERSHIP 5
940 #define SUNOS_IP_DROP_MEMBERSHIP 6
941 static int ipoptxlat[] = {
942 IP_MULTICAST_IF,
943 IP_MULTICAST_TTL,
944 IP_MULTICAST_LOOP,
945 IP_ADD_MEMBERSHIP,
946 IP_DROP_MEMBERSHIP
947 };
948 if (SCARG(uap, name) >= SUNOS_IP_MULTICAST_IF &&
949 SCARG(uap, name) <= SUNOS_IP_DROP_MEMBERSHIP) {
950 SCARG(uap, name) =
951 ipoptxlat[SCARG(uap, name) - SUNOS_IP_MULTICAST_IF];
952 }
953 }
954 if (SCARG(uap, valsize) > MLEN) {
955 error = EINVAL;
956 goto out;
957 }
958 if (SCARG(uap, val)) {
959 m = m_get(M_WAIT, MT_SOOPTS);
960 error = copyin((caddr_t)(u_long)SCARG(uap, val), mtod(m, caddr_t),
961 (u_int)SCARG(uap, valsize));
962 if (error) {
963 (void) m_free(m);
964 goto out;
965 }
966 m->m_len = SCARG(uap, valsize);
967 }
968 error = sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
969 SCARG(uap, name), m);
970 out:
971 FILE_UNUSE(fp, p);
972 return (error);
973 }
974
975 /*
976 * XXX: This needs cleaning up.
977 */
978 int
979 sunos32_sys_auditsys(p, v, retval)
980 struct proc *p;
981 void *v;
982 register_t *retval;
983 {
984 return 0;
985 }
986
987 int
988 sunos32_sys_uname(p, v, retval)
989 struct proc *p;
990 void *v;
991 register_t *retval;
992 {
993 struct sunos32_sys_uname_args /* {
994 syscallarg(sunos32_utsnamep_t) name;
995 } */ *uap = v;
996 struct sunos_utsname sut;
997
998 memset(&sut, 0, sizeof(sut));
999
1000 memcpy(sut.sysname, ostype, sizeof(sut.sysname) - 1);
1001 memcpy(sut.nodename, hostname, sizeof(sut.nodename));
1002 sut.nodename[sizeof(sut.nodename)-1] = '\0';
1003 memcpy(sut.release, osrelease, sizeof(sut.release) - 1);
1004 memcpy(sut.version, "1", sizeof(sut.version) - 1);
1005 memcpy(sut.machine, machine, sizeof(sut.machine) - 1);
1006
1007 return copyout((caddr_t)&sut, (caddr_t)(u_long)SCARG(uap, name),
1008 sizeof(struct sunos_utsname));
1009 }
1010
1011 int
1012 sunos32_sys_setpgrp(p, v, retval)
1013 struct proc *p;
1014 void *v;
1015 register_t *retval;
1016 {
1017 struct sunos32_sys_setpgrp_args /* {
1018 syscallarg(int) pid;
1019 syscallarg(int) pgid;
1020 } */ *uap = v;
1021
1022 /*
1023 * difference to our setpgid call is to include backwards
1024 * compatibility to pre-setsid() binaries. Do setsid()
1025 * instead of setpgid() in those cases where the process
1026 * tries to create a new session the old way.
1027 */
1028 if (!SCARG(uap, pgid) &&
1029 (!SCARG(uap, pid) || SCARG(uap, pid) == p->p_pid))
1030 return sys_setsid(p, uap, retval);
1031 else
1032 return netbsd32_setpgid(p, uap, retval);
1033 }
1034
1035 int
1036 sunos32_sys_open(p, v, retval)
1037 struct proc *p;
1038 void *v;
1039 register_t *retval;
1040 {
1041 struct sunos32_sys_open_args /* {
1042 syscallarg(const netbsd32_charp) path;
1043 syscallarg(int) flags;
1044 syscallarg(int) mode;
1045 } */ *uap = v;
1046 struct sys_open_args ua;
1047 int l, r;
1048 int noctty;
1049 int ret;
1050 caddr_t sg = stackgap_init(p->p_emul);
1051
1052 /* convert mode into NetBSD mode */
1053 l = SCARG(uap, flags);
1054 noctty = l & 0x8000;
1055 r = (l & (0x0001 | 0x0002 | 0x0008 | 0x0040 | 0x0200 | 0x0400 | 0x0800));
1056 r |= ((l & (0x0004 | 0x1000 | 0x4000)) ? O_NONBLOCK : 0);
1057 r |= ((l & 0x0080) ? O_SHLOCK : 0);
1058 r |= ((l & 0x0100) ? O_EXLOCK : 0);
1059 r |= ((l & 0x2000) ? O_FSYNC : 0);
1060
1061 SUNOS32TOP_UAP(path, const char);
1062 SCARG(&ua, flags) = r;
1063 SUNOS32TO64_UAP(mode);
1064
1065 if (r & O_CREAT)
1066 SUNOS32_CHECK_ALT_CREAT(p, &sg, SCARG(&ua, path));
1067 else
1068 SUNOS32_CHECK_ALT_EXIST(p, &sg, SCARG(&ua, path));
1069
1070 ret = sys_open(p, &ua, retval);
1071
1072 if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
1073 struct filedesc *fdp = p->p_fd;
1074 struct file *fp;
1075
1076 fp = fd_getfile(fdp, *retval);
1077
1078 /* ignore any error, just give it a try */
1079 if (fp != NULL && fp->f_type == DTYPE_VNODE)
1080 (fp->f_ops->fo_ioctl)(fp, TIOCSCTTY, (caddr_t)0, p);
1081 }
1082 return ret;
1083 }
1084
1085 #if defined (NFSSERVER)
1086 int
1087 sunos32_sys_nfssvc(p, v, retval)
1088 struct proc *p;
1089 void *v;
1090 register_t *retval;
1091 {
1092 #if 0
1093 struct sunos32_sys_nfssvc_args *uap = v;
1094 struct emul *e = p->p_emul;
1095 struct sys_nfssvc_args outuap;
1096 struct sockaddr sa;
1097 int error;
1098 caddr_t sg = stackgap_init(p->p_emul);
1099
1100 memset(&outuap, 0, sizeof outuap);
1101 SCARG(&outuap, fd) = SCARG(uap, fd);
1102 SCARG(&outuap, mskval) = stackgap_alloc(&sg, sizeof(sa));
1103 SCARG(&outuap, msklen) = sizeof(sa);
1104 SCARG(&outuap, mtchval) = stackgap_alloc(&sg, sizeof(sa));
1105 SCARG(&outuap, mtchlen) = sizeof(sa);
1106
1107 memset(&sa, 0, sizeof sa);
1108 if (error = copyout(&sa, SCARG(&outuap, mskval), SCARG(&outuap, msklen)))
1109 return (error);
1110 if (error = copyout(&sa, SCARG(&outuap, mtchval), SCARG(&outuap, mtchlen)))
1111 return (error);
1112
1113 return nfssvc(p, &outuap, retval);
1114 #else
1115 return (ENOSYS);
1116 #endif
1117 }
1118 #endif /* NFSSERVER */
1119
1120 int
1121 sunos32_sys_ustat(p, v, retval)
1122 struct proc *p;
1123 void *v;
1124 register_t *retval;
1125 {
1126 struct sunos32_sys_ustat_args /* {
1127 syscallarg(int) dev;
1128 syscallarg(sunos32_ustatp_t) buf;
1129 } */ *uap = v;
1130 struct sunos_ustat us;
1131 int error;
1132
1133 memset(&us, 0, sizeof us);
1134
1135 /*
1136 * XXX: should set f_tfree and f_tinode at least
1137 * How do we translate dev -> fstat? (and then to sunos_ustat)
1138 */
1139
1140 if ((error = copyout(&us, (caddr_t)(u_long)SCARG(uap, buf), sizeof us)) != 0)
1141 return (error);
1142 return 0;
1143 }
1144
1145 int
1146 sunos32_sys_quotactl(p, v, retval)
1147 struct proc *p;
1148 void *v;
1149 register_t *retval;
1150 {
1151
1152 return EINVAL;
1153 }
1154
1155 int
1156 sunos32_sys_vhangup(p, v, retval)
1157 struct proc *p;
1158 void *v;
1159 register_t *retval;
1160 {
1161 struct session *sp = p->p_session;
1162
1163 if (sp->s_ttyvp == 0)
1164 return 0;
1165
1166 if (sp->s_ttyp && sp->s_ttyp->t_session == sp && sp->s_ttyp->t_pgrp)
1167 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
1168
1169 (void) ttywait(sp->s_ttyp);
1170 if (sp->s_ttyvp)
1171 VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
1172 if (sp->s_ttyvp)
1173 vrele(sp->s_ttyvp);
1174 sp->s_ttyvp = NULL;
1175
1176 return 0;
1177 }
1178
1179 static int
1180 sunstatfs(sp, buf)
1181 struct statfs *sp;
1182 caddr_t buf;
1183 {
1184 struct sunos_statfs ssfs;
1185
1186 memset(&ssfs, 0, sizeof ssfs);
1187 ssfs.f_type = 0;
1188 ssfs.f_bsize = sp->f_bsize;
1189 ssfs.f_blocks = sp->f_blocks;
1190 ssfs.f_bfree = sp->f_bfree;
1191 ssfs.f_bavail = sp->f_bavail;
1192 ssfs.f_files = sp->f_files;
1193 ssfs.f_ffree = sp->f_ffree;
1194 ssfs.f_fsid = sp->f_fsid;
1195 return copyout((caddr_t)&ssfs, buf, sizeof ssfs);
1196 }
1197
1198 int
1199 sunos32_sys_statfs(p, v, retval)
1200 struct proc *p;
1201 void *v;
1202 register_t *retval;
1203 {
1204 struct sunos32_sys_statfs_args /* {
1205 syscallarg(const netbsd32_charp) path;
1206 syscallarg(sunos32_statfsp_t) buf;
1207 } */ *uap = v;
1208 struct mount *mp;
1209 struct statfs *sp;
1210 int error;
1211 struct nameidata nd;
1212
1213 caddr_t sg = stackgap_init(p->p_emul);
1214 SUNOS32_CHECK_ALT_EXIST(p, &sg, SCARG(uap, path));
1215
1216 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, (caddr_t)(u_long)SCARG(uap, path), p);
1217 if ((error = namei(&nd)) != 0)
1218 return (error);
1219 mp = nd.ni_vp->v_mount;
1220 sp = &mp->mnt_stat;
1221 vrele(nd.ni_vp);
1222 if ((error = VFS_STATFS(mp, sp, p)) != 0)
1223 return (error);
1224 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1225 return sunstatfs(sp, (caddr_t)(u_long)SCARG(uap, buf));
1226 }
1227
1228 int
1229 sunos32_sys_fstatfs(p, v, retval)
1230 struct proc *p;
1231 void *v;
1232 register_t *retval;
1233 {
1234 struct sunos32_sys_fstatfs_args /* {
1235 syscallarg(int) fd;
1236 syscallarg(sunos32_statfsp_t) buf;
1237 } */ *uap = v;
1238 struct file *fp;
1239 struct mount *mp;
1240 struct statfs *sp;
1241 int error;
1242
1243 /* getvnode() will use the descriptor for us */
1244 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1245 return (error);
1246 mp = ((struct vnode *)fp->f_data)->v_mount;
1247 sp = &mp->mnt_stat;
1248 if ((error = VFS_STATFS(mp, sp, p)) != 0)
1249 goto out;
1250 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1251 error = sunstatfs(sp, (caddr_t)(u_long)SCARG(uap, buf));
1252 out:
1253 FILE_UNUSE(fp, p);
1254 return (error);
1255 }
1256
1257 int
1258 sunos32_sys_exportfs(p, v, retval)
1259 struct proc *p;
1260 void *v;
1261 register_t *retval;
1262 {
1263 /*
1264 * XXX: should perhaps translate into a mount(2)
1265 * with MOUNT_EXPORT?
1266 */
1267 return 0;
1268 }
1269
1270 int
1271 sunos32_sys_mknod(p, v, retval)
1272 struct proc *p;
1273 void *v;
1274 register_t *retval;
1275 {
1276 struct sunos32_sys_mknod_args /* {
1277 syscallarg(const netbsd32_charp) path;
1278 syscallarg(int) mode;
1279 syscallarg(int) dev;
1280 } */ *uap = v;
1281
1282 caddr_t sg = stackgap_init(p->p_emul);
1283 SUNOS32_CHECK_ALT_CREAT(p, &sg, SCARG(uap, path));
1284
1285 /* netbsd32_mkfifo/mknod to not do alt checking */
1286 if (S_ISFIFO(SCARG(uap, mode)))
1287 return netbsd32_mkfifo(p, (struct netbsd32_mkfifo_args *)uap, retval);
1288
1289 return netbsd32_mknod(p, (struct netbsd32_mknod_args *)uap, retval);
1290 }
1291
1292 #define SUNOS_SC_ARG_MAX 1
1293 #define SUNOS_SC_CHILD_MAX 2
1294 #define SUNOS_SC_CLK_TCK 3
1295 #define SUNOS_SC_NGROUPS_MAX 4
1296 #define SUNOS_SC_OPEN_MAX 5
1297 #define SUNOS_SC_JOB_CONTROL 6
1298 #define SUNOS_SC_SAVED_IDS 7
1299 #define SUNOS_SC_VERSION 8
1300
1301 int
1302 sunos32_sys_sysconf(p, v, retval)
1303 struct proc *p;
1304 void *v;
1305 register_t *retval;
1306 {
1307 struct sunos32_sys_sysconf_args /* {
1308 syscallarg(int) name;
1309 } */ *uap = v;
1310 extern int maxfiles;
1311
1312 switch(SCARG(uap, name)) {
1313 case SUNOS_SC_ARG_MAX:
1314 *retval = ARG_MAX;
1315 break;
1316 case SUNOS_SC_CHILD_MAX:
1317 *retval = maxproc;
1318 break;
1319 case SUNOS_SC_CLK_TCK:
1320 *retval = 60; /* should this be `hz', ie. 100? */
1321 break;
1322 case SUNOS_SC_NGROUPS_MAX:
1323 *retval = NGROUPS_MAX;
1324 break;
1325 case SUNOS_SC_OPEN_MAX:
1326 *retval = maxfiles;
1327 break;
1328 case SUNOS_SC_JOB_CONTROL:
1329 *retval = 1;
1330 break;
1331 case SUNOS_SC_SAVED_IDS:
1332 #ifdef _POSIX_SAVED_IDS
1333 *retval = 1;
1334 #else
1335 *retval = 0;
1336 #endif
1337 break;
1338 case SUNOS_SC_VERSION:
1339 *retval = 198808;
1340 break;
1341 default:
1342 return EINVAL;
1343 }
1344 return 0;
1345 }
1346
1347 #define SUNOS_RLIMIT_NOFILE 6 /* Other RLIMIT_* are the same */
1348 #define SUNOS_RLIM_NLIMITS 7
1349
1350 int
1351 sunos32_sys_getrlimit(p, v, retval)
1352 struct proc *p;
1353 void *v;
1354 register_t *retval;
1355 {
1356 struct sunos32_sys_getrlimit_args /* {
1357 syscallarg(u_int) which;
1358 syscallarg(netbsd32_orlimitp_t) rlp;
1359 } */ *uap = v;
1360
1361 if (SCARG(uap, which) >= SUNOS_RLIM_NLIMITS)
1362 return EINVAL;
1363
1364 if (SCARG(uap, which) == SUNOS_RLIMIT_NOFILE)
1365 SCARG(uap, which) = RLIMIT_NOFILE;
1366
1367 return compat_43_netbsd32_ogetrlimit(p, uap, retval);
1368 }
1369
1370 int
1371 sunos32_sys_setrlimit(p, v, retval)
1372 struct proc *p;
1373 void *v;
1374 register_t *retval;
1375 {
1376 struct sunos32_sys_setrlimit_args /* {
1377 syscallarg(u_int) which;
1378 syscallarg(netbsd32_orlimitp_t) rlp;
1379 } */ *uap = v;
1380
1381 if (SCARG(uap, which) >= SUNOS_RLIM_NLIMITS)
1382 return EINVAL;
1383
1384 if (SCARG(uap, which) == SUNOS_RLIMIT_NOFILE)
1385 SCARG(uap, which) = RLIMIT_NOFILE;
1386
1387 return compat_43_netbsd32_osetrlimit(p, uap, retval);
1388 }
1389
1390 /* for the m68k machines */
1391 #ifndef PT_GETFPREGS
1392 #define PT_GETFPREGS -1
1393 #endif
1394 #ifndef PT_SETFPREGS
1395 #define PT_SETFPREGS -1
1396 #endif
1397
1398 static int sreq2breq[] = {
1399 PT_TRACE_ME, PT_READ_I, PT_READ_D, -1,
1400 PT_WRITE_I, PT_WRITE_D, -1, PT_CONTINUE,
1401 PT_KILL, -1, PT_ATTACH, PT_DETACH,
1402 PT_GETREGS, PT_SETREGS, PT_GETFPREGS, PT_SETFPREGS
1403 };
1404 static int nreqs = sizeof(sreq2breq) / sizeof(sreq2breq[0]);
1405
1406 int
1407 sunos32_sys_ptrace(p, v, retval)
1408 struct proc *p;
1409 void *v;
1410 register_t *retval;
1411 {
1412 struct sunos32_sys_ptrace_args /* {
1413 syscallarg(int) req;
1414 syscallarg(pid_t) pid;
1415 syscallarg(netbsd32_caddr_t) addr;
1416 syscallarg(int) data;
1417 syscallarg(netbsd32_charp) addr2;
1418 } */ *uap = v;
1419 struct netbsd32_ptrace_args pa;
1420 int req;
1421
1422 req = SCARG(uap, req);
1423
1424 if (req < 0 || req >= nreqs)
1425 return (EINVAL);
1426
1427 req = sreq2breq[req];
1428 if (req == -1)
1429 return (EINVAL);
1430
1431 SCARG(&pa, req) = req;
1432 SCARG(&pa, pid) = (pid_t)SCARG(uap, pid);
1433 SCARG(&pa, addr) = SCARG(uap, addr);
1434 SCARG(&pa, data) = SCARG(uap, data);
1435
1436 return netbsd32_ptrace(p, &pa, retval);
1437 }
1438
1439 /*
1440 * SunOS reboot system call (for compatibility).
1441 * Sun lets you pass in a boot string which the PROM
1442 * saves and provides to the next boot program.
1443 */
1444
1445 #define SUNOS_RB_ASKNAME 0x001
1446 #define SUNOS_RB_SINGLE 0x002
1447 #define SUNOS_RB_NOSYNC 0x004
1448 #define SUNOS_RB_HALT 0x008
1449 #define SUNOS_RB_DUMP 0x080
1450 #define SUNOS_RB_STRING 0x200
1451
1452 static struct sunos_howto_conv {
1453 int sun_howto;
1454 int bsd_howto;
1455 } sunos_howto_conv[] = {
1456 { SUNOS_RB_ASKNAME, RB_ASKNAME },
1457 { SUNOS_RB_SINGLE, RB_SINGLE },
1458 { SUNOS_RB_NOSYNC, RB_NOSYNC },
1459 { SUNOS_RB_HALT, RB_HALT },
1460 { SUNOS_RB_DUMP, RB_DUMP },
1461 { SUNOS_RB_STRING, RB_STRING },
1462 { 0x000, 0 },
1463 };
1464
1465 int
1466 sunos32_sys_reboot(p, v, retval)
1467 struct proc *p;
1468 void *v;
1469 register_t *retval;
1470 {
1471 struct sunos32_sys_reboot_args /* {
1472 syscallarg(int) howto;
1473 syscallarg(netbsd32_charp) bootstr;
1474 } */ *uap = v;
1475 struct sys_reboot_args ua;
1476 struct sunos_howto_conv *convp;
1477 int error, bsd_howto, sun_howto;
1478 char *bootstr;
1479
1480 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1481 return (error);
1482
1483 /*
1484 * Convert howto bits to BSD format.
1485 */
1486 sun_howto = SCARG(uap, howto);
1487 bsd_howto = 0;
1488 convp = sunos_howto_conv;
1489 while (convp->sun_howto) {
1490 if (sun_howto & convp->sun_howto)
1491 bsd_howto |= convp->bsd_howto;
1492 convp++;
1493 }
1494
1495 /*
1496 * Sun RB_STRING (Get user supplied bootstring.)
1497 * If the machine supports passing a string to the
1498 * next booted kernel.
1499 */
1500 if (sun_howto & SUNOS_RB_STRING)
1501 bootstr = (char *)(u_long)SCARG(uap, bootstr);
1502 else
1503 bootstr = NULL;
1504
1505 SCARG(&ua, opt) = bsd_howto;
1506 SCARG(&ua, bootstr) = bootstr;
1507 return (sys_reboot(p, &ua, retval));
1508 }
1509
1510 /*
1511 * Generalized interface signal handler, 4.3-compatible.
1512 */
1513 /* ARGSUSED */
1514 int
1515 sunos32_sys_sigvec(p, v, retval)
1516 struct proc *p;
1517 void *v;
1518 register_t *retval;
1519 {
1520 struct sunos32_sys_sigvec_args /* {
1521 syscallarg(int) signum;
1522 syscallarg(struct sigvec *) nsv;
1523 syscallarg(struct sigvec *) osv;
1524 } */ *uap = v;
1525 struct netbsd32_sigvec sv;
1526 struct sigaction nsa, osa;
1527 int error;
1528
1529 if (SCARG(uap, nsv)) {
1530 error = copyin((caddr_t)(u_long)SCARG(uap, nsv), &sv, sizeof(sv));
1531 if (error != 0)
1532 return (error);
1533
1534 /*
1535 * SunOS uses the mask 0x0004 as SV_RESETHAND
1536 * meaning: `reset to SIG_DFL on delivery'.
1537 * We support only the bits in: 0xF
1538 * (those bits are the same as ours)
1539 */
1540 if (sv.sv_flags & ~0xF)
1541 return (EINVAL);
1542
1543 sunos32_sigvec_to_sigaction(&sv, &nsa);
1544 }
1545 error = sigaction1(p, SCARG(uap, signum),
1546 SCARG(uap, nsv) ? &nsa : 0,
1547 SCARG(uap, osv) ? &osa : 0);
1548 if (error != 0)
1549 return (error);
1550
1551 if (SCARG(uap, osv)) {
1552 sunos32_sigvec_from_sigaction(&sv, &osa);
1553 error = copyout(&sv, (caddr_t)(u_long)SCARG(uap, osv), sizeof(sv));
1554 if (error != 0)
1555 return (error);
1556 }
1557
1558 return (0);
1559 }
1560