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