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