1/*- 2 * Copyright (c) 1995 Steven Wallace 3 * Copyright (c) 1994, 1995 Scott Bartram 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratory. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. All advertising materials mentioning features or use of this software 25 * must display the following acknowledgement: 26 * This product includes software developed by the University of 27 * California, Berkeley and its contributors. 28 * 4. Neither the name of the University nor the names of its contributors 29 * may be used to endorse or promote products derived from this software 30 * without specific prior written permission. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 * 44 * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp 45 * 46 * @(#)sun_misc.c 8.1 (Berkeley) 6/18/93 47 */ 48 49#include <sys/cdefs.h>
| 1/*- 2 * Copyright (c) 1995 Steven Wallace 3 * Copyright (c) 1994, 1995 Scott Bartram 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratory. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. All advertising materials mentioning features or use of this software 25 * must display the following acknowledgement: 26 * This product includes software developed by the University of 27 * California, Berkeley and its contributors. 28 * 4. Neither the name of the University nor the names of its contributors 29 * may be used to endorse or promote products derived from this software 30 * without specific prior written permission. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 * 44 * from: Header: sun_misc.c,v 1.16 93/04/07 02:46:27 torek Exp 45 * 46 * @(#)sun_misc.c 8.1 (Berkeley) 6/18/93 47 */ 48 49#include <sys/cdefs.h>
|
50__FBSDID("$FreeBSD: head/sys/i386/ibcs2/ibcs2_misc.c 193511 2009-06-05 14:55:22Z rwatson $");
| 50__FBSDID("$FreeBSD: head/sys/i386/ibcs2/ibcs2_misc.c 194498 2009-06-19 17:10:35Z brooks $");
|
51 52/* 53 * IBCS2 compatibility module. 54 * 55 * IBCS2 system calls that are implemented differently in BSD are 56 * handled here. 57 */ 58#include <sys/param.h> 59#include <sys/systm.h> 60#include <sys/dirent.h> 61#include <sys/fcntl.h> 62#include <sys/filedesc.h> 63#include <sys/imgact.h> 64#include <sys/kernel.h> 65#include <sys/lock.h> 66#include <sys/malloc.h> 67#include <sys/file.h> /* Must come after sys/malloc.h */ 68#include <sys/mutex.h> 69#include <sys/priv.h> 70#include <sys/reboot.h> 71#include <sys/resourcevar.h> 72#include <sys/stat.h> 73#include <sys/sysctl.h> 74#include <sys/syscallsubr.h> 75#include <sys/sysproto.h> 76#include <sys/time.h> 77#include <sys/times.h> 78#include <sys/vnode.h> 79#include <sys/wait.h> 80 81#include <machine/cpu.h> 82 83#include <i386/ibcs2/ibcs2_dirent.h> 84#include <i386/ibcs2/ibcs2_signal.h> 85#include <i386/ibcs2/ibcs2_proto.h> 86#include <i386/ibcs2/ibcs2_unistd.h> 87#include <i386/ibcs2/ibcs2_util.h> 88#include <i386/ibcs2/ibcs2_utime.h> 89#include <i386/ibcs2/ibcs2_xenix.h> 90 91#include <security/mac/mac_framework.h> 92 93int 94ibcs2_ulimit(td, uap) 95 struct thread *td; 96 struct ibcs2_ulimit_args *uap; 97{ 98 struct rlimit rl; 99 struct proc *p; 100 int error; 101#define IBCS2_GETFSIZE 1 102#define IBCS2_SETFSIZE 2 103#define IBCS2_GETPSIZE 3 104#define IBCS2_GETDTABLESIZE 4 105 106 p = td->td_proc; 107 switch (uap->cmd) { 108 case IBCS2_GETFSIZE: 109 PROC_LOCK(p); 110 td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); 111 PROC_UNLOCK(p); 112 if (td->td_retval[0] == -1) 113 td->td_retval[0] = 0x7fffffff; 114 return 0; 115 case IBCS2_SETFSIZE: 116 PROC_LOCK(p); 117 rl.rlim_max = lim_max(p, RLIMIT_FSIZE); 118 PROC_UNLOCK(p); 119 rl.rlim_cur = uap->newlimit; 120 error = kern_setrlimit(td, RLIMIT_FSIZE, &rl); 121 if (!error) { 122 PROC_LOCK(p); 123 td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); 124 PROC_UNLOCK(p); 125 } else { 126 DPRINTF(("failed ")); 127 } 128 return error; 129 case IBCS2_GETPSIZE: 130 PROC_LOCK(p); 131 td->td_retval[0] = lim_cur(p, RLIMIT_RSS); /* XXX */ 132 PROC_UNLOCK(p); 133 return 0; 134 case IBCS2_GETDTABLESIZE: 135 uap->cmd = IBCS2_SC_OPEN_MAX; 136 return ibcs2_sysconf(td, (struct ibcs2_sysconf_args *)uap); 137 default: 138 return ENOSYS; 139 } 140} 141 142#define IBCS2_WSTOPPED 0177 143#define IBCS2_STOPCODE(sig) ((sig) << 8 | IBCS2_WSTOPPED) 144int 145ibcs2_wait(td, uap) 146 struct thread *td; 147 struct ibcs2_wait_args *uap; 148{ 149 int error, options, status; 150 int *statusp; 151 pid_t pid; 152 struct trapframe *tf = td->td_frame; 153 154 if ((tf->tf_eflags & (PSL_Z|PSL_PF|PSL_N|PSL_V)) 155 == (PSL_Z|PSL_PF|PSL_N|PSL_V)) { 156 /* waitpid */ 157 pid = uap->a1; 158 statusp = (int *)uap->a2; 159 options = uap->a3; 160 } else { 161 /* wait */ 162 pid = WAIT_ANY; 163 statusp = (int *)uap->a1; 164 options = 0; 165 } 166 error = kern_wait(td, pid, &status, options, NULL); 167 if (error) 168 return error; 169 if (statusp) { 170 /* 171 * Convert status/signal result. 172 */ 173 if (WIFSTOPPED(status)) { 174 if (WSTOPSIG(status) <= 0 || 175 WSTOPSIG(status) > IBCS2_SIGTBLSZ) 176 return (EINVAL); 177 status = 178 IBCS2_STOPCODE(bsd_to_ibcs2_sig[_SIG_IDX(WSTOPSIG(status))]); 179 } else if (WIFSIGNALED(status)) { 180 if (WTERMSIG(status) <= 0 || 181 WTERMSIG(status) > IBCS2_SIGTBLSZ) 182 return (EINVAL); 183 status = bsd_to_ibcs2_sig[_SIG_IDX(WTERMSIG(status))]; 184 } 185 /* else exit status -- identical */ 186 187 /* record result/status */ 188 td->td_retval[1] = status; 189 return copyout(&status, statusp, sizeof(status)); 190 } 191 192 return 0; 193} 194 195int 196ibcs2_execv(td, uap) 197 struct thread *td; 198 struct ibcs2_execv_args *uap; 199{ 200 struct image_args eargs; 201 char *path; 202 int error; 203 204 CHECKALTEXIST(td, uap->path, &path); 205 206 error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, NULL); 207 free(path, M_TEMP); 208 if (error == 0) 209 error = kern_execve(td, &eargs, NULL); 210 return (error); 211} 212 213int 214ibcs2_execve(td, uap) 215 struct thread *td; 216 struct ibcs2_execve_args *uap; 217{ 218 struct image_args eargs; 219 char *path; 220 int error; 221 222 CHECKALTEXIST(td, uap->path, &path); 223 224 error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, 225 uap->envp); 226 free(path, M_TEMP); 227 if (error == 0) 228 error = kern_execve(td, &eargs, NULL); 229 return (error); 230} 231 232int 233ibcs2_umount(td, uap) 234 struct thread *td; 235 struct ibcs2_umount_args *uap; 236{ 237 struct unmount_args um; 238 239 um.path = uap->name; 240 um.flags = 0; 241 return unmount(td, &um); 242} 243 244int 245ibcs2_mount(td, uap) 246 struct thread *td; 247 struct ibcs2_mount_args *uap; 248{ 249#ifdef notyet 250 int oflags = uap->flags, nflags, error; 251 char fsname[MFSNAMELEN]; 252 253 if (oflags & (IBCS2_MS_NOSUB | IBCS2_MS_SYS5)) 254 return (EINVAL); 255 if ((oflags & IBCS2_MS_NEWTYPE) == 0) 256 return (EINVAL); 257 nflags = 0; 258 if (oflags & IBCS2_MS_RDONLY) 259 nflags |= MNT_RDONLY; 260 if (oflags & IBCS2_MS_NOSUID) 261 nflags |= MNT_NOSUID; 262 if (oflags & IBCS2_MS_REMOUNT) 263 nflags |= MNT_UPDATE; 264 uap->flags = nflags; 265 266 if (error = copyinstr((caddr_t)uap->type, fsname, sizeof fsname, 267 (u_int *)0)) 268 return (error); 269 270 if (strcmp(fsname, "4.2") == 0) { 271 uap->type = (caddr_t)STACK_ALLOC(); 272 if (error = copyout("ufs", uap->type, sizeof("ufs"))) 273 return (error); 274 } else if (strcmp(fsname, "nfs") == 0) { 275 struct ibcs2_nfs_args sna; 276 struct sockaddr_in sain; 277 struct nfs_args na; 278 struct sockaddr sa; 279 280 if (error = copyin(uap->data, &sna, sizeof sna)) 281 return (error); 282 if (error = copyin(sna.addr, &sain, sizeof sain)) 283 return (error); 284 bcopy(&sain, &sa, sizeof sa); 285 sa.sa_len = sizeof(sain); 286 uap->data = (caddr_t)STACK_ALLOC(); 287 na.addr = (struct sockaddr *)((int)uap->data + sizeof na); 288 na.sotype = SOCK_DGRAM; 289 na.proto = IPPROTO_UDP; 290 na.fh = (nfsv2fh_t *)sna.fh; 291 na.flags = sna.flags; 292 na.wsize = sna.wsize; 293 na.rsize = sna.rsize; 294 na.timeo = sna.timeo; 295 na.retrans = sna.retrans; 296 na.hostname = sna.hostname; 297 298 if (error = copyout(&sa, na.addr, sizeof sa)) 299 return (error); 300 if (error = copyout(&na, uap->data, sizeof na)) 301 return (error); 302 } 303 return (mount(td, uap)); 304#else 305 return EINVAL; 306#endif 307} 308 309/* 310 * Read iBCS2-style directory entries. We suck them into kernel space so 311 * that they can be massaged before being copied out to user code. Like 312 * SunOS, we squish out `empty' entries. 313 * 314 * This is quite ugly, but what do you expect from compatibility code? 315 */ 316 317int 318ibcs2_getdents(td, uap) 319 struct thread *td; 320 register struct ibcs2_getdents_args *uap; 321{ 322 register struct vnode *vp; 323 register caddr_t inp, buf; /* BSD-format */ 324 register int len, reclen; /* BSD-format */ 325 register caddr_t outp; /* iBCS2-format */ 326 register int resid; /* iBCS2-format */ 327 struct file *fp; 328 struct uio auio; 329 struct iovec aiov; 330 struct ibcs2_dirent idb; 331 off_t off; /* true file offset */ 332 int buflen, error, eofflag, vfslocked; 333 u_long *cookies = NULL, *cookiep; 334 int ncookies; 335#define BSD_DIRENT(cp) ((struct dirent *)(cp)) 336#define IBCS2_RECLEN(reclen) (reclen + sizeof(u_short)) 337 338 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 339 return (error); 340 if ((fp->f_flag & FREAD) == 0) { 341 fdrop(fp, td); 342 return (EBADF); 343 } 344 vp = fp->f_vnode; 345 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 346 if (vp->v_type != VDIR) { /* XXX vnode readdir op should do this */ 347 VFS_UNLOCK_GIANT(vfslocked); 348 fdrop(fp, td); 349 return (EINVAL); 350 } 351 352 off = fp->f_offset; 353#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ 354 buflen = max(DIRBLKSIZ, uap->nbytes); 355 buflen = min(buflen, MAXBSIZE); 356 buf = malloc(buflen, M_TEMP, M_WAITOK); 357 vn_lock(vp, LK_SHARED | LK_RETRY); 358again: 359 aiov.iov_base = buf; 360 aiov.iov_len = buflen; 361 auio.uio_iov = &aiov; 362 auio.uio_iovcnt = 1; 363 auio.uio_rw = UIO_READ; 364 auio.uio_segflg = UIO_SYSSPACE; 365 auio.uio_td = td; 366 auio.uio_resid = buflen; 367 auio.uio_offset = off; 368 369 if (cookies) { 370 free(cookies, M_TEMP); 371 cookies = NULL; 372 } 373 374#ifdef MAC 375 error = mac_vnode_check_readdir(td->td_ucred, vp); 376 if (error) 377 goto out; 378#endif 379 380 /* 381 * First we read into the malloc'ed buffer, then 382 * we massage it into user space, one record at a time. 383 */ 384 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) 385 goto out; 386 inp = buf; 387 outp = uap->buf; 388 resid = uap->nbytes; 389 if ((len = buflen - auio.uio_resid) <= 0) 390 goto eof; 391 392 cookiep = cookies; 393 394 if (cookies) { 395 /* 396 * When using cookies, the vfs has the option of reading from 397 * a different offset than that supplied (UFS truncates the 398 * offset to a block boundary to make sure that it never reads 399 * partway through a directory entry, even if the directory 400 * has been compacted). 401 */ 402 while (len > 0 && ncookies > 0 && *cookiep <= off) { 403 len -= BSD_DIRENT(inp)->d_reclen; 404 inp += BSD_DIRENT(inp)->d_reclen; 405 cookiep++; 406 ncookies--; 407 } 408 } 409 410 for (; len > 0; len -= reclen) { 411 if (cookiep && ncookies == 0) 412 break; 413 reclen = BSD_DIRENT(inp)->d_reclen; 414 if (reclen & 3) { 415 printf("ibcs2_getdents: reclen=%d\n", reclen); 416 error = EFAULT; 417 goto out; 418 } 419 if (BSD_DIRENT(inp)->d_fileno == 0) { 420 inp += reclen; /* it is a hole; squish it out */ 421 if (cookiep) { 422 off = *cookiep++; 423 ncookies--; 424 } else 425 off += reclen; 426 continue; 427 } 428 if (reclen > len || resid < IBCS2_RECLEN(reclen)) { 429 /* entry too big for buffer, so just stop */ 430 outp++; 431 break; 432 } 433 /* 434 * Massage in place to make an iBCS2-shaped dirent (otherwise 435 * we have to worry about touching user memory outside of 436 * the copyout() call). 437 */ 438 idb.d_ino = (ibcs2_ino_t)BSD_DIRENT(inp)->d_fileno; 439 idb.d_off = (ibcs2_off_t)off; 440 idb.d_reclen = (u_short)IBCS2_RECLEN(reclen); 441 if ((error = copyout((caddr_t)&idb, outp, 10)) != 0 || 442 (error = copyout(BSD_DIRENT(inp)->d_name, outp + 10, 443 BSD_DIRENT(inp)->d_namlen + 1)) != 0) 444 goto out; 445 /* advance past this real entry */ 446 if (cookiep) { 447 off = *cookiep++; 448 ncookies--; 449 } else 450 off += reclen; 451 inp += reclen; 452 /* advance output past iBCS2-shaped entry */ 453 outp += IBCS2_RECLEN(reclen); 454 resid -= IBCS2_RECLEN(reclen); 455 } 456 /* if we squished out the whole block, try again */ 457 if (outp == uap->buf) 458 goto again; 459 fp->f_offset = off; /* update the vnode offset */ 460eof: 461 td->td_retval[0] = uap->nbytes - resid; 462out: 463 VOP_UNLOCK(vp, 0); 464 VFS_UNLOCK_GIANT(vfslocked); 465 fdrop(fp, td); 466 if (cookies) 467 free(cookies, M_TEMP); 468 free(buf, M_TEMP); 469 return (error); 470} 471 472int 473ibcs2_read(td, uap) 474 struct thread *td; 475 struct ibcs2_read_args *uap; 476{ 477 register struct vnode *vp; 478 register caddr_t inp, buf; /* BSD-format */ 479 register int len, reclen; /* BSD-format */ 480 register caddr_t outp; /* iBCS2-format */ 481 register int resid; /* iBCS2-format */ 482 struct file *fp; 483 struct uio auio; 484 struct iovec aiov; 485 struct ibcs2_direct { 486 ibcs2_ino_t ino; 487 char name[14]; 488 } idb; 489 off_t off; /* true file offset */ 490 int buflen, error, eofflag, size, vfslocked; 491 u_long *cookies = NULL, *cookiep; 492 int ncookies; 493 494 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) { 495 if (error == EINVAL) 496 return read(td, (struct read_args *)uap); 497 else 498 return error; 499 } 500 if ((fp->f_flag & FREAD) == 0) { 501 fdrop(fp, td); 502 return (EBADF); 503 } 504 vp = fp->f_vnode; 505 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 506 if (vp->v_type != VDIR) { 507 VFS_UNLOCK_GIANT(vfslocked); 508 fdrop(fp, td); 509 return read(td, (struct read_args *)uap); 510 } 511 512 off = fp->f_offset; 513 514 DPRINTF(("ibcs2_read: read directory\n")); 515 516 buflen = max(DIRBLKSIZ, uap->nbytes); 517 buflen = min(buflen, MAXBSIZE); 518 buf = malloc(buflen, M_TEMP, M_WAITOK); 519 vn_lock(vp, LK_SHARED | LK_RETRY); 520again: 521 aiov.iov_base = buf; 522 aiov.iov_len = buflen; 523 auio.uio_iov = &aiov; 524 auio.uio_iovcnt = 1; 525 auio.uio_rw = UIO_READ; 526 auio.uio_segflg = UIO_SYSSPACE; 527 auio.uio_td = td; 528 auio.uio_resid = buflen; 529 auio.uio_offset = off; 530 531 if (cookies) { 532 free(cookies, M_TEMP); 533 cookies = NULL; 534 } 535 536#ifdef MAC 537 error = mac_vnode_check_readdir(td->td_ucred, vp); 538 if (error) 539 goto out; 540#endif 541 542 /* 543 * First we read into the malloc'ed buffer, then 544 * we massage it into user space, one record at a time. 545 */ 546 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) { 547 DPRINTF(("VOP_READDIR failed: %d\n", error)); 548 goto out; 549 } 550 inp = buf; 551 outp = uap->buf; 552 resid = uap->nbytes; 553 if ((len = buflen - auio.uio_resid) <= 0) 554 goto eof; 555 556 cookiep = cookies; 557 558 if (cookies) { 559 /* 560 * When using cookies, the vfs has the option of reading from 561 * a different offset than that supplied (UFS truncates the 562 * offset to a block boundary to make sure that it never reads 563 * partway through a directory entry, even if the directory 564 * has been compacted). 565 */ 566 while (len > 0 && ncookies > 0 && *cookiep <= off) { 567 len -= BSD_DIRENT(inp)->d_reclen; 568 inp += BSD_DIRENT(inp)->d_reclen; 569 cookiep++; 570 ncookies--; 571 } 572 } 573 574 for (; len > 0 && resid > 0; len -= reclen) { 575 if (cookiep && ncookies == 0) 576 break; 577 reclen = BSD_DIRENT(inp)->d_reclen; 578 if (reclen & 3) { 579 printf("ibcs2_read: reclen=%d\n", reclen); 580 error = EFAULT; 581 goto out; 582 } 583 if (BSD_DIRENT(inp)->d_fileno == 0) { 584 inp += reclen; /* it is a hole; squish it out */ 585 if (cookiep) { 586 off = *cookiep++; 587 ncookies--; 588 } else 589 off += reclen; 590 continue; 591 } 592 if (reclen > len || resid < sizeof(struct ibcs2_direct)) { 593 /* entry too big for buffer, so just stop */ 594 outp++; 595 break; 596 } 597 /* 598 * Massage in place to make an iBCS2-shaped dirent (otherwise 599 * we have to worry about touching user memory outside of 600 * the copyout() call). 601 * 602 * TODO: if length(filename) > 14, then break filename into 603 * multiple entries and set inode = 0xffff except last 604 */ 605 idb.ino = (BSD_DIRENT(inp)->d_fileno > 0xfffe) ? 0xfffe : 606 BSD_DIRENT(inp)->d_fileno; 607 (void)copystr(BSD_DIRENT(inp)->d_name, idb.name, 14, &size); 608 bzero(idb.name + size, 14 - size); 609 if ((error = copyout(&idb, outp, sizeof(struct ibcs2_direct))) != 0) 610 goto out; 611 /* advance past this real entry */ 612 if (cookiep) { 613 off = *cookiep++; 614 ncookies--; 615 } else 616 off += reclen; 617 inp += reclen; 618 /* advance output past iBCS2-shaped entry */ 619 outp += sizeof(struct ibcs2_direct); 620 resid -= sizeof(struct ibcs2_direct); 621 } 622 /* if we squished out the whole block, try again */ 623 if (outp == uap->buf) 624 goto again; 625 fp->f_offset = off; /* update the vnode offset */ 626eof: 627 td->td_retval[0] = uap->nbytes - resid; 628out: 629 VOP_UNLOCK(vp, 0); 630 VFS_UNLOCK_GIANT(vfslocked); 631 fdrop(fp, td); 632 if (cookies) 633 free(cookies, M_TEMP); 634 free(buf, M_TEMP); 635 return (error); 636} 637 638int 639ibcs2_mknod(td, uap) 640 struct thread *td; 641 struct ibcs2_mknod_args *uap; 642{ 643 char *path; 644 int error; 645 646 CHECKALTCREAT(td, uap->path, &path); 647 if (S_ISFIFO(uap->mode)) 648 error = kern_mkfifo(td, path, UIO_SYSSPACE, uap->mode); 649 else 650 error = kern_mknod(td, path, UIO_SYSSPACE, uap->mode, uap->dev); 651 free(path, M_TEMP); 652 return (error); 653} 654 655int 656ibcs2_getgroups(td, uap) 657 struct thread *td; 658 struct ibcs2_getgroups_args *uap; 659{
| 51 52/* 53 * IBCS2 compatibility module. 54 * 55 * IBCS2 system calls that are implemented differently in BSD are 56 * handled here. 57 */ 58#include <sys/param.h> 59#include <sys/systm.h> 60#include <sys/dirent.h> 61#include <sys/fcntl.h> 62#include <sys/filedesc.h> 63#include <sys/imgact.h> 64#include <sys/kernel.h> 65#include <sys/lock.h> 66#include <sys/malloc.h> 67#include <sys/file.h> /* Must come after sys/malloc.h */ 68#include <sys/mutex.h> 69#include <sys/priv.h> 70#include <sys/reboot.h> 71#include <sys/resourcevar.h> 72#include <sys/stat.h> 73#include <sys/sysctl.h> 74#include <sys/syscallsubr.h> 75#include <sys/sysproto.h> 76#include <sys/time.h> 77#include <sys/times.h> 78#include <sys/vnode.h> 79#include <sys/wait.h> 80 81#include <machine/cpu.h> 82 83#include <i386/ibcs2/ibcs2_dirent.h> 84#include <i386/ibcs2/ibcs2_signal.h> 85#include <i386/ibcs2/ibcs2_proto.h> 86#include <i386/ibcs2/ibcs2_unistd.h> 87#include <i386/ibcs2/ibcs2_util.h> 88#include <i386/ibcs2/ibcs2_utime.h> 89#include <i386/ibcs2/ibcs2_xenix.h> 90 91#include <security/mac/mac_framework.h> 92 93int 94ibcs2_ulimit(td, uap) 95 struct thread *td; 96 struct ibcs2_ulimit_args *uap; 97{ 98 struct rlimit rl; 99 struct proc *p; 100 int error; 101#define IBCS2_GETFSIZE 1 102#define IBCS2_SETFSIZE 2 103#define IBCS2_GETPSIZE 3 104#define IBCS2_GETDTABLESIZE 4 105 106 p = td->td_proc; 107 switch (uap->cmd) { 108 case IBCS2_GETFSIZE: 109 PROC_LOCK(p); 110 td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); 111 PROC_UNLOCK(p); 112 if (td->td_retval[0] == -1) 113 td->td_retval[0] = 0x7fffffff; 114 return 0; 115 case IBCS2_SETFSIZE: 116 PROC_LOCK(p); 117 rl.rlim_max = lim_max(p, RLIMIT_FSIZE); 118 PROC_UNLOCK(p); 119 rl.rlim_cur = uap->newlimit; 120 error = kern_setrlimit(td, RLIMIT_FSIZE, &rl); 121 if (!error) { 122 PROC_LOCK(p); 123 td->td_retval[0] = lim_cur(p, RLIMIT_FSIZE); 124 PROC_UNLOCK(p); 125 } else { 126 DPRINTF(("failed ")); 127 } 128 return error; 129 case IBCS2_GETPSIZE: 130 PROC_LOCK(p); 131 td->td_retval[0] = lim_cur(p, RLIMIT_RSS); /* XXX */ 132 PROC_UNLOCK(p); 133 return 0; 134 case IBCS2_GETDTABLESIZE: 135 uap->cmd = IBCS2_SC_OPEN_MAX; 136 return ibcs2_sysconf(td, (struct ibcs2_sysconf_args *)uap); 137 default: 138 return ENOSYS; 139 } 140} 141 142#define IBCS2_WSTOPPED 0177 143#define IBCS2_STOPCODE(sig) ((sig) << 8 | IBCS2_WSTOPPED) 144int 145ibcs2_wait(td, uap) 146 struct thread *td; 147 struct ibcs2_wait_args *uap; 148{ 149 int error, options, status; 150 int *statusp; 151 pid_t pid; 152 struct trapframe *tf = td->td_frame; 153 154 if ((tf->tf_eflags & (PSL_Z|PSL_PF|PSL_N|PSL_V)) 155 == (PSL_Z|PSL_PF|PSL_N|PSL_V)) { 156 /* waitpid */ 157 pid = uap->a1; 158 statusp = (int *)uap->a2; 159 options = uap->a3; 160 } else { 161 /* wait */ 162 pid = WAIT_ANY; 163 statusp = (int *)uap->a1; 164 options = 0; 165 } 166 error = kern_wait(td, pid, &status, options, NULL); 167 if (error) 168 return error; 169 if (statusp) { 170 /* 171 * Convert status/signal result. 172 */ 173 if (WIFSTOPPED(status)) { 174 if (WSTOPSIG(status) <= 0 || 175 WSTOPSIG(status) > IBCS2_SIGTBLSZ) 176 return (EINVAL); 177 status = 178 IBCS2_STOPCODE(bsd_to_ibcs2_sig[_SIG_IDX(WSTOPSIG(status))]); 179 } else if (WIFSIGNALED(status)) { 180 if (WTERMSIG(status) <= 0 || 181 WTERMSIG(status) > IBCS2_SIGTBLSZ) 182 return (EINVAL); 183 status = bsd_to_ibcs2_sig[_SIG_IDX(WTERMSIG(status))]; 184 } 185 /* else exit status -- identical */ 186 187 /* record result/status */ 188 td->td_retval[1] = status; 189 return copyout(&status, statusp, sizeof(status)); 190 } 191 192 return 0; 193} 194 195int 196ibcs2_execv(td, uap) 197 struct thread *td; 198 struct ibcs2_execv_args *uap; 199{ 200 struct image_args eargs; 201 char *path; 202 int error; 203 204 CHECKALTEXIST(td, uap->path, &path); 205 206 error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, NULL); 207 free(path, M_TEMP); 208 if (error == 0) 209 error = kern_execve(td, &eargs, NULL); 210 return (error); 211} 212 213int 214ibcs2_execve(td, uap) 215 struct thread *td; 216 struct ibcs2_execve_args *uap; 217{ 218 struct image_args eargs; 219 char *path; 220 int error; 221 222 CHECKALTEXIST(td, uap->path, &path); 223 224 error = exec_copyin_args(&eargs, path, UIO_SYSSPACE, uap->argp, 225 uap->envp); 226 free(path, M_TEMP); 227 if (error == 0) 228 error = kern_execve(td, &eargs, NULL); 229 return (error); 230} 231 232int 233ibcs2_umount(td, uap) 234 struct thread *td; 235 struct ibcs2_umount_args *uap; 236{ 237 struct unmount_args um; 238 239 um.path = uap->name; 240 um.flags = 0; 241 return unmount(td, &um); 242} 243 244int 245ibcs2_mount(td, uap) 246 struct thread *td; 247 struct ibcs2_mount_args *uap; 248{ 249#ifdef notyet 250 int oflags = uap->flags, nflags, error; 251 char fsname[MFSNAMELEN]; 252 253 if (oflags & (IBCS2_MS_NOSUB | IBCS2_MS_SYS5)) 254 return (EINVAL); 255 if ((oflags & IBCS2_MS_NEWTYPE) == 0) 256 return (EINVAL); 257 nflags = 0; 258 if (oflags & IBCS2_MS_RDONLY) 259 nflags |= MNT_RDONLY; 260 if (oflags & IBCS2_MS_NOSUID) 261 nflags |= MNT_NOSUID; 262 if (oflags & IBCS2_MS_REMOUNT) 263 nflags |= MNT_UPDATE; 264 uap->flags = nflags; 265 266 if (error = copyinstr((caddr_t)uap->type, fsname, sizeof fsname, 267 (u_int *)0)) 268 return (error); 269 270 if (strcmp(fsname, "4.2") == 0) { 271 uap->type = (caddr_t)STACK_ALLOC(); 272 if (error = copyout("ufs", uap->type, sizeof("ufs"))) 273 return (error); 274 } else if (strcmp(fsname, "nfs") == 0) { 275 struct ibcs2_nfs_args sna; 276 struct sockaddr_in sain; 277 struct nfs_args na; 278 struct sockaddr sa; 279 280 if (error = copyin(uap->data, &sna, sizeof sna)) 281 return (error); 282 if (error = copyin(sna.addr, &sain, sizeof sain)) 283 return (error); 284 bcopy(&sain, &sa, sizeof sa); 285 sa.sa_len = sizeof(sain); 286 uap->data = (caddr_t)STACK_ALLOC(); 287 na.addr = (struct sockaddr *)((int)uap->data + sizeof na); 288 na.sotype = SOCK_DGRAM; 289 na.proto = IPPROTO_UDP; 290 na.fh = (nfsv2fh_t *)sna.fh; 291 na.flags = sna.flags; 292 na.wsize = sna.wsize; 293 na.rsize = sna.rsize; 294 na.timeo = sna.timeo; 295 na.retrans = sna.retrans; 296 na.hostname = sna.hostname; 297 298 if (error = copyout(&sa, na.addr, sizeof sa)) 299 return (error); 300 if (error = copyout(&na, uap->data, sizeof na)) 301 return (error); 302 } 303 return (mount(td, uap)); 304#else 305 return EINVAL; 306#endif 307} 308 309/* 310 * Read iBCS2-style directory entries. We suck them into kernel space so 311 * that they can be massaged before being copied out to user code. Like 312 * SunOS, we squish out `empty' entries. 313 * 314 * This is quite ugly, but what do you expect from compatibility code? 315 */ 316 317int 318ibcs2_getdents(td, uap) 319 struct thread *td; 320 register struct ibcs2_getdents_args *uap; 321{ 322 register struct vnode *vp; 323 register caddr_t inp, buf; /* BSD-format */ 324 register int len, reclen; /* BSD-format */ 325 register caddr_t outp; /* iBCS2-format */ 326 register int resid; /* iBCS2-format */ 327 struct file *fp; 328 struct uio auio; 329 struct iovec aiov; 330 struct ibcs2_dirent idb; 331 off_t off; /* true file offset */ 332 int buflen, error, eofflag, vfslocked; 333 u_long *cookies = NULL, *cookiep; 334 int ncookies; 335#define BSD_DIRENT(cp) ((struct dirent *)(cp)) 336#define IBCS2_RECLEN(reclen) (reclen + sizeof(u_short)) 337 338 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) 339 return (error); 340 if ((fp->f_flag & FREAD) == 0) { 341 fdrop(fp, td); 342 return (EBADF); 343 } 344 vp = fp->f_vnode; 345 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 346 if (vp->v_type != VDIR) { /* XXX vnode readdir op should do this */ 347 VFS_UNLOCK_GIANT(vfslocked); 348 fdrop(fp, td); 349 return (EINVAL); 350 } 351 352 off = fp->f_offset; 353#define DIRBLKSIZ 512 /* XXX we used to use ufs's DIRBLKSIZ */ 354 buflen = max(DIRBLKSIZ, uap->nbytes); 355 buflen = min(buflen, MAXBSIZE); 356 buf = malloc(buflen, M_TEMP, M_WAITOK); 357 vn_lock(vp, LK_SHARED | LK_RETRY); 358again: 359 aiov.iov_base = buf; 360 aiov.iov_len = buflen; 361 auio.uio_iov = &aiov; 362 auio.uio_iovcnt = 1; 363 auio.uio_rw = UIO_READ; 364 auio.uio_segflg = UIO_SYSSPACE; 365 auio.uio_td = td; 366 auio.uio_resid = buflen; 367 auio.uio_offset = off; 368 369 if (cookies) { 370 free(cookies, M_TEMP); 371 cookies = NULL; 372 } 373 374#ifdef MAC 375 error = mac_vnode_check_readdir(td->td_ucred, vp); 376 if (error) 377 goto out; 378#endif 379 380 /* 381 * First we read into the malloc'ed buffer, then 382 * we massage it into user space, one record at a time. 383 */ 384 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) 385 goto out; 386 inp = buf; 387 outp = uap->buf; 388 resid = uap->nbytes; 389 if ((len = buflen - auio.uio_resid) <= 0) 390 goto eof; 391 392 cookiep = cookies; 393 394 if (cookies) { 395 /* 396 * When using cookies, the vfs has the option of reading from 397 * a different offset than that supplied (UFS truncates the 398 * offset to a block boundary to make sure that it never reads 399 * partway through a directory entry, even if the directory 400 * has been compacted). 401 */ 402 while (len > 0 && ncookies > 0 && *cookiep <= off) { 403 len -= BSD_DIRENT(inp)->d_reclen; 404 inp += BSD_DIRENT(inp)->d_reclen; 405 cookiep++; 406 ncookies--; 407 } 408 } 409 410 for (; len > 0; len -= reclen) { 411 if (cookiep && ncookies == 0) 412 break; 413 reclen = BSD_DIRENT(inp)->d_reclen; 414 if (reclen & 3) { 415 printf("ibcs2_getdents: reclen=%d\n", reclen); 416 error = EFAULT; 417 goto out; 418 } 419 if (BSD_DIRENT(inp)->d_fileno == 0) { 420 inp += reclen; /* it is a hole; squish it out */ 421 if (cookiep) { 422 off = *cookiep++; 423 ncookies--; 424 } else 425 off += reclen; 426 continue; 427 } 428 if (reclen > len || resid < IBCS2_RECLEN(reclen)) { 429 /* entry too big for buffer, so just stop */ 430 outp++; 431 break; 432 } 433 /* 434 * Massage in place to make an iBCS2-shaped dirent (otherwise 435 * we have to worry about touching user memory outside of 436 * the copyout() call). 437 */ 438 idb.d_ino = (ibcs2_ino_t)BSD_DIRENT(inp)->d_fileno; 439 idb.d_off = (ibcs2_off_t)off; 440 idb.d_reclen = (u_short)IBCS2_RECLEN(reclen); 441 if ((error = copyout((caddr_t)&idb, outp, 10)) != 0 || 442 (error = copyout(BSD_DIRENT(inp)->d_name, outp + 10, 443 BSD_DIRENT(inp)->d_namlen + 1)) != 0) 444 goto out; 445 /* advance past this real entry */ 446 if (cookiep) { 447 off = *cookiep++; 448 ncookies--; 449 } else 450 off += reclen; 451 inp += reclen; 452 /* advance output past iBCS2-shaped entry */ 453 outp += IBCS2_RECLEN(reclen); 454 resid -= IBCS2_RECLEN(reclen); 455 } 456 /* if we squished out the whole block, try again */ 457 if (outp == uap->buf) 458 goto again; 459 fp->f_offset = off; /* update the vnode offset */ 460eof: 461 td->td_retval[0] = uap->nbytes - resid; 462out: 463 VOP_UNLOCK(vp, 0); 464 VFS_UNLOCK_GIANT(vfslocked); 465 fdrop(fp, td); 466 if (cookies) 467 free(cookies, M_TEMP); 468 free(buf, M_TEMP); 469 return (error); 470} 471 472int 473ibcs2_read(td, uap) 474 struct thread *td; 475 struct ibcs2_read_args *uap; 476{ 477 register struct vnode *vp; 478 register caddr_t inp, buf; /* BSD-format */ 479 register int len, reclen; /* BSD-format */ 480 register caddr_t outp; /* iBCS2-format */ 481 register int resid; /* iBCS2-format */ 482 struct file *fp; 483 struct uio auio; 484 struct iovec aiov; 485 struct ibcs2_direct { 486 ibcs2_ino_t ino; 487 char name[14]; 488 } idb; 489 off_t off; /* true file offset */ 490 int buflen, error, eofflag, size, vfslocked; 491 u_long *cookies = NULL, *cookiep; 492 int ncookies; 493 494 if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0) { 495 if (error == EINVAL) 496 return read(td, (struct read_args *)uap); 497 else 498 return error; 499 } 500 if ((fp->f_flag & FREAD) == 0) { 501 fdrop(fp, td); 502 return (EBADF); 503 } 504 vp = fp->f_vnode; 505 vfslocked = VFS_LOCK_GIANT(vp->v_mount); 506 if (vp->v_type != VDIR) { 507 VFS_UNLOCK_GIANT(vfslocked); 508 fdrop(fp, td); 509 return read(td, (struct read_args *)uap); 510 } 511 512 off = fp->f_offset; 513 514 DPRINTF(("ibcs2_read: read directory\n")); 515 516 buflen = max(DIRBLKSIZ, uap->nbytes); 517 buflen = min(buflen, MAXBSIZE); 518 buf = malloc(buflen, M_TEMP, M_WAITOK); 519 vn_lock(vp, LK_SHARED | LK_RETRY); 520again: 521 aiov.iov_base = buf; 522 aiov.iov_len = buflen; 523 auio.uio_iov = &aiov; 524 auio.uio_iovcnt = 1; 525 auio.uio_rw = UIO_READ; 526 auio.uio_segflg = UIO_SYSSPACE; 527 auio.uio_td = td; 528 auio.uio_resid = buflen; 529 auio.uio_offset = off; 530 531 if (cookies) { 532 free(cookies, M_TEMP); 533 cookies = NULL; 534 } 535 536#ifdef MAC 537 error = mac_vnode_check_readdir(td->td_ucred, vp); 538 if (error) 539 goto out; 540#endif 541 542 /* 543 * First we read into the malloc'ed buffer, then 544 * we massage it into user space, one record at a time. 545 */ 546 if ((error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &ncookies, &cookies)) != 0) { 547 DPRINTF(("VOP_READDIR failed: %d\n", error)); 548 goto out; 549 } 550 inp = buf; 551 outp = uap->buf; 552 resid = uap->nbytes; 553 if ((len = buflen - auio.uio_resid) <= 0) 554 goto eof; 555 556 cookiep = cookies; 557 558 if (cookies) { 559 /* 560 * When using cookies, the vfs has the option of reading from 561 * a different offset than that supplied (UFS truncates the 562 * offset to a block boundary to make sure that it never reads 563 * partway through a directory entry, even if the directory 564 * has been compacted). 565 */ 566 while (len > 0 && ncookies > 0 && *cookiep <= off) { 567 len -= BSD_DIRENT(inp)->d_reclen; 568 inp += BSD_DIRENT(inp)->d_reclen; 569 cookiep++; 570 ncookies--; 571 } 572 } 573 574 for (; len > 0 && resid > 0; len -= reclen) { 575 if (cookiep && ncookies == 0) 576 break; 577 reclen = BSD_DIRENT(inp)->d_reclen; 578 if (reclen & 3) { 579 printf("ibcs2_read: reclen=%d\n", reclen); 580 error = EFAULT; 581 goto out; 582 } 583 if (BSD_DIRENT(inp)->d_fileno == 0) { 584 inp += reclen; /* it is a hole; squish it out */ 585 if (cookiep) { 586 off = *cookiep++; 587 ncookies--; 588 } else 589 off += reclen; 590 continue; 591 } 592 if (reclen > len || resid < sizeof(struct ibcs2_direct)) { 593 /* entry too big for buffer, so just stop */ 594 outp++; 595 break; 596 } 597 /* 598 * Massage in place to make an iBCS2-shaped dirent (otherwise 599 * we have to worry about touching user memory outside of 600 * the copyout() call). 601 * 602 * TODO: if length(filename) > 14, then break filename into 603 * multiple entries and set inode = 0xffff except last 604 */ 605 idb.ino = (BSD_DIRENT(inp)->d_fileno > 0xfffe) ? 0xfffe : 606 BSD_DIRENT(inp)->d_fileno; 607 (void)copystr(BSD_DIRENT(inp)->d_name, idb.name, 14, &size); 608 bzero(idb.name + size, 14 - size); 609 if ((error = copyout(&idb, outp, sizeof(struct ibcs2_direct))) != 0) 610 goto out; 611 /* advance past this real entry */ 612 if (cookiep) { 613 off = *cookiep++; 614 ncookies--; 615 } else 616 off += reclen; 617 inp += reclen; 618 /* advance output past iBCS2-shaped entry */ 619 outp += sizeof(struct ibcs2_direct); 620 resid -= sizeof(struct ibcs2_direct); 621 } 622 /* if we squished out the whole block, try again */ 623 if (outp == uap->buf) 624 goto again; 625 fp->f_offset = off; /* update the vnode offset */ 626eof: 627 td->td_retval[0] = uap->nbytes - resid; 628out: 629 VOP_UNLOCK(vp, 0); 630 VFS_UNLOCK_GIANT(vfslocked); 631 fdrop(fp, td); 632 if (cookies) 633 free(cookies, M_TEMP); 634 free(buf, M_TEMP); 635 return (error); 636} 637 638int 639ibcs2_mknod(td, uap) 640 struct thread *td; 641 struct ibcs2_mknod_args *uap; 642{ 643 char *path; 644 int error; 645 646 CHECKALTCREAT(td, uap->path, &path); 647 if (S_ISFIFO(uap->mode)) 648 error = kern_mkfifo(td, path, UIO_SYSSPACE, uap->mode); 649 else 650 error = kern_mknod(td, path, UIO_SYSSPACE, uap->mode, uap->dev); 651 free(path, M_TEMP); 652 return (error); 653} 654 655int 656ibcs2_getgroups(td, uap) 657 struct thread *td; 658 struct ibcs2_getgroups_args *uap; 659{
|
660 ibcs2_gid_t iset[NGROUPS_MAX]; 661 gid_t gp[NGROUPS_MAX];
| 660 ibcs2_gid_t *iset; 661 gid_t *gp;
|
662 u_int i, ngrp; 663 int error; 664 665 if (uap->gidsetsize < 0) 666 return (EINVAL); 667 ngrp = MIN(uap->gidsetsize, NGROUPS_MAX);
| 662 u_int i, ngrp; 663 int error; 664 665 if (uap->gidsetsize < 0) 666 return (EINVAL); 667 ngrp = MIN(uap->gidsetsize, NGROUPS_MAX);
|
| 668 gp = malloc(ngrp * sizeof(*gp), M_TEMP, M_WAITOK);
|
668 error = kern_getgroups(td, &ngrp, gp); 669 if (error)
| 669 error = kern_getgroups(td, &ngrp, gp); 670 if (error)
|
670 return (error);
| 671 goto out;
|
671 if (uap->gidsetsize > 0) {
| 672 if (uap->gidsetsize > 0) {
|
| 673 iset = malloc(ngrp * sizeof(*iset), M_TEMP, M_WAITOK);
|
672 for (i = 0; i < ngrp; i++) 673 iset[i] = (ibcs2_gid_t)gp[i]; 674 error = copyout(iset, uap->gidset, ngrp * sizeof(ibcs2_gid_t));
| 674 for (i = 0; i < ngrp; i++) 675 iset[i] = (ibcs2_gid_t)gp[i]; 676 error = copyout(iset, uap->gidset, ngrp * sizeof(ibcs2_gid_t));
|
| 677 free(iset, M_TEMP);
|
675 } 676 if (error == 0) 677 td->td_retval[0] = ngrp;
| 678 } 679 if (error == 0) 680 td->td_retval[0] = ngrp;
|
| 681out: 682 free(gp, M_TEMP);
|
678 return (error); 679} 680 681int 682ibcs2_setgroups(td, uap) 683 struct thread *td; 684 struct ibcs2_setgroups_args *uap; 685{
| 683 return (error); 684} 685 686int 687ibcs2_setgroups(td, uap) 688 struct thread *td; 689 struct ibcs2_setgroups_args *uap; 690{
|
686 ibcs2_gid_t iset[NGROUPS_MAX]; 687 gid_t gp[NGROUPS_MAX];
| 691 ibcs2_gid_t *iset; 692 gid_t *gp;
|
688 int error, i; 689 690 if (uap->gidsetsize < 0 || uap->gidsetsize > NGROUPS_MAX) 691 return (EINVAL);
| 693 int error, i; 694 695 if (uap->gidsetsize < 0 || uap->gidsetsize > NGROUPS_MAX) 696 return (EINVAL);
|
692 if (uap->gidsetsize && uap->gidset) {
| 697 if (uap->gidsetsize && uap->gidset == NULL) 698 return (EINVAL); 699 gp = malloc(uap->gidsetsize * sizeof(*gp), M_TEMP, M_WAITOK); 700 if (uap->gidsetsize) { 701 iset = malloc(uap->gidsetsize * sizeof(*iset), M_TEMP, M_WAITOK);
|
693 error = copyin(uap->gidset, iset, sizeof(ibcs2_gid_t) * 694 uap->gidsetsize);
| 702 error = copyin(uap->gidset, iset, sizeof(ibcs2_gid_t) * 703 uap->gidsetsize);
|
695 if (error) 696 return (error);
| 704 if (error) { 705 free(iset, M_TEMP); 706 goto out; 707 }
|
697 for (i = 0; i < uap->gidsetsize; i++) 698 gp[i] = (gid_t)iset[i]; 699 }
| 708 for (i = 0; i < uap->gidsetsize; i++) 709 gp[i] = (gid_t)iset[i]; 710 }
|
700 return (kern_setgroups(td, uap->gidsetsize, gp));
| 711 712 error = kern_setgroups(td, uap->gidsetsize, gp); 713out: 714 free(gp, M_TEMP); 715 return (error);
|
701} 702 703int 704ibcs2_setuid(td, uap) 705 struct thread *td; 706 struct ibcs2_setuid_args *uap; 707{ 708 struct setuid_args sa; 709 710 sa.uid = (uid_t)uap->uid; 711 return setuid(td, &sa); 712} 713 714int 715ibcs2_setgid(td, uap) 716 struct thread *td; 717 struct ibcs2_setgid_args *uap; 718{ 719 struct setgid_args sa; 720 721 sa.gid = (gid_t)uap->gid; 722 return setgid(td, &sa); 723} 724 725int 726ibcs2_time(td, uap) 727 struct thread *td; 728 struct ibcs2_time_args *uap; 729{ 730 struct timeval tv; 731 732 microtime(&tv); 733 td->td_retval[0] = tv.tv_sec; 734 if (uap->tp) 735 return copyout((caddr_t)&tv.tv_sec, (caddr_t)uap->tp, 736 sizeof(ibcs2_time_t)); 737 else 738 return 0; 739} 740 741int 742ibcs2_pathconf(td, uap) 743 struct thread *td; 744 struct ibcs2_pathconf_args *uap; 745{ 746 char *path; 747 int error; 748 749 CHECKALTEXIST(td, uap->path, &path); 750 uap->name++; /* iBCS2 _PC_* defines are offset by one */ 751 error = kern_pathconf(td, path, UIO_SYSSPACE, uap->name); 752 free(path, M_TEMP); 753 return (error); 754} 755 756int 757ibcs2_fpathconf(td, uap) 758 struct thread *td; 759 struct ibcs2_fpathconf_args *uap; 760{ 761 uap->name++; /* iBCS2 _PC_* defines are offset by one */ 762 return fpathconf(td, (struct fpathconf_args *)uap); 763} 764 765int 766ibcs2_sysconf(td, uap) 767 struct thread *td; 768 struct ibcs2_sysconf_args *uap; 769{ 770 int mib[2], value, len, error; 771 struct proc *p; 772 773 p = td->td_proc; 774 switch(uap->name) { 775 case IBCS2_SC_ARG_MAX: 776 mib[1] = KERN_ARGMAX; 777 break; 778 779 case IBCS2_SC_CHILD_MAX: 780 PROC_LOCK(p); 781 td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NPROC); 782 PROC_UNLOCK(p); 783 return 0; 784 785 case IBCS2_SC_CLK_TCK: 786 td->td_retval[0] = hz; 787 return 0; 788 789 case IBCS2_SC_NGROUPS_MAX: 790 mib[1] = KERN_NGROUPS; 791 break; 792 793 case IBCS2_SC_OPEN_MAX: 794 PROC_LOCK(p); 795 td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NOFILE); 796 PROC_UNLOCK(p); 797 return 0; 798 799 case IBCS2_SC_JOB_CONTROL: 800 mib[1] = KERN_JOB_CONTROL; 801 break; 802 803 case IBCS2_SC_SAVED_IDS: 804 mib[1] = KERN_SAVED_IDS; 805 break; 806 807 case IBCS2_SC_VERSION: 808 mib[1] = KERN_POSIX1; 809 break; 810 811 case IBCS2_SC_PASS_MAX: 812 td->td_retval[0] = 128; /* XXX - should we create PASS_MAX ? */ 813 return 0; 814 815 case IBCS2_SC_XOPEN_VERSION: 816 td->td_retval[0] = 2; /* XXX: What should that be? */ 817 return 0; 818 819 default: 820 return EINVAL; 821 } 822 823 mib[0] = CTL_KERN; 824 len = sizeof(value); 825 error = kernel_sysctl(td, mib, 2, &value, &len, NULL, 0, NULL, 0); 826 if (error) 827 return error; 828 td->td_retval[0] = value; 829 return 0; 830} 831 832int 833ibcs2_alarm(td, uap) 834 struct thread *td; 835 struct ibcs2_alarm_args *uap; 836{ 837 struct itimerval itv, oitv; 838 int error; 839 840 timevalclear(&itv.it_interval); 841 itv.it_value.tv_sec = uap->sec; 842 itv.it_value.tv_usec = 0; 843 error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv); 844 if (error) 845 return (error); 846 if (oitv.it_value.tv_usec != 0) 847 oitv.it_value.tv_sec++; 848 td->td_retval[0] = oitv.it_value.tv_sec; 849 return (0); 850} 851 852int 853ibcs2_times(td, uap) 854 struct thread *td; 855 struct ibcs2_times_args *uap; 856{ 857 struct rusage ru; 858 struct timeval t; 859 struct tms tms; 860 int error; 861 862#define CONVTCK(r) (r.tv_sec * hz + r.tv_usec / (1000000 / hz)) 863 864 error = kern_getrusage(td, RUSAGE_SELF, &ru); 865 if (error) 866 return (error); 867 tms.tms_utime = CONVTCK(ru.ru_utime); 868 tms.tms_stime = CONVTCK(ru.ru_stime); 869 870 error = kern_getrusage(td, RUSAGE_CHILDREN, &ru); 871 if (error) 872 return (error); 873 tms.tms_cutime = CONVTCK(ru.ru_utime); 874 tms.tms_cstime = CONVTCK(ru.ru_stime); 875 876 microtime(&t); 877 td->td_retval[0] = CONVTCK(t); 878 879 return (copyout(&tms, uap->tp, sizeof(struct tms))); 880} 881 882int 883ibcs2_stime(td, uap) 884 struct thread *td; 885 struct ibcs2_stime_args *uap; 886{ 887 struct timeval tv; 888 long secs; 889 int error; 890 891 error = copyin(uap->timep, &secs, sizeof(long)); 892 if (error) 893 return (error); 894 tv.tv_sec = secs; 895 tv.tv_usec = 0; 896 error = kern_settimeofday(td, &tv, NULL); 897 if (error) 898 error = EPERM; 899 return (error); 900} 901 902int 903ibcs2_utime(td, uap) 904 struct thread *td; 905 struct ibcs2_utime_args *uap; 906{ 907 struct ibcs2_utimbuf ubuf; 908 struct timeval tbuf[2], *tp; 909 char *path; 910 int error; 911 912 if (uap->buf) { 913 error = copyin(uap->buf, &ubuf, sizeof(ubuf)); 914 if (error) 915 return (error); 916 tbuf[0].tv_sec = ubuf.actime; 917 tbuf[0].tv_usec = 0; 918 tbuf[1].tv_sec = ubuf.modtime; 919 tbuf[1].tv_usec = 0; 920 tp = tbuf; 921 } else 922 tp = NULL; 923 924 CHECKALTEXIST(td, uap->path, &path); 925 error = kern_utimes(td, path, UIO_SYSSPACE, tp, UIO_SYSSPACE); 926 free(path, M_TEMP); 927 return (error); 928} 929 930int 931ibcs2_nice(td, uap) 932 struct thread *td; 933 struct ibcs2_nice_args *uap; 934{ 935 int error; 936 struct setpriority_args sa; 937 938 sa.which = PRIO_PROCESS; 939 sa.who = 0; 940 sa.prio = td->td_proc->p_nice + uap->incr; 941 if ((error = setpriority(td, &sa)) != 0) 942 return EPERM; 943 td->td_retval[0] = td->td_proc->p_nice; 944 return 0; 945} 946 947/* 948 * iBCS2 getpgrp, setpgrp, setsid, and setpgid 949 */ 950 951int 952ibcs2_pgrpsys(td, uap) 953 struct thread *td; 954 struct ibcs2_pgrpsys_args *uap; 955{ 956 struct proc *p = td->td_proc; 957 switch (uap->type) { 958 case 0: /* getpgrp */ 959 PROC_LOCK(p); 960 td->td_retval[0] = p->p_pgrp->pg_id; 961 PROC_UNLOCK(p); 962 return 0; 963 964 case 1: /* setpgrp */ 965 { 966 struct setpgid_args sa; 967 968 sa.pid = 0; 969 sa.pgid = 0; 970 setpgid(td, &sa); 971 PROC_LOCK(p); 972 td->td_retval[0] = p->p_pgrp->pg_id; 973 PROC_UNLOCK(p); 974 return 0; 975 } 976 977 case 2: /* setpgid */ 978 { 979 struct setpgid_args sa; 980 981 sa.pid = uap->pid; 982 sa.pgid = uap->pgid; 983 return setpgid(td, &sa); 984 } 985 986 case 3: /* setsid */ 987 return setsid(td, NULL); 988 989 default: 990 return EINVAL; 991 } 992} 993 994/* 995 * XXX - need to check for nested calls 996 */ 997 998int 999ibcs2_plock(td, uap) 1000 struct thread *td; 1001 struct ibcs2_plock_args *uap; 1002{ 1003 int error; 1004#define IBCS2_UNLOCK 0 1005#define IBCS2_PROCLOCK 1 1006#define IBCS2_TEXTLOCK 2 1007#define IBCS2_DATALOCK 4 1008 1009 1010 switch(uap->cmd) { 1011 case IBCS2_UNLOCK: 1012 error = priv_check(td, PRIV_VM_MUNLOCK); 1013 if (error) 1014 return (error); 1015 /* XXX - TODO */ 1016 return (0); 1017 1018 case IBCS2_PROCLOCK: 1019 case IBCS2_TEXTLOCK: 1020 case IBCS2_DATALOCK: 1021 error = priv_check(td, PRIV_VM_MLOCK); 1022 if (error) 1023 return (error); 1024 /* XXX - TODO */ 1025 return 0; 1026 } 1027 return EINVAL; 1028} 1029 1030int 1031ibcs2_uadmin(td, uap) 1032 struct thread *td; 1033 struct ibcs2_uadmin_args *uap; 1034{ 1035#define SCO_A_REBOOT 1 1036#define SCO_A_SHUTDOWN 2 1037#define SCO_A_REMOUNT 4 1038#define SCO_A_CLOCK 8 1039#define SCO_A_SETCONFIG 128 1040#define SCO_A_GETDEV 130 1041 1042#define SCO_AD_HALT 0 1043#define SCO_AD_BOOT 1 1044#define SCO_AD_IBOOT 2 1045#define SCO_AD_PWRDOWN 3 1046#define SCO_AD_PWRNAP 4 1047 1048#define SCO_AD_PANICBOOT 1 1049 1050#define SCO_AD_GETBMAJ 0 1051#define SCO_AD_GETCMAJ 1 1052 1053 switch(uap->cmd) { 1054 case SCO_A_REBOOT: 1055 case SCO_A_SHUTDOWN: 1056 switch(uap->func) { 1057 struct reboot_args r; 1058 case SCO_AD_HALT: 1059 case SCO_AD_PWRDOWN: 1060 case SCO_AD_PWRNAP: 1061 r.opt = RB_HALT; 1062 return (reboot(td, &r)); 1063 case SCO_AD_BOOT: 1064 case SCO_AD_IBOOT: 1065 r.opt = RB_AUTOBOOT; 1066 return (reboot(td, &r)); 1067 } 1068 return EINVAL; 1069 case SCO_A_REMOUNT: 1070 case SCO_A_CLOCK: 1071 case SCO_A_SETCONFIG: 1072 return 0; 1073 case SCO_A_GETDEV: 1074 return EINVAL; /* XXX - TODO */ 1075 } 1076 return EINVAL; 1077} 1078 1079int 1080ibcs2_sysfs(td, uap) 1081 struct thread *td; 1082 struct ibcs2_sysfs_args *uap; 1083{ 1084#define IBCS2_GETFSIND 1 1085#define IBCS2_GETFSTYP 2 1086#define IBCS2_GETNFSTYP 3 1087 1088 switch(uap->cmd) { 1089 case IBCS2_GETFSIND: 1090 case IBCS2_GETFSTYP: 1091 case IBCS2_GETNFSTYP: 1092 break; 1093 } 1094 return EINVAL; /* XXX - TODO */ 1095} 1096 1097int 1098ibcs2_unlink(td, uap) 1099 struct thread *td; 1100 struct ibcs2_unlink_args *uap; 1101{ 1102 char *path; 1103 int error; 1104 1105 CHECKALTEXIST(td, uap->path, &path); 1106 error = kern_unlink(td, path, UIO_SYSSPACE); 1107 free(path, M_TEMP); 1108 return (error); 1109} 1110 1111int 1112ibcs2_chdir(td, uap) 1113 struct thread *td; 1114 struct ibcs2_chdir_args *uap; 1115{ 1116 char *path; 1117 int error; 1118 1119 CHECKALTEXIST(td, uap->path, &path); 1120 error = kern_chdir(td, path, UIO_SYSSPACE); 1121 free(path, M_TEMP); 1122 return (error); 1123} 1124 1125int 1126ibcs2_chmod(td, uap) 1127 struct thread *td; 1128 struct ibcs2_chmod_args *uap; 1129{ 1130 char *path; 1131 int error; 1132 1133 CHECKALTEXIST(td, uap->path, &path); 1134 error = kern_chmod(td, path, UIO_SYSSPACE, uap->mode); 1135 free(path, M_TEMP); 1136 return (error); 1137} 1138 1139int 1140ibcs2_chown(td, uap) 1141 struct thread *td; 1142 struct ibcs2_chown_args *uap; 1143{ 1144 char *path; 1145 int error; 1146 1147 CHECKALTEXIST(td, uap->path, &path); 1148 error = kern_chown(td, path, UIO_SYSSPACE, uap->uid, uap->gid); 1149 free(path, M_TEMP); 1150 return (error); 1151} 1152 1153int 1154ibcs2_rmdir(td, uap) 1155 struct thread *td; 1156 struct ibcs2_rmdir_args *uap; 1157{ 1158 char *path; 1159 int error; 1160 1161 CHECKALTEXIST(td, uap->path, &path); 1162 error = kern_rmdir(td, path, UIO_SYSSPACE); 1163 free(path, M_TEMP); 1164 return (error); 1165} 1166 1167int 1168ibcs2_mkdir(td, uap) 1169 struct thread *td; 1170 struct ibcs2_mkdir_args *uap; 1171{ 1172 char *path; 1173 int error; 1174 1175 CHECKALTEXIST(td, uap->path, &path); 1176 error = kern_mkdir(td, path, UIO_SYSSPACE, uap->mode); 1177 free(path, M_TEMP); 1178 return (error); 1179} 1180 1181int 1182ibcs2_symlink(td, uap) 1183 struct thread *td; 1184 struct ibcs2_symlink_args *uap; 1185{ 1186 char *path, *link; 1187 int error; 1188 1189 CHECKALTEXIST(td, uap->path, &path); 1190 1191 /* 1192 * Have to expand CHECKALTCREAT() so that 'path' can be freed on 1193 * errors. 1194 */ 1195 error = ibcs2_emul_find(td, uap->link, UIO_USERSPACE, &link, 1); 1196 if (link == NULL) { 1197 free(path, M_TEMP); 1198 return (error); 1199 } 1200 error = kern_symlink(td, path, link, UIO_SYSSPACE); 1201 free(path, M_TEMP); 1202 free(link, M_TEMP); 1203 return (error); 1204} 1205 1206int 1207ibcs2_rename(td, uap) 1208 struct thread *td; 1209 struct ibcs2_rename_args *uap; 1210{ 1211 char *from, *to; 1212 int error; 1213 1214 CHECKALTEXIST(td, uap->from, &from); 1215 1216 /* 1217 * Have to expand CHECKALTCREAT() so that 'from' can be freed on 1218 * errors. 1219 */ 1220 error = ibcs2_emul_find(td, uap->to, UIO_USERSPACE, &to, 1); 1221 if (to == NULL) { 1222 free(from, M_TEMP); 1223 return (error); 1224 } 1225 error = kern_rename(td, from, to, UIO_SYSSPACE); 1226 free(from, M_TEMP); 1227 free(to, M_TEMP); 1228 return (error); 1229} 1230 1231int 1232ibcs2_readlink(td, uap) 1233 struct thread *td; 1234 struct ibcs2_readlink_args *uap; 1235{ 1236 char *path; 1237 int error; 1238 1239 CHECKALTEXIST(td, uap->path, &path); 1240 error = kern_readlink(td, path, UIO_SYSSPACE, uap->buf, UIO_USERSPACE, 1241 uap->count); 1242 free(path, M_TEMP); 1243 return (error); 1244}
| 716} 717 718int 719ibcs2_setuid(td, uap) 720 struct thread *td; 721 struct ibcs2_setuid_args *uap; 722{ 723 struct setuid_args sa; 724 725 sa.uid = (uid_t)uap->uid; 726 return setuid(td, &sa); 727} 728 729int 730ibcs2_setgid(td, uap) 731 struct thread *td; 732 struct ibcs2_setgid_args *uap; 733{ 734 struct setgid_args sa; 735 736 sa.gid = (gid_t)uap->gid; 737 return setgid(td, &sa); 738} 739 740int 741ibcs2_time(td, uap) 742 struct thread *td; 743 struct ibcs2_time_args *uap; 744{ 745 struct timeval tv; 746 747 microtime(&tv); 748 td->td_retval[0] = tv.tv_sec; 749 if (uap->tp) 750 return copyout((caddr_t)&tv.tv_sec, (caddr_t)uap->tp, 751 sizeof(ibcs2_time_t)); 752 else 753 return 0; 754} 755 756int 757ibcs2_pathconf(td, uap) 758 struct thread *td; 759 struct ibcs2_pathconf_args *uap; 760{ 761 char *path; 762 int error; 763 764 CHECKALTEXIST(td, uap->path, &path); 765 uap->name++; /* iBCS2 _PC_* defines are offset by one */ 766 error = kern_pathconf(td, path, UIO_SYSSPACE, uap->name); 767 free(path, M_TEMP); 768 return (error); 769} 770 771int 772ibcs2_fpathconf(td, uap) 773 struct thread *td; 774 struct ibcs2_fpathconf_args *uap; 775{ 776 uap->name++; /* iBCS2 _PC_* defines are offset by one */ 777 return fpathconf(td, (struct fpathconf_args *)uap); 778} 779 780int 781ibcs2_sysconf(td, uap) 782 struct thread *td; 783 struct ibcs2_sysconf_args *uap; 784{ 785 int mib[2], value, len, error; 786 struct proc *p; 787 788 p = td->td_proc; 789 switch(uap->name) { 790 case IBCS2_SC_ARG_MAX: 791 mib[1] = KERN_ARGMAX; 792 break; 793 794 case IBCS2_SC_CHILD_MAX: 795 PROC_LOCK(p); 796 td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NPROC); 797 PROC_UNLOCK(p); 798 return 0; 799 800 case IBCS2_SC_CLK_TCK: 801 td->td_retval[0] = hz; 802 return 0; 803 804 case IBCS2_SC_NGROUPS_MAX: 805 mib[1] = KERN_NGROUPS; 806 break; 807 808 case IBCS2_SC_OPEN_MAX: 809 PROC_LOCK(p); 810 td->td_retval[0] = lim_cur(td->td_proc, RLIMIT_NOFILE); 811 PROC_UNLOCK(p); 812 return 0; 813 814 case IBCS2_SC_JOB_CONTROL: 815 mib[1] = KERN_JOB_CONTROL; 816 break; 817 818 case IBCS2_SC_SAVED_IDS: 819 mib[1] = KERN_SAVED_IDS; 820 break; 821 822 case IBCS2_SC_VERSION: 823 mib[1] = KERN_POSIX1; 824 break; 825 826 case IBCS2_SC_PASS_MAX: 827 td->td_retval[0] = 128; /* XXX - should we create PASS_MAX ? */ 828 return 0; 829 830 case IBCS2_SC_XOPEN_VERSION: 831 td->td_retval[0] = 2; /* XXX: What should that be? */ 832 return 0; 833 834 default: 835 return EINVAL; 836 } 837 838 mib[0] = CTL_KERN; 839 len = sizeof(value); 840 error = kernel_sysctl(td, mib, 2, &value, &len, NULL, 0, NULL, 0); 841 if (error) 842 return error; 843 td->td_retval[0] = value; 844 return 0; 845} 846 847int 848ibcs2_alarm(td, uap) 849 struct thread *td; 850 struct ibcs2_alarm_args *uap; 851{ 852 struct itimerval itv, oitv; 853 int error; 854 855 timevalclear(&itv.it_interval); 856 itv.it_value.tv_sec = uap->sec; 857 itv.it_value.tv_usec = 0; 858 error = kern_setitimer(td, ITIMER_REAL, &itv, &oitv); 859 if (error) 860 return (error); 861 if (oitv.it_value.tv_usec != 0) 862 oitv.it_value.tv_sec++; 863 td->td_retval[0] = oitv.it_value.tv_sec; 864 return (0); 865} 866 867int 868ibcs2_times(td, uap) 869 struct thread *td; 870 struct ibcs2_times_args *uap; 871{ 872 struct rusage ru; 873 struct timeval t; 874 struct tms tms; 875 int error; 876 877#define CONVTCK(r) (r.tv_sec * hz + r.tv_usec / (1000000 / hz)) 878 879 error = kern_getrusage(td, RUSAGE_SELF, &ru); 880 if (error) 881 return (error); 882 tms.tms_utime = CONVTCK(ru.ru_utime); 883 tms.tms_stime = CONVTCK(ru.ru_stime); 884 885 error = kern_getrusage(td, RUSAGE_CHILDREN, &ru); 886 if (error) 887 return (error); 888 tms.tms_cutime = CONVTCK(ru.ru_utime); 889 tms.tms_cstime = CONVTCK(ru.ru_stime); 890 891 microtime(&t); 892 td->td_retval[0] = CONVTCK(t); 893 894 return (copyout(&tms, uap->tp, sizeof(struct tms))); 895} 896 897int 898ibcs2_stime(td, uap) 899 struct thread *td; 900 struct ibcs2_stime_args *uap; 901{ 902 struct timeval tv; 903 long secs; 904 int error; 905 906 error = copyin(uap->timep, &secs, sizeof(long)); 907 if (error) 908 return (error); 909 tv.tv_sec = secs; 910 tv.tv_usec = 0; 911 error = kern_settimeofday(td, &tv, NULL); 912 if (error) 913 error = EPERM; 914 return (error); 915} 916 917int 918ibcs2_utime(td, uap) 919 struct thread *td; 920 struct ibcs2_utime_args *uap; 921{ 922 struct ibcs2_utimbuf ubuf; 923 struct timeval tbuf[2], *tp; 924 char *path; 925 int error; 926 927 if (uap->buf) { 928 error = copyin(uap->buf, &ubuf, sizeof(ubuf)); 929 if (error) 930 return (error); 931 tbuf[0].tv_sec = ubuf.actime; 932 tbuf[0].tv_usec = 0; 933 tbuf[1].tv_sec = ubuf.modtime; 934 tbuf[1].tv_usec = 0; 935 tp = tbuf; 936 } else 937 tp = NULL; 938 939 CHECKALTEXIST(td, uap->path, &path); 940 error = kern_utimes(td, path, UIO_SYSSPACE, tp, UIO_SYSSPACE); 941 free(path, M_TEMP); 942 return (error); 943} 944 945int 946ibcs2_nice(td, uap) 947 struct thread *td; 948 struct ibcs2_nice_args *uap; 949{ 950 int error; 951 struct setpriority_args sa; 952 953 sa.which = PRIO_PROCESS; 954 sa.who = 0; 955 sa.prio = td->td_proc->p_nice + uap->incr; 956 if ((error = setpriority(td, &sa)) != 0) 957 return EPERM; 958 td->td_retval[0] = td->td_proc->p_nice; 959 return 0; 960} 961 962/* 963 * iBCS2 getpgrp, setpgrp, setsid, and setpgid 964 */ 965 966int 967ibcs2_pgrpsys(td, uap) 968 struct thread *td; 969 struct ibcs2_pgrpsys_args *uap; 970{ 971 struct proc *p = td->td_proc; 972 switch (uap->type) { 973 case 0: /* getpgrp */ 974 PROC_LOCK(p); 975 td->td_retval[0] = p->p_pgrp->pg_id; 976 PROC_UNLOCK(p); 977 return 0; 978 979 case 1: /* setpgrp */ 980 { 981 struct setpgid_args sa; 982 983 sa.pid = 0; 984 sa.pgid = 0; 985 setpgid(td, &sa); 986 PROC_LOCK(p); 987 td->td_retval[0] = p->p_pgrp->pg_id; 988 PROC_UNLOCK(p); 989 return 0; 990 } 991 992 case 2: /* setpgid */ 993 { 994 struct setpgid_args sa; 995 996 sa.pid = uap->pid; 997 sa.pgid = uap->pgid; 998 return setpgid(td, &sa); 999 } 1000 1001 case 3: /* setsid */ 1002 return setsid(td, NULL); 1003 1004 default: 1005 return EINVAL; 1006 } 1007} 1008 1009/* 1010 * XXX - need to check for nested calls 1011 */ 1012 1013int 1014ibcs2_plock(td, uap) 1015 struct thread *td; 1016 struct ibcs2_plock_args *uap; 1017{ 1018 int error; 1019#define IBCS2_UNLOCK 0 1020#define IBCS2_PROCLOCK 1 1021#define IBCS2_TEXTLOCK 2 1022#define IBCS2_DATALOCK 4 1023 1024 1025 switch(uap->cmd) { 1026 case IBCS2_UNLOCK: 1027 error = priv_check(td, PRIV_VM_MUNLOCK); 1028 if (error) 1029 return (error); 1030 /* XXX - TODO */ 1031 return (0); 1032 1033 case IBCS2_PROCLOCK: 1034 case IBCS2_TEXTLOCK: 1035 case IBCS2_DATALOCK: 1036 error = priv_check(td, PRIV_VM_MLOCK); 1037 if (error) 1038 return (error); 1039 /* XXX - TODO */ 1040 return 0; 1041 } 1042 return EINVAL; 1043} 1044 1045int 1046ibcs2_uadmin(td, uap) 1047 struct thread *td; 1048 struct ibcs2_uadmin_args *uap; 1049{ 1050#define SCO_A_REBOOT 1 1051#define SCO_A_SHUTDOWN 2 1052#define SCO_A_REMOUNT 4 1053#define SCO_A_CLOCK 8 1054#define SCO_A_SETCONFIG 128 1055#define SCO_A_GETDEV 130 1056 1057#define SCO_AD_HALT 0 1058#define SCO_AD_BOOT 1 1059#define SCO_AD_IBOOT 2 1060#define SCO_AD_PWRDOWN 3 1061#define SCO_AD_PWRNAP 4 1062 1063#define SCO_AD_PANICBOOT 1 1064 1065#define SCO_AD_GETBMAJ 0 1066#define SCO_AD_GETCMAJ 1 1067 1068 switch(uap->cmd) { 1069 case SCO_A_REBOOT: 1070 case SCO_A_SHUTDOWN: 1071 switch(uap->func) { 1072 struct reboot_args r; 1073 case SCO_AD_HALT: 1074 case SCO_AD_PWRDOWN: 1075 case SCO_AD_PWRNAP: 1076 r.opt = RB_HALT; 1077 return (reboot(td, &r)); 1078 case SCO_AD_BOOT: 1079 case SCO_AD_IBOOT: 1080 r.opt = RB_AUTOBOOT; 1081 return (reboot(td, &r)); 1082 } 1083 return EINVAL; 1084 case SCO_A_REMOUNT: 1085 case SCO_A_CLOCK: 1086 case SCO_A_SETCONFIG: 1087 return 0; 1088 case SCO_A_GETDEV: 1089 return EINVAL; /* XXX - TODO */ 1090 } 1091 return EINVAL; 1092} 1093 1094int 1095ibcs2_sysfs(td, uap) 1096 struct thread *td; 1097 struct ibcs2_sysfs_args *uap; 1098{ 1099#define IBCS2_GETFSIND 1 1100#define IBCS2_GETFSTYP 2 1101#define IBCS2_GETNFSTYP 3 1102 1103 switch(uap->cmd) { 1104 case IBCS2_GETFSIND: 1105 case IBCS2_GETFSTYP: 1106 case IBCS2_GETNFSTYP: 1107 break; 1108 } 1109 return EINVAL; /* XXX - TODO */ 1110} 1111 1112int 1113ibcs2_unlink(td, uap) 1114 struct thread *td; 1115 struct ibcs2_unlink_args *uap; 1116{ 1117 char *path; 1118 int error; 1119 1120 CHECKALTEXIST(td, uap->path, &path); 1121 error = kern_unlink(td, path, UIO_SYSSPACE); 1122 free(path, M_TEMP); 1123 return (error); 1124} 1125 1126int 1127ibcs2_chdir(td, uap) 1128 struct thread *td; 1129 struct ibcs2_chdir_args *uap; 1130{ 1131 char *path; 1132 int error; 1133 1134 CHECKALTEXIST(td, uap->path, &path); 1135 error = kern_chdir(td, path, UIO_SYSSPACE); 1136 free(path, M_TEMP); 1137 return (error); 1138} 1139 1140int 1141ibcs2_chmod(td, uap) 1142 struct thread *td; 1143 struct ibcs2_chmod_args *uap; 1144{ 1145 char *path; 1146 int error; 1147 1148 CHECKALTEXIST(td, uap->path, &path); 1149 error = kern_chmod(td, path, UIO_SYSSPACE, uap->mode); 1150 free(path, M_TEMP); 1151 return (error); 1152} 1153 1154int 1155ibcs2_chown(td, uap) 1156 struct thread *td; 1157 struct ibcs2_chown_args *uap; 1158{ 1159 char *path; 1160 int error; 1161 1162 CHECKALTEXIST(td, uap->path, &path); 1163 error = kern_chown(td, path, UIO_SYSSPACE, uap->uid, uap->gid); 1164 free(path, M_TEMP); 1165 return (error); 1166} 1167 1168int 1169ibcs2_rmdir(td, uap) 1170 struct thread *td; 1171 struct ibcs2_rmdir_args *uap; 1172{ 1173 char *path; 1174 int error; 1175 1176 CHECKALTEXIST(td, uap->path, &path); 1177 error = kern_rmdir(td, path, UIO_SYSSPACE); 1178 free(path, M_TEMP); 1179 return (error); 1180} 1181 1182int 1183ibcs2_mkdir(td, uap) 1184 struct thread *td; 1185 struct ibcs2_mkdir_args *uap; 1186{ 1187 char *path; 1188 int error; 1189 1190 CHECKALTEXIST(td, uap->path, &path); 1191 error = kern_mkdir(td, path, UIO_SYSSPACE, uap->mode); 1192 free(path, M_TEMP); 1193 return (error); 1194} 1195 1196int 1197ibcs2_symlink(td, uap) 1198 struct thread *td; 1199 struct ibcs2_symlink_args *uap; 1200{ 1201 char *path, *link; 1202 int error; 1203 1204 CHECKALTEXIST(td, uap->path, &path); 1205 1206 /* 1207 * Have to expand CHECKALTCREAT() so that 'path' can be freed on 1208 * errors. 1209 */ 1210 error = ibcs2_emul_find(td, uap->link, UIO_USERSPACE, &link, 1); 1211 if (link == NULL) { 1212 free(path, M_TEMP); 1213 return (error); 1214 } 1215 error = kern_symlink(td, path, link, UIO_SYSSPACE); 1216 free(path, M_TEMP); 1217 free(link, M_TEMP); 1218 return (error); 1219} 1220 1221int 1222ibcs2_rename(td, uap) 1223 struct thread *td; 1224 struct ibcs2_rename_args *uap; 1225{ 1226 char *from, *to; 1227 int error; 1228 1229 CHECKALTEXIST(td, uap->from, &from); 1230 1231 /* 1232 * Have to expand CHECKALTCREAT() so that 'from' can be freed on 1233 * errors. 1234 */ 1235 error = ibcs2_emul_find(td, uap->to, UIO_USERSPACE, &to, 1); 1236 if (to == NULL) { 1237 free(from, M_TEMP); 1238 return (error); 1239 } 1240 error = kern_rename(td, from, to, UIO_SYSSPACE); 1241 free(from, M_TEMP); 1242 free(to, M_TEMP); 1243 return (error); 1244} 1245 1246int 1247ibcs2_readlink(td, uap) 1248 struct thread *td; 1249 struct ibcs2_readlink_args *uap; 1250{ 1251 char *path; 1252 int error; 1253 1254 CHECKALTEXIST(td, uap->path, &path); 1255 error = kern_readlink(td, path, UIO_SYSSPACE, uap->buf, UIO_USERSPACE, 1256 uap->count); 1257 free(path, M_TEMP); 1258 return (error); 1259}
|