|
|
1.1 ! root 1: /* (lgl- ! 2: * The information contained herein is a trade secret of Mark Williams ! 3: * Company, and is confidential information. It is provided under a ! 4: * license agreement, and may be copied or disclosed only under the ! 5: * terms of that agreement. Any reproduction or disclosure of this ! 6: * material without the express written authorization of Mark Williams ! 7: * Company or persuant to the license agreement is unlawful. ! 8: * ! 9: * COHERENT Version 2.3.37 ! 10: * Copyright (c) 1982, 1983, 1984. ! 11: * An unpublished work by Mark Williams Company, Chicago. ! 12: * All rights reserved. ! 13: -lgl) */ ! 14: /* ! 15: * coh.386/sys1.c ! 16: * ! 17: * Coherent. ! 18: * General system calls. ! 19: * ! 20: * Revised: Tue May 11 11:12:03 1993 CDT ! 21: */ ! 22: #include <sys/coherent.h> ! 23: #include <sys/acct.h> ! 24: #include <sys/con.h> ! 25: #include <sys/wait.h> ! 26: #include <errno.h> ! 27: #include <sys/proc.h> ! 28: #include <sys/sched.h> ! 29: #include <sys/seg.h> ! 30: #include <sys/stat.h> ! 31: #include <signal.h> ! 32: #include <sys/times.h> ! 33: ! 34: /* ! 35: * Send alarm signal to specified process - function timed by ualarm() ! 36: */ ! 37: sigalrm(pp) ! 38: register PROC * pp; ! 39: { ! 40: sendsig(SIGALRM, pp); ! 41: } ! 42: ! 43: /* ! 44: * Send a SIGALARM signal in `n' seconds. ! 45: */ ! 46: ualarm(n) ! 47: unsigned n; ! 48: { ! 49: register PROC * pp = SELF; ! 50: register unsigned s; ! 51: ! 52: /* ! 53: * Calculate time left before current alarm timeout. ! 54: */ ! 55: s = 0; ! 56: if (pp->p_alrmtim.t_last != NULL) ! 57: s = (pp->p_alrmtim.t_lbolt - lbolt + HZ - 1) / HZ; ! 58: ! 59: /* ! 60: * Cancel previous alarm [if any], start new alarm [if n != 0]. ! 61: */ ! 62: timeout2(&pp->p_alrmtim, (long) n * HZ, sigalrm, pp); ! 63: ! 64: /* ! 65: * Return time left before previous alarm timeout. ! 66: */ ! 67: return(s); ! 68: } ! 69: ! 70: ! 71: /* ! 72: * Change the size of our data segment. ! 73: */ ! 74: char * ! 75: ubrk(cp) ! 76: caddr_t cp; ! 77: { ! 78: register SEG *sp; ! 79: register caddr_t sb; ! 80: register SR *stack_sr; ! 81: caddr_t top_of_stack; ! 82: ! 83: T_HAL(0x8000, printf("%s:ubrk(%x) ", u.u_comm, cp)); ! 84: ! 85: /* ! 86: * Pick up the segment handle for our data segment. ! 87: */ ! 88: sp = SELF->p_segp[SIPDATA]; ! 89: ! 90: /* ! 91: * Extract the starting virtual address for our data segment, ! 92: * as it is currently mapped into the memory space. ! 93: */ ! 94: sb = u.u_segl[SIPDATA].sr_base; ! 95: ! 96: /* ! 97: * We can not move the top of the data segment below the ! 98: * start of the data segment. ! 99: */ ! 100: if (cp < sb) { ! 101: SET_U_ERROR(ENOMEM, ! 102: "Requested brk address is below start of data segment."); ! 103: return 0; ! 104: } ! 105: ! 106: /* ! 107: * Would the request cause a collision with the stack segment? ! 108: * ! 109: * Since the stack grows downward, its top is below its base :-). ! 110: */ ! 111: stack_sr = &u.u_segl[SISTACK]; ! 112: top_of_stack = (stack_sr->sr_base) - (stack_sr->sr_size); ! 113: ! 114: if (btoc(cp) >= btoc(top_of_stack)) { ! 115: SET_U_ERROR(ENOMEM, ! 116: "Requested brk address would collide with stack segment."); ! 117: return 0; ! 118: } ! 119: ! 120: /* ! 121: * Attempt to establish the segment with the newly requested size. ! 122: */ ! 123: segsize(sp, (cp - sb)); ! 124: ! 125: /* ! 126: * Be sure to return the true new top of data segment. ! 127: */ ! 128: sb += sp->s_size; ! 129: ! 130: T_HAL(0x8000, printf("=%x ", sb)); ! 131: return sb; ! 132: } ! 133: ! 134: /* ! 135: * Execute a l.out. ! 136: */ ! 137: uexece(np, argp, envp) ! 138: char *np; ! 139: char *argp[]; ! 140: char *envp[]; ! 141: { ! 142: pexece(np, argp, envp); ! 143: } ! 144: ! 145: /* ! 146: * Exit. ! 147: */ ! 148: uexit(s) ! 149: { ! 150: pexit(s<<8); ! 151: } ! 152: ! 153: /* ! 154: * Fork. ! 155: */ ! 156: ufork() ! 157: { ! 158: return (pfork()); ! 159: } ! 160: ! 161: /* ! 162: * Get group id. ! 163: * Get effective group id. ! 164: */ ! 165: ugetgid() ! 166: { ! 167: u.u_rval2 = u.u_gid; ! 168: return u.u_rgid; ! 169: } ! 170: ! 171: /* ! 172: * Get user id. ! 173: * Get effective user id. ! 174: */ ! 175: ugetuid() ! 176: { ! 177: u.u_rval2 = u.u_uid; ! 178: return u.u_ruid; ! 179: } ! 180: ! 181: /* ! 182: * Get process group. ! 183: * Set the process group. ! 184: * ! 185: * This is System V type setpgrp(). ! 186: * Set process group equal to process id (make process its own group leader). ! 187: * If process was NOT already a group leader, lose its controlling terminal. ! 188: */ ! 189: upgrp(fl) ! 190: { ! 191: register PROC * pp = SELF; ! 192: ! 193: if (fl) { ! 194: if (pp->p_group != pp->p_pid) ! 195: pp->p_ttdev = NODEV; ! 196: pp->p_group = pp->p_pid; ! 197: } ! 198: return pp->p_group; ! 199: } ! 200: ! 201: /* ! 202: * Get process id. ! 203: */ ! 204: ugetpid() ! 205: { ! 206: register PROC *pp = SELF; ! 207: ! 208: u.u_rval2 = pp->p_ppid; ! 209: return pp->p_pid; ! 210: } ! 211: ! 212: /* ! 213: * Send the signal `sig' to the process with id `pid'. ! 214: */ ! 215: ukill(pid, sig) ! 216: int pid; ! 217: register unsigned sig; ! 218: { ! 219: register PROC *pp; ! 220: register int sigflag; ! 221: ! 222: if (sig > NSIG) { ! 223: u.u_error = EINVAL; ! 224: return; ! 225: } ! 226: sigflag = 0; ! 227: lock(pnxgate); ! 228: if (pid > 0) { /* send to matching process */ ! 229: for (pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw) { ! 230: if (pp->p_state == PSDEAD) ! 231: continue; ! 232: if (pp->p_pid == pid) { ! 233: sigflag = 1; ! 234: if (sig) { ! 235: if (sigperm(sig, pp)) ! 236: sendsig(sig, pp); ! 237: else ! 238: u.u_error = EPERM; ! 239: } ! 240: break; ! 241: } ! 242: } ! 243: } ! 244: else if (pid < -1) { ! 245: pid = -pid; ! 246: for (pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw) { ! 247: if (pp->p_state == PSDEAD) ! 248: continue; ! 249: if (pp->p_group == pid) { ! 250: sigflag = 1; ! 251: if (sig) { ! 252: if (sigperm(sig, pp)) ! 253: sendsig(sig,pp); ! 254: else ! 255: u.u_error = EPERM; ! 256: } ! 257: } ! 258: } ! 259: } ! 260: else if (pid == 0) { ! 261: for (pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw) { ! 262: if (pp->p_state == PSDEAD) ! 263: continue; ! 264: if (pp->p_group == SELF->p_group) { ! 265: sigflag = 1; ! 266: if (sig && sigperm(sig, pp)) ! 267: sendsig(sig, pp); ! 268: } ! 269: } ! 270: } ! 271: else if (pid == -1) { ! 272: for (pp=procq.p_nforw; pp != &procq; pp=pp->p_nforw) { ! 273: if (pp->p_state == PSDEAD) ! 274: continue; ! 275: if (pp->p_pid == 0) ! 276: continue; ! 277: if (pp->p_pid == 1) ! 278: continue; ! 279: if (pp->p_flags & PFKERN) ! 280: continue; ! 281: sigflag = 1; ! 282: if (sig && super()) ! 283: sendsig(sig, pp); ! 284: } ! 285: } ! 286: unlock(pnxgate); ! 287: if (sigflag == 0) ! 288: u.u_error = ESRCH; ! 289: return 0; ! 290: } ! 291: ! 292: /* ! 293: * See if we have permission to send the signal, `sig' to the process, `pp'. ! 294: */ ! 295: sigperm(sig, pp) ! 296: register PROC *pp; ! 297: { ! 298: if (u.u_uid == pp->p_uid) ! 299: return (1); ! 300: if (u.u_ruid == pp->p_ruid) { ! 301: if (sig == SIGHUP ! 302: || sig == SIGINT ! 303: || sig == SIGQUIT ! 304: || sig == SIGTERM) ! 305: return (1); ! 306: } ! 307: if (u.u_uid == 0) { ! 308: u.u_flag |= ASU; ! 309: return (1); ! 310: } ! 311: return 0; ! 312: } ! 313: ! 314: /* ! 315: * Lock a process in core. ! 316: */ ! 317: ulock(f) ! 318: { ! 319: if (super() == 0) ! 320: return; ! 321: if (f) ! 322: SELF->p_flags |= PFLOCK; ! 323: else ! 324: SELF->p_flags &= ~PFLOCK; ! 325: return 0; ! 326: } ! 327: ! 328: /* ! 329: * Change priority by the given increment. ! 330: */ ! 331: unice(n) ! 332: register int n; ! 333: { ! 334: n += SELF->p_nice; ! 335: if (n < MINNICE) ! 336: n = MINNICE; ! 337: if (n > MAXNICE) ! 338: n = MAXNICE; ! 339: if (n<SELF->p_nice && super()==0) ! 340: return; ! 341: SELF->p_nice = n; ! 342: return 0; ! 343: } ! 344: ! 345: /* ! 346: * Non existant system call. ! 347: */ ! 348: unone() ! 349: { ! 350: u.u_error = EFAULT; ! 351: } ! 352: ! 353: /* ! 354: * Null system call. ! 355: */ ! 356: unull() ! 357: { ! 358: } ! 359: ! 360: /* ! 361: * Pause. Go to sleep on a channel that nobody will wakeup so that only ! 362: * signals will wake us up. ! 363: */ ! 364: upause() ! 365: { ! 366: x_sleep((char *)&u, prilo, slpriSigLjmp, "pause"); ! 367: } ! 368: ! 369: /* ! 370: * Start/stop profiling. ! 371: * ! 372: * buff: address in user data of an array of shorts ! 373: * bufsiz: number of bytes in the area at buff ! 374: * offset: address in user text of start of profiling area ! 375: * scale: 0 or 1 - turn off profiling ! 376: * other - treat as 16 bit scale factor ! 377: * ! 378: * For purposes of compatibility with System 5, scale values work as follows: ! 379: * 0xFFFF profile buffer is same length as text being profiled. ! 380: * 0x7FFF profile buffer is half as long as text being profiled. ! 381: * 0x4000 profile buffer is one fourth as long as text profiled. ! 382: * (each short in the buffer covers 8 bytes of text) ! 383: * ... ... ! 384: * 0x0002 each short in the buffer covers 64K bytes of text. ! 385: * ! 386: * Values 0xFFFF and 0x7FFF are used, for historical reasons, when 0x10000 ! 387: * and 0x8000, respectively, should be used. To clean up the ensuing ! 388: * arithmetic, there is an upward rounding kluge below. ! 389: * ! 390: * Each clock interrupt, take (pc - offset) * scale * (2**-16) as a byte ! 391: * offset into pbase. Add 1 to the short at or below the given address ! 392: * when profiling. ! 393: */ ! 394: uprofil(buff, bufsiz, offset, scale) ! 395: short * buff; ! 396: int bufsiz, offset, scale; ! 397: { ! 398: u.u_pbase = buff; ! 399: u.u_pbend = buff + bufsiz; ! 400: u.u_pofft = offset; ! 401: u.u_pscale = scale & 0xffff; /* scale is really unsigned short */ ! 402: ! 403: /* round up kluge - see above */ ! 404: if ((scale & 0xfff) == 0xfff) ! 405: u.u_pscale++; ! 406: } ! 407: ! 408: /* ! 409: * Process trace. ! 410: */ ! 411: uptrace(req, pid, add, data) ! 412: int *add; ! 413: { ! 414: int ret; ! 415: ! 416: #ifdef TRACER ! 417: int readChild = 0; /* for debug, true if reading child memory */ ! 418: ! 419: if (t_hal & 0x10000) { ! 420: switch(req) { ! 421: case 0: /* init called by child */ ! 422: printf("PSetup: child=%d ", SELF->p_pid); ! 423: break; ! 424: case 1: /* parent reads child text */ ! 425: printf("PRdT: add=%x ", add); ! 426: readChild = 1; ! 427: break; ! 428: case 2: /* parent reads child data */ ! 429: printf("PRdD: add=%x ", add); ! 430: readChild = 1; ! 431: break; ! 432: case 3: /* parent reads child u area */ ! 433: printf("PRdU: add=%x ", add); ! 434: readChild = 1; ! 435: break; ! 436: case 4: /* parent writes child text */ ! 437: printf("PWrT: add=%x data=%x ", add, data); ! 438: break; ! 439: case 5: /* parent writes child data */ ! 440: printf("PWrD: add=%x data=%x ", add, data); ! 441: break; ! 442: case 6: /* parent writes child u area */ ! 443: printf("PWrU: add=%x data=%x ", add, data); ! 444: break; ! 445: case 7: /* resume child, maybe fake signal to child */ ! 446: printf("PResume: sig=%d ", data); ! 447: break; ! 448: case 8: /* terminate child */ ! 449: printf("PTerm: pid=%d ", pid); ! 450: break; ! 451: case 9: /* single-step child, maybe fake signal to child */ ! 452: printf("PSStp: sig=%d ", data); ! 453: break; ! 454: } ! 455: } ! 456: #endif ! 457: ! 458: if (req == 0) { ! 459: SELF->p_flags |= PFTRAC; ! 460: ret = 0; ! 461: } else ! 462: ret = ptset(req, pid, add, data); ! 463: ! 464: #ifdef TRACER ! 465: if (t_hal & 0x10000) { ! 466: if (readChild) ! 467: printf("data=%x ", ret); ! 468: } ! 469: #endif ! 470: ! 471: return ret; ! 472: } ! 473: ! 474: /* ! 475: * Set group id. ! 476: * ! 477: * As in SVID issue 2: ! 478: * ! 479: * if effective gid is superuser ! 480: * set real, effective, and saved effective gid to argument "gid" ! 481: * else if real gid is same as "gid" ! 482: * set effective gid to "gid" ! 483: * else if saved effective gid is same as "gid" ! 484: * set effective gid to "gid" ! 485: */ ! 486: usetgid(gid) ! 487: register int gid; ! 488: { ! 489: if (super()) { ! 490: u.u_gid = u.u_rgid = u.u_egid = gid; ! 491: SELF->p_rgid = gid; ! 492: } else { ! 493: u.u_error = 0; /* super() sets u_error when it fails */ ! 494: if (u.u_rgid == gid || u.u_egid == gid) { ! 495: u.u_gid = gid; ! 496: } else { ! 497: SET_U_ERROR(EPERM, "Illegal gid"); ! 498: } ! 499: } ! 500: return 0; ! 501: } ! 502: ! 503: /* ! 504: * Set user id. ! 505: * ! 506: * As in SVID issue 2: ! 507: * ! 508: * if effective uid is superuser ! 509: * set real, effective, and saved effective uid to argument "uid" ! 510: * else if real uid is same as "uid" ! 511: * set effective uid to "uid" ! 512: * else if saved effective uid is same as "uid" ! 513: * set effective uid to "uid" ! 514: */ ! 515: usetuid(uid) ! 516: register int uid; ! 517: { ! 518: if (super()) { ! 519: u.u_uid = u.u_ruid = u.u_euid = uid; ! 520: SELF->p_uid = SELF->p_ruid = uid; ! 521: } else { ! 522: u.u_error = 0; /* super() sets u_error when it fails */ ! 523: if (u.u_ruid == uid || u.u_euid == uid) { ! 524: SELF->p_uid = u.u_uid = uid; ! 525: } else { ! 526: SET_U_ERROR(EPERM, "Illegal uid"); ! 527: } ! 528: } ! 529: return 0; ! 530: } ! 531: ! 532: /* ! 533: * Load a device driver. ! 534: */ ! 535: usload(np) ! 536: char *np; ! 537: { ! 538: return pload(np); ! 539: } ! 540: ! 541: /* ! 542: * Set time and date. ! 543: * ! 544: * Unlike the libc interface, this routine expects a time_t value ! 545: * as an arg, not a time_t pointer. ! 546: */ ! 547: ustime(tp) ! 548: time_t tp; ! 549: { ! 550: register int s; ! 551: ! 552: if (super() == 0) { ! 553: return; ! 554: } ! 555: s = sphi(); ! 556: ukcopy(&tp, &timer.t_time, sizeof(tp)); ! 557: spl(s); ! 558: return 0; ! 559: } ! 560: ! 561: /* ! 562: * Return process times. ! 563: */ ! 564: utimes(tp) ! 565: struct tms *tp; ! 566: { ! 567: register PROC *pp; ! 568: struct tms tbuffer; ! 569: ! 570: if (tp) { ! 571: pp = SELF; ! 572: tbuffer.tms_utime = pp->p_utime; ! 573: tbuffer.tms_stime = pp->p_stime; ! 574: tbuffer.tms_cutime = pp->p_cutime; ! 575: tbuffer.tms_cstime = pp->p_cstime; ! 576: kucopyS(&tbuffer, tp, sizeof(tbuffer)); ! 577: } ! 578: return lbolt; ! 579: } ! 580: ! 581: /* ! 582: * Unload a device driver. ! 583: */ ! 584: usuload(m) ! 585: register int m; ! 586: { ! 587: if (super() == 0) ! 588: return; ! 589: puload(m); ! 590: return 0; ! 591: } ! 592: ! 593: /* ! 594: * Wait for a child to terminate. ! 595: * ! 596: * iBCS2 says the same system call number is wait() and waitpid(), the ! 597: * distinction being in how the psw is set on entry. ! 598: * ! 599: * iBCS2 fails to mention that when wait() or waitpid() report status ! 600: * by writing into the pointer supplied, the status is put into %edx by ! 601: * the kernel, and moved from there into user space by the function in ! 602: * libc.a. uwait() and uwaitpid() specify a value for %edx by writing ! 603: * to u.u_rval2. ! 604: * ! 605: * Do wait() unless (ZF|PF|SF|OF) (=WPMASK) are set in psw. ! 606: */ ! 607: #define WPMASK 0x8C4 ! 608: ! 609: uwait(arg1, arg2, arg3) ! 610: { ! 611: register PROC *pp; ! 612: register PROC *ppp; ! 613: register PROC *cpp; ! 614: register int pid; ! 615: ! 616: if ((u.u_regl[EFL] & WPMASK) == WPMASK) ! 617: return uwaitpid(arg1, arg2, arg3); ! 618: ! 619: /* Wait for a child to stop or die. */ ! 620: T_HAL(8, printf("[%d]waits ", SELF->p_pid)); ! 621: ppp = SELF; ! 622: for (;;) { ! 623: int x_s; ! 624: ! 625: /* Look at all processes. */ ! 626: lock(pnxgate); ! 627: cpp = NULL; ! 628: pp = &procq; ! 629: while ((pp=pp->p_nforw) != &procq) { ! 630: ! 631: /* Ignore the current process. */ ! 632: if (pp == ppp) ! 633: continue; ! 634: /* ! 635: * Ignore processes that aren't children of the ! 636: * current one. ! 637: */ ! 638: if (pp->p_ppid != ppp->p_pid) ! 639: continue; ! 640: if (pp->p_flags&PFSTOP) ! 641: continue; ! 642: ! 643: /* Here is a child that hit a breakpoint. */ ! 644: if (pp->p_flags&PFWAIT) { ! 645: int work; /* virtual click number */ ! 646: int childUseg; /* system global addr */ ! 647: UPROC * uprc; ! 648: SEG * sp; ! 649: ! 650: pp->p_flags &= ~PFWAIT; ! 651: pp->p_flags |= PFSTOP; ! 652: ! 653: /* fetch u.u_signo from the child */ ! 654: ! 655: /* Find u area for child process pp */ ! 656: sp = pp->p_segp[SIUSERP]; ! 657: childUseg = MAPIO(sp->s_vmem, U_OFFSET); ! 658: work = workAlloc(); ! 659: ptable1_v[work] = ! 660: sysmem.u.pbase[btocrd(childUseg)] | SEG_RW; ! 661: mmuupd(); ! 662: uprc = (UPROC *) (ctob(work) + U_OFFSET); ! 663: u.u_rval2 = ((uprc->u_signo)<<8) | 0177; ! 664: workFree(work); ! 665: ! 666: unlock(pnxgate); ! 667: T_HAL(8, printf("[%d]ends waiting, %d stopped ", ! 668: SELF->p_pid, pid)); ! 669: return pp->p_pid; ! 670: } ! 671: if (pp->p_state == PSDEAD) { ! 672: ppp->p_cutime += pp->p_utime + pp->p_cutime; ! 673: ppp->p_cstime += pp->p_stime + pp->p_cstime; ! 674: u.u_rval2 = pp->p_exit; ! 675: pid = pp->p_pid; ! 676: unlock(pnxgate); ! 677: relproc(pp); ! 678: if (SIG_BIT(SIGCLD) & ppp->p_isig) ! 679: continue; ! 680: else { ! 681: T_HAL(8, printf("[%d]ends waiting," ! 682: " %d died ", SELF->p_pid, pid)); ! 683: return pid; ! 684: } ! 685: } ! 686: cpp = pp; ! 687: } ! 688: unlock(pnxgate); ! 689: if (cpp == NULL) { ! 690: T_HAL(8, printf("[%d]ends waiting, no children ", ! 691: SELF->p_pid)); ! 692: u.u_error = ECHILD; ! 693: return; ! 694: } ! 695: x_s = x_sleep((char *)ppp, prilo, slpriSigLjmp, "wait"); ! 696: /* Wait for a child to terminate. */ ! 697: } ! 698: } ! 699: ! 700: /* ! 701: * waitpid() and wait() share the same system call number under BCS. ! 702: * ! 703: * pid argument: ! 704: * > 0 wait for child whose process matches pid ! 705: * = 0 wait for any child in current process group ! 706: * = -1 wait for any child - same as wait() ! 707: * < -1 wait for any child in group given by -pid ! 708: * ! 709: * The only waitpid() options supported are WNOHANG and WUNTRACED. ! 710: * ! 711: */ ! 712: int ! 713: uwaitpid(opid, stat_loc, options) ! 714: register pid_t opid; ! 715: int *stat_loc, options; ! 716: { ! 717: register PROC *pp; ! 718: register PROC *ppp; ! 719: register PROC *cpp; ! 720: register int pid; ! 721: ! 722: if (options & WUNTRACED) { ! 723: printf("waitpid(%d,%d, WUNTRACED): unsupported\n", opid, ! 724: stat_loc); ! 725: u.u_error = EINVAL; ! 726: return; ! 727: } ! 728: ! 729: /* Wait for a child to stop or die. */ ! 730: ppp = SELF; ! 731: for (;;) { ! 732: int x_s; ! 733: ! 734: /* Look at all processes. */ ! 735: lock(pnxgate); ! 736: cpp = NULL; ! 737: pp = &procq; ! 738: while ((pp=pp->p_nforw) != &procq) { ! 739: ! 740: /* Ignore the current process. */ ! 741: if (pp == ppp) ! 742: continue; ! 743: /* ! 744: * Ignore processes that aren't children of the ! 745: * current one. ! 746: */ ! 747: if (pp->p_ppid != ppp->p_pid) ! 748: continue; ! 749: ! 750: if (pp->p_flags&PFSTOP) ! 751: continue; ! 752: ! 753: /* If opid == 0 we want to match gids */ ! 754: if ((opid == 0) && (pp->p_group != ppp->p_group)) ! 755: continue; ! 756: ! 757: /* If opid>0, want to match opid to child pid */ ! 758: else if ((opid > 0) && (opid != pp->p_pid)) ! 759: continue; ! 760: ! 761: /* If opid<-1, want to match -opid to child gid */ ! 762: else if ((opid < -1) && ((-opid) != pp->p_group)) ! 763: continue; ! 764: ! 765: /* if opid == -1, then any child is acceptable */ ! 766: ! 767: /* Here is an acceptable child that hit a breakpoint. */ ! 768: if (pp->p_flags&PFWAIT) { ! 769: int work; /* virtual click number */ ! 770: int childUseg; /* system global addr */ ! 771: UPROC * uprc; ! 772: SEG * sp; ! 773: ! 774: pp->p_flags &= ~PFWAIT; ! 775: pp->p_flags |= PFSTOP; ! 776: ! 777: /* fetch u.u_signo from the child */ ! 778: ! 779: /* Find u area for child process pp */ ! 780: sp = pp->p_segp[SIUSERP]; ! 781: childUseg = MAPIO(sp->s_vmem, U_OFFSET); ! 782: work = workAlloc(); ! 783: ptable1_v[work] = ! 784: sysmem.u.pbase[btocrd(childUseg)] | SEG_RW; ! 785: mmuupd(); ! 786: uprc = (UPROC *) (ctob(work) + U_OFFSET); ! 787: u.u_rval2 = ((uprc->u_signo)<<8) | 0177; ! 788: workFree(work); ! 789: ! 790: unlock(pnxgate); ! 791: return pp->p_pid; ! 792: } ! 793: ! 794: /* Here is an acceptable child that is a zombie. */ ! 795: if (pp->p_state == PSDEAD) { ! 796: ppp->p_cutime += pp->p_utime + pp->p_cutime; ! 797: ppp->p_cstime += pp->p_stime + pp->p_cstime; ! 798: u.u_rval2 = pp->p_exit; ! 799: pid = pp->p_pid; ! 800: unlock(pnxgate); ! 801: relproc(pp); ! 802: if (SIG_BIT(SIGCLD) & ppp->p_isig) ! 803: continue; ! 804: else { ! 805: return pid; ! 806: } ! 807: } ! 808: cpp = pp; ! 809: } ! 810: unlock(pnxgate); ! 811: if (cpp == NULL) { ! 812: u.u_error = ECHILD; ! 813: return; ! 814: } ! 815: ! 816: if (options & WNOHANG) { ! 817: u.u_rval2 = 0; ! 818: return 0; ! 819: } ! 820: else ! 821: /* Wait for a child to terminate. */ ! 822: x_s = x_sleep((char *)ppp, prilo, slpriSigLjmp, ! 823: "waitpid"); ! 824: } ! 825: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.