1: /* 2: * SCCS id @(#)syslocal.c 2.1 (Berkeley) 9/4/83 3: */ 4: 5: #include "param.h" 6: #include <sys/dir.h> 7: #include <sys/proc.h> 8: #include <sys/seg.h> 9: #include <sys/user.h> 10: #include <sys/systm.h> 11: #include <sys/inode.h> 12: #include <sys/ino.h> 13: #include <sys/file.h> 14: #include <sys/conf.h> 15: #ifdef UCB_QUOTAS 16: #include <sys/quota.h> 17: #include <sys/qstat.h> 18: #include <sys/buf.h> 19: #endif 20: #ifdef UCB_VHANGUP 21: #include <sys/tty.h> 22: #endif 23: #include <sys/autoconfig.h> 24: #ifdef UCB_NET 25: #include <sys/mbuf.h> 26: #include <sys/protosw.h> 27: #include <sys/socket.h> 28: #include <sys/socketvar.h> 29: #include <sys/ubavar.h> 30: #include <sys/map.h> 31: #include "../net/if.h" 32: #include "../net/in_systm.h" 33: #endif 34: 35: /* 36: * These routines implement local system calls 37: */ 38: 39: /* 40: * nostk -- Set up the process to have no stack segment. 41: * The process is responsible for the management 42: * of its own stack, and can thus use the full 43: * 64k byte address space. 44: */ 45: 46: nostk() 47: { 48: #ifndef VIRUS_VFORK 49: register size; 50: 51: size = u.u_procp->p_size - u.u_ssize; 52: if(estabur(u.u_tsize, u.u_dsize, 0, u.u_sep, RO)) 53: return; 54: u.u_ssize = 0; 55: expand(size); 56: #else 57: if(estabur(u.u_tsize, u.u_dsize, 0, u.u_sep, RO)) 58: return; 59: expand(0,S_STACK); 60: u.u_ssize = 0; 61: #endif 62: } 63: 64: #if !defined(NONSEPARATE) && defined(NONFP) 65: /* 66: * fetchi -- fetch from user I space 67: * required because the mfpi instruction 68: * does not work if current and previous 69: * are both user. 70: */ 71: 72: fetchi() 73: { 74: struct a { 75: caddr_t iaddr; 76: }; 77: 78: u.u_r.r_val1 = fuiword(((struct a *)u.u_ap)->iaddr); 79: } 80: #endif 81: 82: #ifdef UCB_QUOTAS 83: /* 84: * quota -- establish or change the quota on a directory 85: */ 86: quota() 87: { 88: register struct inode *ip; 89: register struct a { 90: char *name; 91: daddr_t current; 92: daddr_t max; 93: } *uap; 94: 95: if (!suser()) 96: return; 97: #ifndef UCB_SYMLINKS 98: ip = namei(uchar, LOOKUP); 99: #else 100: ip = namei(uchar, LOOKUP, 1); 101: #endif 102: if (ip == NULL) 103: return; 104: else 105: if ((ip->i_mode & IFMT) != IFQUOT) { 106: u.u_error = EACCES; 107: return; 108: } 109: /* 110: * Round the current up to be a multiple of the 111: * counting unit. 112: */ 113: uap = (struct a *) u.u_ap; 114: #if QCOUNT==2 115: ip->i_un.i_qused = ((uap->current + QCOUNT - 1) >> 1) << 1; 116: #else 117: ip->i_un.i_qused = (uap->current + QCOUNT - 1) / QCOUNT * QCOUNT; 118: #endif 119: ip->i_un.i_qmax = uap->max; 120: ip->i_flag |= IUPD|IACC; 121: iput(ip); 122: } 123: #endif 124: 125: #ifdef UCB_QUOTAS 126: /* 127: * the qfstat system call. 128: */ 129: qfstat() 130: { 131: register struct file *fp; 132: register struct a { 133: int fdes; 134: struct qstat *sb; 135: } *uap; 136: 137: uap = (struct a *) u.u_ap; 138: fp = getf(uap->fdes); 139: if(fp == NULL) 140: return; 141: qstat1(fp->f_inode, uap->sb); 142: } 143: 144: /* 145: * the qstat system call. 146: */ 147: qstat() 148: { 149: register struct inode *ip; 150: struct a { 151: char *fname; 152: struct qstat *sb; 153: }; 154: 155: #ifndef UCB_SYMLINKS 156: ip = namei(uchar, LOOKUP); 157: #else 158: ip = namei(uchar, LOOKUP, 0); 159: #endif 160: if(ip == (struct inode *) NULL) 161: return; 162: qstat1(ip, ((struct a *) u.u_ap)->sb); 163: iput(ip); 164: } 165: 166: /* 167: * The basic routine for qfstat and qstat: 168: * get the inode and pass all of it back. 169: */ 170: qstat1(ip, ub) 171: register struct inode *ip; 172: struct inode *ub; 173: { 174: register struct dinode *dp; 175: register struct buf *bp; 176: struct qstat qs, *qp; 177: 178: #ifdef UCB_FSFIX 179: iupdat(ip, &time, &time, 0); 180: #else 181: iupdat(ip, &time, &time); 182: #endif 183: 184: /* 185: * first copy from inode table 186: */ 187: qp = &qs; 188: *((struct inode *) qp) = *ip; 189: 190: /* 191: * next the dates in the disk 192: */ 193: bp = bread(ip->i_dev, itod(ip->i_number)); 194: dp = (struct dinode *) mapin(bp); 195: dp += itoo(ip->i_number); 196: qs.qs_atime = dp->di_atime; 197: qs.qs_mtime = dp->di_mtime; 198: qs.qs_ctime = dp->di_ctime; 199: mapout(bp); 200: brelse(bp); 201: if (copyout((caddr_t) & qs, (caddr_t) ub, sizeof qs) < 0) 202: u.u_error = EFAULT; 203: } 204: #endif 205: 206: #ifndef MENLO_JCL 207: /* 208: * killpg -- send all processes the specified 209: * process group the given signal. 210: */ 211: 212: killpg() 213: { 214: struct a { 215: int pgrp; 216: int sig; 217: }; 218: 219: killgrp(((struct a *) u.u_ap)->pgrp, ((struct a *) u.u_ap)->sig, 0); 220: } 221: #endif 222: 223: #ifdef UCB_SUBM 224: /* 225: * killbkg -- signal processes in the specified group that 226: * have not been blessed by a submit call 227: */ 228: 229: killbkg() 230: { 231: struct a { 232: int pgrp; 233: int sig; 234: }; 235: 236: killgrp(((struct a *) u.u_ap)->pgrp, ((struct a *) u.u_ap)->sig, SSUBM); 237: } 238: #endif 239: 240: #if defined(UCB_SUBM) || !defined(MENLO_JCL) 241: /* 242: * common code for killpg and killbkg 243: * 244: * if mask is non-zero, send signal 245: * only to processes whose (p_flag & mask) 246: * is zero. 247: */ 248: 249: killgrp(pgrp, sig, mask) 250: register pgrp; 251: register sig; 252: { 253: register struct proc *p; 254: int count; 255: 256: if(!suser()) 257: return; 258: count = 0; 259: for(p = &proc[2]; p <= maxproc; p++) { 260: if(p->p_stat == SZOMB || p->p_pgrp != pgrp) 261: continue; 262: 263: /* 264: * include following if suser is immune 265: * 266: if(p->p_uid == 0) 267: continue; 268: * 269: */ 270: 271: if(mask && (mask & p->p_flag)) { 272: continue; 273: } 274: count++; 275: psignal(p, sig); 276: } 277: if(count == 0) 278: u.u_error = ESRCH; 279: } 280: #endif 281: 282: #ifdef UCB_SUBM 283: /* 284: * submit -- mark the specified process to allow execution after logout 285: */ 286: 287: submit() 288: { 289: register struct proc *p; 290: #ifndef MENLO_JCL 291: register group; 292: #endif 293: register pid; 294: struct a { 295: int pid; 296: }; 297: 298: pid = ((struct a *) u.u_ap)->pid; 299: #ifndef MENLO_JCL 300: group = u.u_procp->p_pgrp; 301: #endif 302: for(p = &proc[2]; p <= maxproc; p++) 303: if(p->p_pid == pid) { 304: #ifndef MENLO_JCL 305: if(p->p_pgrp != group && !suser()) 306: return; 307: #else 308: if (p->p_uid != u.u_uid && !suser()) 309: return; 310: #endif 311: p->p_flag |= SSUBM; 312: return; 313: } 314: u.u_error = ESRCH; 315: } 316: #endif UCB_SUBM 317: 318: #ifdef UCB_LOGIN 319: /* 320: * login -- mark a process as a login process, 321: * and record accounting information. 322: */ 323: login() 324: { 325: register i; 326: struct a { 327: int tslot; 328: char crn[4]; 329: }; 330: 331: if (suser()) { 332: u.u_login = ((struct a *) u.u_ap)->tslot; 333: for (i = 0; i < sizeof u.u_crn; i++) 334: u.u_crn[i] = ((struct a *) u.u_ap)->crn[i]; 335: } 336: } 337: #endif 338: 339: #ifndef MENLO_JCL 340: /* 341: * establish a new process group 342: */ 343: setpgrp() 344: { 345: register struct proc *pp; 346: 347: if (suser()) { 348: pp = u.u_procp; 349: pp->p_pgrp = pp->p_pid; 350: } 351: } 352: #endif 353: 354: #ifdef UCB_LOAD 355: /* 356: * gldav -- get the load averages 357: */ 358: gldav() 359: { 360: extern short avenrun[]; 361: struct a { 362: short *ptr; 363: }; 364: 365: if (copyout( (caddr_t) avenrun, (caddr_t) (((struct a *) u.u_ap)->ptr), 366: 3 * sizeof(short)) < 0) 367: u.u_error = EFAULT; 368: } 369: #endif 370: 371: #ifndef NONFP 372: /* 373: * fperr - return floating point error registers 374: */ 375: fperr() 376: { 377: u.u_r.r_val1 = u.u_fperr.f_fec; 378: u.u_r.r_val2 = u.u_fperr.f_fea; 379: } 380: #endif 381: 382: #ifdef UCB_VHANGUP 383: /* 384: * Revoke access to the current tty by all processes. 385: * Used only by the super-user in init 386: * to give ``clean'' terminals at login. 387: */ 388: vhangup() 389: { 390: if (suser()) { 391: if (u.u_ttyp == NULL) 392: return; 393: forceclose(u.u_ttyd); 394: if ((u.u_ttyp->t_state) & ISOPEN) 395: gsignal(u.u_ttyp->t_pgrp, SIGHUP); 396: } 397: } 398: 399: forceclose(dev) 400: dev_t dev; 401: { 402: register struct file *fp; 403: register struct inode *ip; 404: register int n = 0; 405: 406: for (fp = file; fp < fileNFILE; fp++) { 407: #ifdef UCB_NET 408: if (fp->f_flag & FSOCKET) 409: continue; 410: #endif 411: if (fp->f_count == 0) 412: continue; 413: ip = fp->f_inode; 414: if ((ip->i_mode & IFMT) != IFCHR) 415: continue; 416: if (ip->i_un.i_rdev != dev) 417: continue; 418: fp->f_flag &= ~(FREAD | FWRITE); 419: n++; 420: } 421: return (n); 422: } 423: #endif UCB_VHANGUP 424: 425: #ifdef UCB_RENICE 426: /* 427: * renice -- change the nice value of a process 428: */ 429: renice() 430: { 431: register struct proc *p; 432: register struct a { 433: int pid; 434: int nice; 435: } *uap; 436: 437: uap = (struct a *) u.u_ap; 438: 439: for (p = &proc[2]; p <= maxproc; p++) 440: if (p->p_pid == uap->pid) { 441: if (suser()) { 442: u.u_r.r_val1 = p->p_nice; 443: p->p_nice = MAX(uap->nice, -127); 444: } 445: else if (p->p_uid == u.u_uid) { 446: u.u_r.r_val1 = p->p_nice; 447: p->p_nice = MIN(MAX(p->p_nice, uap->nice), 127); 448: u.u_error = 0; 449: } 450: return; 451: } 452: u.u_error = ESRCH; 453: } 454: #endif UCB_RENICE 455: 456: int conf_int = CONF_MAGIC; /* Used to pass result from int service to probe() */ 457: 458: /* 459: * Routine to allow user level code to call various internal 460: * functions; in configuration it calls for the probe and 461: * attach functions of the various drivers. 462: */ 463: ucall() 464: { 465: register struct a { 466: int priority; 467: int (*routine)(); 468: int arg0; 469: int arg1; 470: } *uap; 471: 472: if (suser()) { 473: uap = (struct a *) u.u_ap; 474: (void) splx(uap->priority); 475: u.u_r.r_val1 = (*uap->routine)(uap->arg0, uap->arg1); 476: (void) _spl0(); 477: } 478: } 479: 480: #ifdef UCB_NET 481: 482: extern u_long LocalAddr; /* Generic local net address */ 483: 484: int nlbase; /* net error log area in clicks */ 485: int nlsize = 01000; 486: int nlclick, nlbyte; 487: 488: int netoff = 0; 489: int protoslow; 490: int protofast; 491: int ifnetslow; 492: int nselcoll; 493: 494: /* 495: * Initialize network code. Called from main(). 496: */ 497: netinit() 498: { 499: extern struct uba_device ubdinit[]; 500: register struct uba_driver *udp; 501: register struct uba_device *ui = &ubdinit; 502: 503: if (netoff) 504: return; 505: nlbase = nlclick = malloc(coremap, nlsize); /* net error log */ 506: MAPSAVE(); 507: mbinit(); 508: for (ui = &ubdinit ; udp = ui->ui_driver ; ui++) { 509: if (badaddr(ui->ui_addr, 2)) 510: continue; 511: ui->ui_alive = 1; 512: udp->ud_dinfo[ui->ui_unit] = ui; 513: (*udp->ud_attach)(ui); 514: } 515: #ifdef INET 516: loattach(); /* XXX */ 517: ifinit(); 518: pfinit(); /* must follow interfaces */ 519: #endif 520: MAPREST(); 521: } 522: 523: /* 524: * Entered via software interrupt vector at spl1. Check netisr bit array 525: * for tasks requesting service. 526: */ 527: netintr() 528: { 529: int onetisr; 530: mapinfo map; 531: 532: savemap(map); 533: while (spl7(), (onetisr = netisr)) { 534: netisr = 0; 535: splnet(); 536: if (onetisr & (1 << NETISR_RAW)) 537: rawintr(); 538: if (onetisr & (1 << NETISR_IP)) 539: ipintr(); 540: if (protofast <= 0) { 541: protofast = hz / PR_FASTHZ; 542: pffasttimo(); 543: } 544: if (protoslow <= 0) { 545: protoslow = hz / PR_SLOWHZ; 546: pfslowtimo(); 547: } 548: if (ifnetslow <= 0) { 549: ifnetslow = hz / IFNET_SLOWHZ; 550: if_slowtimo(); 551: } 552: } 553: restormap(map); 554: } 555: 556: int nprint = 0; /* enable nprintf */ 557: 558: /* 559: * net printf. prints to net log area in memory (nlbase, nlsize). 560: */ 561: nprintf(fmt, x1) 562: char *fmt; 563: unsigned x1; 564: { 565: if (enprint) 566: prf(fmt, &x1, 4); 567: } 568: 569: /* 570: * Select system call. 571: */ 572: select() 573: { 574: register struct uap { 575: int nfd; 576: fd_set *rp, *wp; 577: long timo; 578: } *ap = (struct uap *)u.u_ap; 579: fd_set rd, wr; 580: int nfds = 0; 581: long selscan(); 582: long readable = 0, writeable = 0; 583: time_t t = time; 584: int s, tsel, ncoll, rem; 585: 586: if (ap->nfd > NOFILE) 587: ap->nfd = NOFILE; 588: if (ap->nfd < 0) { 589: u.u_error = EBADF; 590: return; 591: } 592: if (ap->rp && copyin((caddr_t)ap->rp, (caddr_t)&rd, sizeof(fd_set))) 593: return; 594: if (ap->wp && copyin((caddr_t)ap->wp, (caddr_t)&wr, sizeof(fd_set))) 595: return; 596: 597: retry: 598: ncoll = nselcoll; 599: u.u_procp->p_flag |= SSEL; 600: if (ap->rp) 601: readable = selscan(ap->nfd, rd, &nfds, FREAD); 602: if (ap->wp) 603: writeable = selscan(ap->nfd, wr, &nfds, FWRITE); 604: if (u.u_error) 605: goto done; 606: if (readable || writeable) 607: goto done; 608: rem = (ap->timo + 999) / 1000 - (time - t); 609: if (ap->timo == 0 || rem <= 0) 610: goto done; 611: s = spl6(); 612: if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 613: u.u_procp->p_flag &= ~SSEL; 614: splx(s); 615: goto retry; 616: } 617: u.u_procp->p_flag &= ~SSEL; 618: tsel = tsleep((caddr_t)&selwait, PZERO + 1, rem); 619: splx(s); 620: switch (tsel) { 621: 622: case TS_OK: 623: goto retry; 624: 625: case TS_SIG: 626: u.u_error = EINTR; 627: return; 628: 629: case TS_TIME: 630: break; 631: } 632: done: 633: rd.fds_bits[0] = readable; 634: wr.fds_bits[0] = writeable; 635: s = sizeof (fd_set); 636: if (s * NBBY > ap->nfd) 637: s = (ap->nfd + NBBY - 1) / NBBY; 638: u.u_r.r_val1 = nfds; 639: if (ap->rp) 640: (void) copyout((caddr_t)&rd, (caddr_t)ap->rp, sizeof(fd_set)); 641: if (ap->wp) 642: (void) copyout((caddr_t)&wr, (caddr_t)ap->wp, sizeof(fd_set)); 643: } 644: 645: long 646: selscan(nfd, fds, nfdp, flag) 647: int nfd; 648: fd_set fds; 649: int *nfdp, flag; 650: { 651: struct file *fp; 652: struct inode *ip; 653: long bits,res = 0; 654: int i, able; 655: 656: bits = fds.fds_bits[0]; 657: while (i = ffs(bits)) { 658: if (i >= nfd) 659: break; 660: bits &= ~(1L << (i - 1)); 661: fp = u.u_ofile[i - 1]; 662: if (fp == NULL) { 663: u.u_error = EBADF; 664: return (0); 665: } 666: if (fp->f_flag & FSOCKET) 667: able = soselect(fp->f_socket, flag); 668: else { 669: ip = fp->f_inode; 670: switch (ip->i_mode & IFMT) { 671: 672: case IFCHR: 673: able = (*cdevsw[major(ip->i_un.i_rdev)].d_select) 674: ((int)ip->i_un.i_rdev, flag); 675: break; 676: 677: case IFBLK: 678: case IFREG: 679: case IFDIR: 680: able = 1; 681: break; 682: } 683: } 684: if (able) { 685: res |= (1L << (i - 1)); 686: (*nfdp)++; 687: } 688: } 689: return (res); 690: } 691: 692: ffs(mask) 693: long mask; 694: { 695: register int i; 696: register imask; 697: 698: if (mask == 0) 699: return (0); 700: 701: imask = loint(mask); 702: for (i = 1; i < 16; i++) { 703: if (imask & 1) 704: return (i); 705: imask >>= 1; 706: } 707: imask = hiint(mask); 708: for(; i <= 32; i++) { 709: if (imask & 1) 710: return (i); 711: imask >>= 1; 712: } 713: return (0); /* can't get here anyway! */ 714: } 715: 716: /*ARGSUSED*/ 717: seltrue(dev, flag) 718: dev_t dev; 719: int flag; 720: { 721: return (1); 722: } 723: 724: selwakeup(p, coll) 725: register struct proc *p; 726: int coll; 727: { 728: int s; 729: 730: if (coll) { 731: nselcoll++; 732: wakeup((caddr_t) &selwait); 733: } 734: s = spl6(); 735: if (p) 736: if (p->p_wchan == (caddr_t) &selwait) 737: setrun(p); 738: else 739: if (p->p_flag & SSEL) 740: p->p_flag &= ~SSEL; 741: splx(s); 742: } 743: 744: char hostname[32] = "hostnameunknown"; 745: int hostnamelen = 16; 746: 747: gethostname() 748: { 749: register struct a { 750: char *hostname; 751: int len; 752: } *uap = (struct a *) u.u_ap; 753: register int len; 754: 755: len = uap->len; 756: if (len > hostnamelen) 757: len = hostnamelen; 758: if (copyout((caddr_t) hostname, (caddr_t) uap->hostname, len)) 759: u.u_error = EFAULT; 760: } 761: 762: sethostname() 763: { 764: register struct a { 765: char *hostname; 766: int len; 767: } *uap = (struct a *) u.u_ap; 768: 769: if (suser()) { 770: if (uap->len > sizeof (hostname) - 1) { 771: u.u_error = EINVAL; 772: return; 773: } 774: hostnamelen = uap->len; 775: if (copyin((caddr_t) uap->hostname, hostname, uap->len + 1)) 776: u.u_error = EFAULT; 777: } 778: } 779: 780: /* 781: * Sleep on chan at pri. 782: * Return in no more than the indicated number of seconds. 783: * (If seconds==0, no timeout implied) 784: * Return TS_OK if chan was awakened normally 785: * TS_TIME if timeout occurred 786: * TS_SIG if asynchronous signal occurred 787: * 788: * SHOULD HAVE OPTION TO SLEEP TO ABSOLUTE TIME OR AN 789: * INCREMENT IN MILLISECONDS! 790: */ 791: tsleep(chan, pri, seconds) 792: caddr_t chan; 793: int pri, seconds; 794: { 795: label_t lqsav; 796: register struct proc *pp; 797: register sec, n, rval; 798: 799: pp = u.u_procp; 800: n = spl7(); 801: sec = 0; 802: rval = 0; 803: if (pp->p_clktim && pp->p_clktim < seconds) 804: seconds = 0; 805: if (seconds) { 806: pp->p_flag |= STIMO; 807: sec = pp->p_clktim - seconds; 808: pp->p_clktim = seconds; 809: } 810: bcopy((caddr_t) u.u_qsav, (caddr_t) lqsav, sizeof (label_t)); 811: if (save(u.u_qsav)) 812: rval = TS_SIG; 813: else { 814: sleep(chan, pri); 815: if ((pp->p_flag & STIMO) == 0 && seconds) 816: rval = TS_TIME; 817: else 818: rval = TS_OK; 819: } 820: pp->p_flag &= ~STIMO; 821: bcopy((caddr_t) lqsav, (caddr_t) u.u_qsav, sizeof (label_t)); 822: if (sec > 0) 823: pp->p_clktim += sec; 824: else 825: pp->p_clktim = 0; 826: splx(n); 827: return (rval); 828: } 829: 830: /* 831: * Provide about n microseconds of delay 832: */ 833: delay(n) 834: long n; 835: { 836: register hi,low; 837: 838: low = (n & 0177777); 839: hi = n >> 16; 840: if (hi == 0) 841: hi = 1; 842: do { 843: do { } while (--low); 844: } while(--hi); 845: } 846: 847: /* 848: * compare bytes; same result as VAX cmpc3. 849: */ 850: bcmp(s1, s2, n) 851: register char *s1, *s2; 852: register n; 853: { 854: do 855: if (*s1++ != *s2++) 856: break; 857: while (--n); 858: 859: return(n); 860: } 861: 862: struct vaxque { /* queue format expected by VAX queue instr's */ 863: struct vaxque *vq_next; 864: struct vaxque *vq_prev; 865: }; 866: 867: /* 868: * Insert an entry onto queue. 869: */ 870: _insque(e,prev) 871: register struct vaxque *e,*prev; 872: { 873: e->vq_prev = prev; 874: e->vq_next = prev->vq_next; 875: prev->vq_next->vq_prev = e; 876: prev->vq_next = e; 877: } 878: 879: /* 880: * Remove an entry from queue. 881: */ 882: _remque(e) 883: register struct vaxque *e; 884: { 885: e->vq_prev->vq_next = e->vq_next; 886: e->vq_next->vq_prev = e->vq_prev; 887: } 888: 889: setreuid() 890: { 891: struct a { 892: int ruid; 893: int euid; 894: } *uap; 895: register int ruid, euid; 896: 897: uap = (struct a *) u.u_ap; 898: ruid = uap->ruid; 899: if (ruid == -1) 900: ruid = u.u_ruid; 901: if (u.u_ruid != ruid && u.u_uid != ruid && !suser()) 902: return; 903: euid = uap->euid; 904: if (euid == -1) 905: euid = u.u_uid; 906: if (u.u_ruid != euid && u.u_uid != euid && !suser()) 907: return; 908: /* 909: * Everything's okay, do it. 910: */ 911: u.u_procp->p_uid = ruid; 912: u.u_ruid = ruid; 913: u.u_uid = euid; 914: } 915: 916: setregid() 917: { 918: register struct a { 919: int rgid; 920: int egid; 921: } *uap; 922: register int rgid, egid; 923: 924: uap = (struct a *) u.u_ap; 925: rgid = uap->rgid; 926: if (rgid == -1) 927: rgid = u.u_rgid; 928: if (u.u_rgid != rgid && u.u_gid != rgid && !suser()) 929: return; 930: egid = uap->egid; 931: if (egid == -1) 932: egid = u.u_gid; 933: if (u.u_rgid != egid && u.u_gid != egid && !suser()) 934: return; 935: if (u.u_rgid != rgid) 936: u.u_rgid = rgid; 937: if (u.u_gid != egid) 938: u.u_gid = egid; 939: } 940: 941: /* 942: * Get/Set our local internet address. 943: * Names changed from Vax code because of PDP11 length restrictions 944: */ 945: gethostid() 946: { 947: u.u_r.r_off = (off_t) LocalAddr; 948: } 949: 950: sethostid() 951: { 952: struct a { 953: u_long hostid; 954: } *uap = (struct a *) u.u_ap; 955: 956: if (suser()) 957: LocalAddr = uap->hostid; 958: } 959: #endif UCB_NET