1 /*- 2 * Copyright (c) 1994-1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software withough specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id: linux_misc.c,v 1.32 1997/10/30 10:53:30 kato Exp $ 29 */ 30 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/sysproto.h> 34 #include <sys/kernel.h> 35 #include <sys/mman.h> 36 #include <sys/proc.h> 37 #include <sys/fcntl.h> 38 #include <sys/imgact_aout.h> 39 #include <sys/mount.h> 40 #include <sys/namei.h> 41 #include <sys/resourcevar.h> 42 #include <sys/stat.h> 43 #include <sys/sysctl.h> 44 #include <sys/vnode.h> 45 #include <sys/wait.h> 46 #include <sys/time.h> 47 48 #include <vm/vm.h> 49 #include <vm/pmap.h> 50 #include <vm/vm_kern.h> 51 #include <vm/vm_prot.h> 52 #include <vm/vm_map.h> 53 #include <vm/vm_extern.h> 54 55 #include <machine/frame.h> 56 #include <machine/psl.h> 57 58 #include <i386/linux/linux.h> 59 #include <i386/linux/linux_proto.h> 60 #include <i386/linux/linux_util.h> 61 62 int 63 linux_alarm(struct proc *p, struct linux_alarm_args *args) 64 { 65 struct itimerval it, old_it; 66 struct timeval tv; 67 int s; 68 69 #ifdef DEBUG 70 printf("Linux-emul(%d): alarm(%d)\n", p->p_pid, args->secs); 71 #endif 72 it.it_value.tv_sec = (long)args->secs; 73 it.it_value.tv_usec = 0; 74 it.it_interval.tv_sec = 0; 75 it.it_interval.tv_usec = 0; 76 s = splclock(); 77 old_it = p->p_realtimer; 78 tv = time; 79 if (timerisset(&old_it.it_value)) 80 if (timercmp(&old_it.it_value, &tv, <)) 81 timerclear(&old_it.it_value); 82 else 83 timevalsub(&old_it.it_value, &tv); 84 splx(s); 85 if (itimerfix(&it.it_value) || itimerfix(&it.it_interval)) 86 return EINVAL; 87 s = splclock(); 88 if (timerisset(&p->p_realtimer.it_value)) 89 untimeout(realitexpire, (caddr_t)p, p->p_ithandle); 90 tv = time; 91 if (timerisset(&it.it_value)) { 92 timevaladd(&it.it_value, &tv); 93 p->p_ithandle = timeout(realitexpire, (caddr_t)p, hzto(&it.it_value)); 94 } 95 p->p_realtimer = it; 96 splx(s); 97 if (old_it.it_value.tv_usec) 98 old_it.it_value.tv_sec++; 99 p->p_retval[0] = old_it.it_value.tv_sec; 100 return 0; 101 } 102 103 int 104 linux_brk(struct proc *p, struct linux_brk_args *args) 105 { 106 #if 0 107 struct vmspace *vm = p->p_vmspace; 108 vm_offset_t new, old; 109 int error; 110 111 if ((vm_offset_t)args->dsend < (vm_offset_t)vm->vm_daddr) 112 return EINVAL; 113 if (((caddr_t)args->dsend - (caddr_t)vm->vm_daddr) 114 > p->p_rlimit[RLIMIT_DATA].rlim_cur) 115 return ENOMEM; 116 117 old = round_page((vm_offset_t)vm->vm_daddr) + ctob(vm->vm_dsize); 118 new = round_page((vm_offset_t)args->dsend); 119 p->p_retval[0] = old; 120 if ((new-old) > 0) { 121 if (swap_pager_full) 122 return ENOMEM; 123 error = vm_map_find(&vm->vm_map, NULL, 0, &old, (new-old), FALSE, 124 VM_PROT_ALL, VM_PROT_ALL, 0); 125 if (error) 126 return error; 127 vm->vm_dsize += btoc((new-old)); 128 p->p_retval[0] = (int)(vm->vm_daddr + ctob(vm->vm_dsize)); 129 } 130 return 0; 131 #else 132 struct vmspace *vm = p->p_vmspace; 133 vm_offset_t new, old; 134 struct obreak_args /* { 135 char * nsize; 136 } */ tmp; 137 138 #ifdef DEBUG 139 printf("Linux-emul(%d): brk(%08x)\n", p->p_pid, args->dsend); 140 #endif 141 old = (vm_offset_t)vm->vm_daddr + ctob(vm->vm_dsize); 142 new = (vm_offset_t)args->dsend; 143 tmp.nsize = (char *) new; 144 if (((caddr_t)new > vm->vm_daddr) && !obreak(p, &tmp)) 145 p->p_retval[0] = (int)new; 146 else 147 p->p_retval[0] = (int)old; 148 149 return 0; 150 #endif 151 } 152 153 int 154 linux_uselib(struct proc *p, struct linux_uselib_args *args) 155 { 156 struct nameidata ni; 157 struct vnode *vp; 158 struct exec *a_out; 159 struct vattr attr; 160 vm_offset_t vmaddr; 161 unsigned long file_offset; 162 vm_offset_t buffer; 163 unsigned long bss_size; 164 int error; 165 caddr_t sg; 166 int locked; 167 168 sg = stackgap_init(); 169 CHECKALTEXIST(p, &sg, args->library); 170 171 #ifdef DEBUG 172 printf("Linux-emul(%d): uselib(%s)\n", p->p_pid, args->library); 173 #endif 174 175 a_out = NULL; 176 locked = 0; 177 vp = NULL; 178 179 NDINIT(&ni, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, args->library, p); 180 if (error = namei(&ni)) 181 goto cleanup; 182 183 vp = ni.ni_vp; 184 if (vp == NULL) { 185 error = ENOEXEC; /* ?? */ 186 goto cleanup; 187 } 188 189 /* 190 * From here on down, we have a locked vnode that must be unlocked. 191 */ 192 locked++; 193 194 /* 195 * Writable? 196 */ 197 if (vp->v_writecount) { 198 error = ETXTBSY; 199 goto cleanup; 200 } 201 202 /* 203 * Executable? 204 */ 205 if (error = VOP_GETATTR(vp, &attr, p->p_ucred, p)) 206 goto cleanup; 207 208 if ((vp->v_mount->mnt_flag & MNT_NOEXEC) || 209 ((attr.va_mode & 0111) == 0) || 210 (attr.va_type != VREG)) { 211 error = ENOEXEC; 212 goto cleanup; 213 } 214 215 /* 216 * Sensible size? 217 */ 218 if (attr.va_size == 0) { 219 error = ENOEXEC; 220 goto cleanup; 221 } 222 223 /* 224 * Can we access it? 225 */ 226 if (error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p)) 227 goto cleanup; 228 229 if (error = VOP_OPEN(vp, FREAD, p->p_ucred, p)) 230 goto cleanup; 231 232 /* 233 * Lock no longer needed 234 */ 235 VOP_UNLOCK(vp, 0, p); 236 locked = 0; 237 238 /* 239 * Pull in executable header into kernel_map 240 */ 241 error = vm_mmap(kernel_map, (vm_offset_t *)&a_out, PAGE_SIZE, 242 VM_PROT_READ, VM_PROT_READ, 0, (caddr_t)vp, 0); 243 if (error) 244 goto cleanup; 245 246 /* 247 * Is it a Linux binary ? 248 */ 249 if (((a_out->a_magic >> 16) & 0xff) != 0x64) { 250 error = ENOEXEC; 251 goto cleanup; 252 } 253 254 /* While we are here, we should REALLY do some more checks */ 255 256 /* 257 * Set file/virtual offset based on a.out variant. 258 */ 259 switch ((int)(a_out->a_magic & 0xffff)) { 260 case 0413: /* ZMAGIC */ 261 file_offset = 1024; 262 break; 263 case 0314: /* QMAGIC */ 264 file_offset = 0; 265 break; 266 default: 267 error = ENOEXEC; 268 goto cleanup; 269 } 270 271 bss_size = round_page(a_out->a_bss); 272 273 /* 274 * Check various fields in header for validity/bounds. 275 */ 276 if (a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK) { 277 error = ENOEXEC; 278 goto cleanup; 279 } 280 281 /* text + data can't exceed file size */ 282 if (a_out->a_data + a_out->a_text > attr.va_size) { 283 error = EFAULT; 284 goto cleanup; 285 } 286 287 /* 288 * text/data/bss must not exceed limits 289 * XXX: this is not complete. it should check current usage PLUS 290 * the resources needed by this library. 291 */ 292 if (a_out->a_text > MAXTSIZ || a_out->a_data + bss_size > MAXDSIZ || 293 a_out->a_data+bss_size > p->p_rlimit[RLIMIT_DATA].rlim_cur) { 294 error = ENOMEM; 295 goto cleanup; 296 } 297 298 /* 299 * prevent more writers 300 */ 301 vp->v_flag |= VTEXT; 302 303 /* 304 * Check if file_offset page aligned,. 305 * Currently we cannot handle misalinged file offsets, 306 * and so we read in the entire image (what a waste). 307 */ 308 if (file_offset & PAGE_MASK) { 309 #ifdef DEBUG 310 printf("uselib: Non page aligned binary %d\n", file_offset); 311 #endif 312 /* 313 * Map text+data read/write/execute 314 */ 315 316 /* a_entry is the load address and is page aligned */ 317 vmaddr = trunc_page(a_out->a_entry); 318 319 /* get anon user mapping, read+write+execute */ 320 error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, 321 a_out->a_text + a_out->a_data, FALSE, 322 VM_PROT_ALL, VM_PROT_ALL, 0); 323 if (error) 324 goto cleanup; 325 326 /* map file into kernel_map */ 327 error = vm_mmap(kernel_map, &buffer, 328 round_page(a_out->a_text + a_out->a_data + file_offset), 329 VM_PROT_READ, VM_PROT_READ, 0, 330 (caddr_t)vp, trunc_page(file_offset)); 331 if (error) 332 goto cleanup; 333 334 /* copy from kernel VM space to user space */ 335 error = copyout((caddr_t)(buffer + file_offset), (caddr_t)vmaddr, 336 a_out->a_text + a_out->a_data); 337 338 /* release temporary kernel space */ 339 vm_map_remove(kernel_map, buffer, 340 buffer + round_page(a_out->a_text + a_out->a_data + file_offset)); 341 342 if (error) 343 goto cleanup; 344 } 345 else { 346 #ifdef DEBUG 347 printf("uselib: Page aligned binary %d\n", file_offset); 348 #endif 349 /* 350 * for QMAGIC, a_entry is 20 bytes beyond the load address 351 * to skip the executable header 352 */ 353 vmaddr = trunc_page(a_out->a_entry); 354 355 /* 356 * Map it all into the process's space as a single copy-on-write 357 * "data" segment. 358 */ 359 error = vm_mmap(&p->p_vmspace->vm_map, &vmaddr, 360 a_out->a_text + a_out->a_data, 361 VM_PROT_ALL, VM_PROT_ALL, MAP_PRIVATE | MAP_FIXED, 362 (caddr_t)vp, file_offset); 363 if (error) 364 goto cleanup; 365 } 366 #ifdef DEBUG 367 printf("mem=%08x = %08x %08x\n", vmaddr, ((int*)vmaddr)[0], ((int*)vmaddr)[1]); 368 #endif 369 if (bss_size != 0) { 370 /* 371 * Calculate BSS start address 372 */ 373 vmaddr = trunc_page(a_out->a_entry) + a_out->a_text + a_out->a_data; 374 375 /* 376 * allocate some 'anon' space 377 */ 378 error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &vmaddr, 379 bss_size, FALSE, 380 VM_PROT_ALL, VM_PROT_ALL, 0); 381 if (error) 382 goto cleanup; 383 } 384 385 cleanup: 386 /* 387 * Unlock vnode if needed 388 */ 389 if (locked) 390 VOP_UNLOCK(vp, 0, p); 391 392 /* 393 * Release the kernel mapping. 394 */ 395 if (a_out) 396 vm_map_remove(kernel_map, (vm_offset_t)a_out, (vm_offset_t)a_out + PAGE_SIZE); 397 398 return error; 399 } 400 401 /* XXX move */ 402 struct linux_select_argv { 403 int nfds; 404 fd_set *readfds; 405 fd_set *writefds; 406 fd_set *exceptfds; 407 struct timeval *timeout; 408 }; 409 410 int 411 linux_select(struct proc *p, struct linux_select_args *args) 412 { 413 struct linux_select_argv linux_args; 414 struct linux_newselect_args newsel; 415 int error; 416 417 #ifdef SELECT_DEBUG 418 printf("Linux-emul(%d): select(%x)\n", 419 p->p_pid, args->ptr); 420 #endif 421 if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args, 422 sizeof(linux_args)))) 423 return error; 424 425 newsel.nfds = linux_args.nfds; 426 newsel.readfds = linux_args.readfds; 427 newsel.writefds = linux_args.writefds; 428 newsel.exceptfds = linux_args.exceptfds; 429 newsel.timeout = linux_args.timeout; 430 431 return linux_newselect(p, &newsel); 432 } 433 434 int 435 linux_newselect(struct proc *p, struct linux_newselect_args *args) 436 { 437 struct select_args bsa; 438 struct timeval tv0, tv1, utv, *tvp; 439 caddr_t sg; 440 int error; 441 442 #ifdef DEBUG 443 printf("Linux-emul(%d): newselect(%d, %x, %x, %x, %x)\n", 444 p->p_pid, args->nfds, args->readfds, args->writefds, 445 args->exceptfds, args->timeout); 446 #endif 447 error = 0; 448 bsa.nd = args->nfds; 449 bsa.in = args->readfds; 450 bsa.ou = args->writefds; 451 bsa.ex = args->exceptfds; 452 bsa.tv = args->timeout; 453 454 /* 455 * Store current time for computation of the amount of 456 * time left. 457 */ 458 if (args->timeout) { 459 if ((error = copyin(args->timeout, &utv, sizeof(utv)))) 460 goto select_out; 461 #ifdef DEBUG 462 printf("Linux-emul(%d): incoming timeout (%d/%d)\n", 463 p->p_pid, utv.tv_sec, utv.tv_usec); 464 #endif 465 if (itimerfix(&utv)) { 466 /* 467 * The timeval was invalid. Convert it to something 468 * valid that will act as it does under Linux. 469 */ 470 sg = stackgap_init(); 471 tvp = stackgap_alloc(&sg, sizeof(utv)); 472 utv.tv_sec += utv.tv_usec / 1000000; 473 utv.tv_usec %= 1000000; 474 if (utv.tv_usec < 0) { 475 utv.tv_sec -= 1; 476 utv.tv_usec += 1000000; 477 } 478 if (utv.tv_sec < 0) 479 timerclear(&utv); 480 if ((error = copyout(&utv, tvp, sizeof(utv)))) 481 goto select_out; 482 bsa.tv = tvp; 483 } 484 microtime(&tv0); 485 } 486 487 error = select(p, &bsa); 488 #ifdef DEBUG 489 printf("Linux-emul(%d): real select returns %d\n", 490 p->p_pid, error); 491 #endif 492 493 if (error) { 494 /* 495 * See fs/select.c in the Linux kernel. Without this, 496 * Maelstrom doesn't work. 497 */ 498 if (error == ERESTART) 499 error = EINTR; 500 goto select_out; 501 } 502 503 if (args->timeout) { 504 if (p->p_retval[0]) { 505 /* 506 * Compute how much time was left of the timeout, 507 * by subtracting the current time and the time 508 * before we started the call, and subtracting 509 * that result from the user-supplied value. 510 */ 511 microtime(&tv1); 512 timevalsub(&tv1, &tv0); 513 timevalsub(&utv, &tv1); 514 if (utv.tv_sec < 0) 515 timerclear(&utv); 516 } else 517 timerclear(&utv); 518 #ifdef DEBUG 519 printf("Linux-emul(%d): outgoing timeout (%d/%d)\n", 520 p->p_pid, utv.tv_sec, utv.tv_usec); 521 #endif 522 if ((error = copyout(&utv, args->timeout, sizeof(utv)))) 523 goto select_out; 524 } 525 526 select_out: 527 #ifdef DEBUG 528 printf("Linux-emul(%d): newselect_out -> %d\n", 529 p->p_pid, error); 530 #endif 531 return error; 532 } 533 534 int 535 linux_getpgid(struct proc *p, struct linux_getpgid_args *args) 536 { 537 struct proc *curproc; 538 539 #ifdef DEBUG 540 printf("Linux-emul(%d): getpgid(%d)\n", p->p_pid, args->pid); 541 #endif 542 if (args->pid != p->p_pid) { 543 if (!(curproc = pfind(args->pid))) 544 return ESRCH; 545 } 546 else 547 curproc = p; 548 p->p_retval[0] = curproc->p_pgid; 549 return 0; 550 } 551 552 int 553 linux_fork(struct proc *p, struct linux_fork_args *args) 554 { 555 int error; 556 557 #ifdef DEBUG 558 printf("Linux-emul(%d): fork()\n", p->p_pid); 559 #endif 560 if (error = fork(p, (struct fork_args *)args)) 561 return error; 562 if (p->p_retval[1] == 1) 563 p->p_retval[0] = 0; 564 return 0; 565 } 566 567 /* XXX move */ 568 struct linux_mmap_argv { 569 linux_caddr_t addr; 570 int len; 571 int prot; 572 int flags; 573 int fd; 574 int pos; 575 }; 576 577 int 578 linux_mmap(struct proc *p, struct linux_mmap_args *args) 579 { 580 struct mmap_args /* { 581 caddr_t addr; 582 size_t len; 583 int prot; 584 int flags; 585 int fd; 586 long pad; 587 off_t pos; 588 } */ bsd_args; 589 int error; 590 struct linux_mmap_argv linux_args; 591 592 if ((error = copyin((caddr_t)args->ptr, (caddr_t)&linux_args, 593 sizeof(linux_args)))) 594 return error; 595 #ifdef DEBUG 596 printf("Linux-emul(%d): mmap(%08x, %d, %d, %08x, %d, %d)\n", 597 p->p_pid, linux_args.addr, linux_args.len, linux_args.prot, 598 linux_args.flags, linux_args.fd, linux_args.pos); 599 #endif 600 bsd_args.flags = 0; 601 if (linux_args.flags & LINUX_MAP_SHARED) 602 bsd_args.flags |= MAP_SHARED; 603 if (linux_args.flags & LINUX_MAP_PRIVATE) 604 bsd_args.flags |= MAP_PRIVATE; 605 if (linux_args.flags & LINUX_MAP_FIXED) 606 bsd_args.flags |= MAP_FIXED; 607 if (linux_args.flags & LINUX_MAP_ANON) 608 bsd_args.flags |= MAP_ANON; 609 bsd_args.addr = linux_args.addr; 610 bsd_args.len = linux_args.len; 611 bsd_args.prot = linux_args.prot | PROT_READ; /* always required */ 612 bsd_args.fd = linux_args.fd; 613 bsd_args.pos = linux_args.pos; 614 bsd_args.pad = 0; 615 return mmap(p, &bsd_args); 616 } 617 618 int 619 linux_msync(struct proc *p, struct linux_msync_args *args) 620 { 621 struct msync_args bsd_args; 622 623 bsd_args.addr = args->addr; 624 bsd_args.len = args->len; 625 bsd_args.flags = 0; /* XXX ignore */ 626 627 return msync(p, &bsd_args); 628 } 629 630 int 631 linux_pipe(struct proc *p, struct linux_pipe_args *args) 632 { 633 int error; 634 635 #ifdef DEBUG 636 printf("Linux-emul(%d): pipe(*)\n", p->p_pid); 637 #endif 638 if (error = pipe(p, 0)) 639 return error; 640 if (error = copyout(p->p_retval, args->pipefds, 2*sizeof(int))) 641 return error; 642 p->p_retval[0] = 0; 643 return 0; 644 } 645 646 int 647 linux_time(struct proc *p, struct linux_time_args *args) 648 { 649 struct timeval tv; 650 linux_time_t tm; 651 int error; 652 653 #ifdef DEBUG 654 printf("Linux-emul(%d): time(*)\n", p->p_pid); 655 #endif 656 microtime(&tv); 657 tm = tv.tv_sec; 658 if (args->tm && (error = copyout(&tm, args->tm, sizeof(linux_time_t)))) 659 return error; 660 p->p_retval[0] = tm; 661 return 0; 662 } 663 664 struct linux_times_argv { 665 long tms_utime; 666 long tms_stime; 667 long tms_cutime; 668 long tms_cstime; 669 }; 670 671 #define CLK_TCK 100 /* Linux uses 100 */ 672 #define CONVTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK)) 673 674 int 675 linux_times(struct proc *p, struct linux_times_args *args) 676 { 677 struct timeval tv; 678 struct linux_times_argv tms; 679 struct rusage ru; 680 int error; 681 682 #ifdef DEBUG 683 printf("Linux-emul(%d): times(*)\n", p->p_pid); 684 #endif 685 calcru(p, &ru.ru_utime, &ru.ru_stime, NULL); 686 687 tms.tms_utime = CONVTCK(ru.ru_utime); 688 tms.tms_stime = CONVTCK(ru.ru_stime); 689 690 tms.tms_cutime = CONVTCK(p->p_stats->p_cru.ru_utime); 691 tms.tms_cstime = CONVTCK(p->p_stats->p_cru.ru_stime); 692 693 if ((error = copyout((caddr_t)&tms, (caddr_t)args->buf, 694 sizeof(struct linux_times_argv)))) 695 return error; 696 697 microtime(&tv); 698 timevalsub(&tv, &boottime); 699 p->p_retval[0] = (int)CONVTCK(tv); 700 return 0; 701 } 702 703 /* XXX move */ 704 struct linux_newuname_t { 705 char sysname[65]; 706 char nodename[65]; 707 char release[65]; 708 char version[65]; 709 char machine[65]; 710 char domainname[65]; 711 }; 712 713 int 714 linux_newuname(struct proc *p, struct linux_newuname_args *args) 715 { 716 struct linux_newuname_t linux_newuname; 717 718 #ifdef DEBUG 719 printf("Linux-emul(%d): newuname(*)\n", p->p_pid); 720 #endif 721 bzero(&linux_newuname, sizeof(struct linux_newuname_args)); 722 strncpy(linux_newuname.sysname, ostype, 64); 723 strncpy(linux_newuname.nodename, hostname, 64); 724 strncpy(linux_newuname.release, osrelease, 64); 725 strncpy(linux_newuname.version, version, 64); 726 strncpy(linux_newuname.machine, machine, 64); 727 strncpy(linux_newuname.domainname, domainname, 64); 728 return (copyout((caddr_t)&linux_newuname, (caddr_t)args->buf, 729 sizeof(struct linux_newuname_t))); 730 } 731 732 struct linux_utimbuf { 733 linux_time_t l_actime; 734 linux_time_t l_modtime; 735 }; 736 737 int 738 linux_utime(struct proc *p, struct linux_utime_args *args) 739 { 740 struct utimes_args /* { 741 char *path; 742 struct timeval *tptr; 743 } */ bsdutimes; 744 struct timeval tv[2], *tvp; 745 struct linux_utimbuf lut; 746 int error; 747 caddr_t sg; 748 749 sg = stackgap_init(); 750 CHECKALTEXIST(p, &sg, args->fname); 751 752 #ifdef DEBUG 753 printf("Linux-emul(%d): utime(%s, *)\n", p->p_pid, args->fname); 754 #endif 755 if (args->times) { 756 if ((error = copyin(args->times, &lut, sizeof lut))) 757 return error; 758 tv[0].tv_sec = lut.l_actime; 759 tv[0].tv_usec = 0; 760 tv[1].tv_sec = lut.l_modtime; 761 tv[1].tv_usec = 0; 762 /* so that utimes can copyin */ 763 tvp = (struct timeval *)stackgap_alloc(&sg, sizeof(tv)); 764 if ((error = copyout(tv, tvp, sizeof(tv)))) 765 return error; 766 bsdutimes.tptr = tvp; 767 } else 768 bsdutimes.tptr = NULL; 769 770 bsdutimes.path = args->fname; 771 return utimes(p, &bsdutimes); 772 } 773 774 int 775 linux_waitpid(struct proc *p, struct linux_waitpid_args *args) 776 { 777 struct wait_args /* { 778 int pid; 779 int *status; 780 int options; 781 struct rusage *rusage; 782 } */ tmp; 783 int error, tmpstat; 784 785 #ifdef DEBUG 786 printf("Linux-emul(%d): waitpid(%d, 0x%x, %d)\n", 787 p->p_pid, args->pid, args->status, args->options); 788 #endif 789 tmp.pid = args->pid; 790 tmp.status = args->status; 791 tmp.options = args->options; 792 tmp.rusage = NULL; 793 794 if (error = wait4(p, &tmp)) 795 return error; 796 if (args->status) { 797 if (error = copyin(args->status, &tmpstat, sizeof(int))) 798 return error; 799 if (WIFSIGNALED(tmpstat)) 800 tmpstat = (tmpstat & 0xffffff80) | 801 bsd_to_linux_signal[WTERMSIG(tmpstat)]; 802 else if (WIFSTOPPED(tmpstat)) 803 tmpstat = (tmpstat & 0xffff00ff) | 804 (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8); 805 return copyout(&tmpstat, args->status, sizeof(int)); 806 } else 807 return 0; 808 } 809 810 int 811 linux_wait4(struct proc *p, struct linux_wait4_args *args) 812 { 813 struct wait_args /* { 814 int pid; 815 int *status; 816 int options; 817 struct rusage *rusage; 818 } */ tmp; 819 int error, tmpstat; 820 821 #ifdef DEBUG 822 printf("Linux-emul(%d): wait4(%d, 0x%x, %d, 0x%x)\n", 823 p->p_pid, args->pid, args->status, args->options, args->rusage); 824 #endif 825 tmp.pid = args->pid; 826 tmp.status = args->status; 827 tmp.options = args->options; 828 tmp.rusage = args->rusage; 829 830 if (error = wait4(p, &tmp)) 831 return error; 832 833 p->p_siglist &= ~sigmask(SIGCHLD); 834 835 if (args->status) { 836 if (error = copyin(args->status, &tmpstat, sizeof(int))) 837 return error; 838 if (WIFSIGNALED(tmpstat)) 839 tmpstat = (tmpstat & 0xffffff80) | 840 bsd_to_linux_signal[WTERMSIG(tmpstat)]; 841 else if (WIFSTOPPED(tmpstat)) 842 tmpstat = (tmpstat & 0xffff00ff) | 843 (bsd_to_linux_signal[WSTOPSIG(tmpstat)]<<8); 844 return copyout(&tmpstat, args->status, sizeof(int)); 845 } else 846 return 0; 847 } 848 849 int 850 linux_mknod(struct proc *p, struct linux_mknod_args *args) 851 { 852 caddr_t sg; 853 struct mknod_args bsd_mknod; 854 struct mkfifo_args bsd_mkfifo; 855 856 sg = stackgap_init(); 857 858 CHECKALTCREAT(p, &sg, args->path); 859 860 #ifdef DEBUG 861 printf("Linux-emul(%d): mknod(%s, %d, %d)\n", 862 p->p_pid, args->path, args->mode, args->dev); 863 #endif 864 865 if (args->mode & S_IFIFO) { 866 bsd_mkfifo.path = args->path; 867 bsd_mkfifo.mode = args->mode; 868 return mkfifo(p, &bsd_mkfifo); 869 } else { 870 bsd_mknod.path = args->path; 871 bsd_mknod.mode = args->mode; 872 bsd_mknod.dev = args->dev; 873 return mknod(p, &bsd_mknod); 874 } 875 } 876 877 /* 878 * UGH! This is just about the dumbest idea I've ever heard!! 879 */ 880 int 881 linux_personality(struct proc *p, struct linux_personality_args *args) 882 { 883 #ifdef DEBUG 884 printf("Linux-emul(%d): personality(%d)\n", 885 p->p_pid, args->per); 886 #endif 887 if (args->per != 0) 888 return EINVAL; 889 890 /* Yes Jim, it's still a Linux... */ 891 p->p_retval[0] = 0; 892 return 0; 893 } 894 895 /* 896 * Wrappers for get/setitimer for debugging.. 897 */ 898 int 899 linux_setitimer(struct proc *p, struct linux_setitimer_args *args) 900 { 901 struct setitimer_args bsa; 902 struct itimerval foo; 903 int error; 904 905 #ifdef DEBUG 906 printf("Linux-emul(%d): setitimer(%08x, %08x)\n", 907 p->p_pid, args->itv, args->oitv); 908 #endif 909 bsa.which = args->which; 910 bsa.itv = args->itv; 911 bsa.oitv = args->oitv; 912 if (args->itv) { 913 if ((error = copyin((caddr_t)args->itv, (caddr_t)&foo, 914 sizeof(foo)))) 915 return error; 916 #ifdef DEBUG 917 printf("setitimer: value: sec: %d, usec: %d\n", foo.it_value.tv_sec, foo.it_value.tv_usec); 918 printf("setitimer: interval: sec: %d, usec: %d\n", foo.it_interval.tv_sec, foo.it_interval.tv_usec); 919 #endif 920 } 921 return setitimer(p, &bsa); 922 } 923 924 int 925 linux_getitimer(struct proc *p, struct linux_getitimer_args *args) 926 { 927 struct getitimer_args bsa; 928 #ifdef DEBUG 929 printf("Linux-emul(%d): getitimer(%08x)\n", 930 p->p_pid, args->itv); 931 #endif 932 bsa.which = args->which; 933 bsa.itv = args->itv; 934 return getitimer(p, &bsa); 935 } 936 937 int 938 linux_iopl(struct proc *p, struct linux_iopl_args *args) 939 { 940 int error; 941 942 error = suser(p->p_ucred, &p->p_acflag); 943 if (error != 0) 944 return error; 945 if (securelevel > 0) 946 return EPERM; 947 p->p_md.md_regs->tf_eflags |= PSL_IOPL; 948 return 0; 949 } 950 951 int 952 linux_nice(struct proc *p, struct linux_nice_args *args) 953 { 954 struct setpriority_args bsd_args; 955 956 bsd_args.which = PRIO_PROCESS; 957 bsd_args.who = 0; /* current process */ 958 bsd_args.prio = args->inc; 959 return setpriority(p, &bsd_args); 960 } 961 962