|
|
1.1 ! root 1: From uucp Thu Jan 10 01:37:58 1980 ! 2: >From dmr Thu Jan 10 04:25:49 1980 remote from research ! 3: The system has been changed so that if a file being executed ! 4: begins with the magic characters #! , the rest of the line is understood ! 5: to be the name of an interpreter for the executed file. ! 6: Previously (and in fact still) the shell did much of this job; ! 7: it automatically executed itself on a text file with executable mode ! 8: when the text file's name was typed as a command. ! 9: Putting the facility into the system gives the following ! 10: benefits. ! 11: ! 12: 1) It makes shell scripts more like real executable files, ! 13: because they can be the subject of 'exec.' ! 14: ! 15: 2) If you do a 'ps' while such a command is running, its real ! 16: name appears instead of 'sh'. ! 17: Likewise, accounting is done on the basis of the real name. ! 18: ! 19: 3) Shell scripts can be set-user-ID. ! 20: ! 21: 4) It is simpler to have alternate shells available; ! 22: e.g. if you like the Berkeley csh there is no question about ! 23: which shell is to interpret a file. ! 24: ! 25: 5) It will allow other interpreters to fit in more smoothly. ! 26: ! 27: To take advantage of this wonderful opportunity, ! 28: put ! 29: ! 30: #! /bin/sh ! 31: ! 32: at the left margin of the first line of your shell scripts. ! 33: Blanks after ! are OK. Use a complete pathname (no search is done). ! 34: At the moment the whole line is restricted to 16 characters but ! 35: this limit will be raised. ! 36: ! 37: ! 38: From uucp Thu Jan 10 01:37:49 1980 ! 39: >From dmr Thu Jan 10 04:23:53 1980 remote from research ! 40: #include "../h/param.h" ! 41: #include "../h/systm.h" ! 42: #include "../h/map.h" ! 43: #include "../h/dir.h" ! 44: #include "../h/user.h" ! 45: #include "../h/proc.h" ! 46: #include "../h/buf.h" ! 47: #include "../h/reg.h" ! 48: #include "../h/inode.h" ! 49: #include "../h/seg.h" ! 50: #include "../h/acct.h" ! 51: ! 52: ! 53: /* ! 54: * exec system call, with and without environments. ! 55: */ ! 56: struct execa { ! 57: char *fname; ! 58: char **argp; ! 59: char **envp; ! 60: }; ! 61: ! 62: exec() ! 63: { ! 64: ((struct execa *)u.u_ap)->envp = NULL; ! 65: exece(); ! 66: } ! 67: ! 68: exece() ! 69: { ! 70: register nc; ! 71: register char *cp; ! 72: register struct buf *bp; ! 73: register struct execa *uap; ! 74: int na, ne, bno, ucp, ap, c, indir, uid, gid; ! 75: struct inode *ip; ! 76: ! 77: bno = 0; ! 78: bp = 0; ! 79: indir = 0; ! 80: if ((ip = namei(uchar, 0)) == NULL) ! 81: return; ! 82: uid = u.u_uid; ! 83: gid = u.u_gid; ! 84: if (ip->i_mode&ISUID) ! 85: uid = ip->i_uid; ! 86: if (ip->i_mode&ISGID) ! 87: gid = ip->i_gid; ! 88: again: ! 89: if(access(ip, IEXEC)) ! 90: goto bad; ! 91: if((ip->i_mode & IFMT) != IFREG || ! 92: (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { ! 93: u.u_error = EACCES; ! 94: goto bad; ! 95: } ! 96: /* ! 97: * read in first few bytes ! 98: * of file for segment ! 99: * types and sizes: ! 100: * ux_mag = 407/410/411/405 ! 101: * 407 is plain executable ! 102: * 410 is RO text ! 103: * 411 is separated ID ! 104: * 405 is overlaid text ! 105: * ! 106: * Also, an ascii line beginning ! 107: * with '#!' is the file name of a shell. ! 108: */ ! 109: u.u_base = (caddr_t)&u.u_exdata; ! 110: u.u_count = sizeof(u.u_exdata); ! 111: u.u_offset = 0; ! 112: u.u_segflg = 1; ! 113: readi(ip); ! 114: u.u_segflg = 0; ! 115: if(u.u_error) ! 116: goto bad; ! 117: if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.A) ! 118: && u.u_exdata.S[0] != '#') { ! 119: u.u_error = ENOEXEC; ! 120: goto bad; ! 121: } ! 122: if(u.u_exdata.A.ux_mag == 0407) ! 123: ; ! 124: else if (u.u_exdata.A.ux_mag == 0411) ! 125: ; ! 126: else if (u.u_exdata.A.ux_mag == 0405) ! 127: ; ! 128: else if (u.u_exdata.A.ux_mag == 0410) ! 129: ; ! 130: else if (u.u_exdata.S[0]=='#' && u.u_exdata.S[1]=='!' && indir==0) { ! 131: cp = &u.u_exdata.S[2]; ! 132: while (*cp==' ' && cp<&u.u_exdata.S[SHSIZ]) ! 133: cp++; ! 134: u.u_dirp = cp; ! 135: while (cp < &u.u_exdata.S[SHSIZ-1] && *cp != '\n') ! 136: cp++; ! 137: *cp = '\0'; ! 138: indir++; ! 139: iput(ip); ! 140: ip = namei(schar, 0); ! 141: if (ip==NULL) ! 142: return; ! 143: goto again; ! 144: } else { ! 145: u.u_error = ENOEXEC; ! 146: goto bad; ! 147: } ! 148: /* ! 149: * Collect arguments on "file" in swap space. ! 150: */ ! 151: na = 0; ! 152: ne = 0; ! 153: nc = 0; ! 154: uap = (struct execa *)u.u_ap; ! 155: while ((bno = malloc(argmap,(NCARGS+BSIZE-1)/BSIZE)) == 0) ! 156: sleep((caddr_t)&argmap, PRIBIO); ! 157: if (uap->argp) for (;;) { ! 158: ap = NULL; ! 159: if (indir && na==1) ! 160: ap = uap->fname; ! 161: else if (uap->argp) { ! 162: ap = fuword((caddr_t)uap->argp); ! 163: uap->argp++; ! 164: } ! 165: if (ap==NULL && uap->envp) { ! 166: uap->argp = NULL; ! 167: if ((ap = fuword((caddr_t)uap->envp)) == NULL) ! 168: break; ! 169: uap->envp++; ! 170: ne++; ! 171: } ! 172: if (ap==NULL) ! 173: break; ! 174: na++; ! 175: if(ap == -1) ! 176: u.u_error = EFAULT; ! 177: do { ! 178: if (nc >= NCARGS-1) ! 179: u.u_error = E2BIG; ! 180: if ((c = fubyte((caddr_t)ap++)) < 0) ! 181: u.u_error = EFAULT; ! 182: if (u.u_error) ! 183: goto bad; ! 184: if ((nc&BMASK) == 0) { ! 185: if (bp) ! 186: bawrite(bp); ! 187: bp = getblk(swapdev, swplo+bno+(nc>>BSHIFT)); ! 188: cp = bp->b_un.b_addr; ! 189: } ! 190: nc++; ! 191: *cp++ = c; ! 192: } while (c>0); ! 193: } ! 194: if (bp) ! 195: bawrite(bp); ! 196: bp = 0; ! 197: nc = (nc + NBPW-1) & ~(NBPW-1); ! 198: getxfile(ip, nc, uid, gid); ! 199: if (u.u_error || u.u_exdata.A.ux_mag==0405) ! 200: goto bad; ! 201: ! 202: /* ! 203: * copy back arglist ! 204: */ ! 205: ucp = -nc - NBPW; ! 206: ap = ucp - na*NBPW - 3*NBPW; ! 207: u.u_ar0[R6] = ap; ! 208: suword((caddr_t)ap, na-ne); ! 209: nc = 0; ! 210: for (;;) { ! 211: ap += NBPW; ! 212: if (na==ne) { ! 213: suword((caddr_t)ap, 0); ! 214: ap += NBPW; ! 215: } ! 216: if (--na < 0) ! 217: break; ! 218: suword((caddr_t)ap, ucp); ! 219: do { ! 220: if ((nc&BMASK) == 0) { ! 221: if (bp) ! 222: brelse(bp); ! 223: bp = bread(swapdev, swplo+bno+(nc>>BSHIFT)); ! 224: bp->b_flags &= ~B_DELWRI; ! 225: cp = bp->b_un.b_addr; ! 226: if (nc==0 && indir) ! 227: bcopy(cp, (caddr_t)u.u_dbuf, DIRSIZ); ! 228: } ! 229: subyte((caddr_t)ucp++, (c = *cp++)); ! 230: nc++; ! 231: } while(c&0377); ! 232: } ! 233: suword((caddr_t)ap, 0); ! 234: suword((caddr_t)ucp, 0); ! 235: setregs(); ! 236: bad: ! 237: if (bp) ! 238: brelse(bp); ! 239: if(bno) { ! 240: mfree(argmap, (NCARGS+BSIZE-1)/BSIZE, bno); ! 241: wakeup((caddr_t)&argmap); ! 242: } ! 243: iput(ip); ! 244: } ! 245: ! 246: /* ! 247: * Read in and set up memory for executed file. ! 248: */ ! 249: getxfile(ip, nargc, uid, gid) ! 250: register struct inode *ip; ! 251: { ! 252: register unsigned ds; ! 253: register sep; ! 254: register unsigned ts, ss; ! 255: int i; ! 256: long lsize; ! 257: ! 258: sep = 0; ! 259: if(u.u_exdata.A.ux_mag == 0407) { ! 260: lsize = (long)u.u_exdata.A.ux_dsize + u.u_exdata.A.ux_tsize; ! 261: u.u_exdata.A.ux_dsize = lsize; ! 262: if (lsize != u.u_exdata.A.ux_dsize) { /* check overflow */ ! 263: u.u_error = ENOMEM; ! 264: return; ! 265: } ! 266: u.u_exdata.A.ux_tsize = 0; ! 267: } else if (u.u_exdata.A.ux_mag == 0411) ! 268: sep++; ! 269: if(u.u_exdata.A.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) { ! 270: u.u_error = ETXTBSY; ! 271: return; ! 272: } ! 273: ! 274: /* ! 275: * find text and data sizes ! 276: * try them out for possible ! 277: * overflow of max sizes ! 278: */ ! 279: ts = btoc(u.u_exdata.A.ux_tsize); ! 280: lsize = (long)u.u_exdata.A.ux_dsize + u.u_exdata.A.ux_bsize; ! 281: if (lsize != (unsigned)lsize) { ! 282: u.u_error = ENOMEM; ! 283: return; ! 284: } ! 285: ds = btoc(lsize); ! 286: ss = SSIZE + btoc(nargc); ! 287: if (u.u_exdata.A.ux_mag==0405) { ! 288: if (u.u_sep==0 && ctos(ts) != ctos(u.u_tsize) || nargc) { ! 289: u.u_error = ENOMEM; ! 290: return; ! 291: } ! 292: ds = u.u_dsize; ! 293: ss = u.u_ssize; ! 294: sep = u.u_sep; ! 295: xfree(); ! 296: xalloc(ip); ! 297: u.u_ar0[PC] = u.u_exdata.A.ux_entloc & ~01; ! 298: } else { ! 299: if(estabur(ts, ds, ss, sep, RO)) ! 300: return; ! 301: ! 302: /* ! 303: * allocate and clear core ! 304: * at this point, committed ! 305: * to the new image ! 306: */ ! 307: u.u_prof.pr_scale = 0; ! 308: xfree(); ! 309: i = USIZE+ds+ss; ! 310: expand(i); ! 311: while(--i >= USIZE) ! 312: clearseg(u.u_procp->p_addr+i); ! 313: xalloc(ip); ! 314: ! 315: /* ! 316: * read in data segment ! 317: */ ! 318: estabur((unsigned)0, ds, (unsigned)0, 0, RO); ! 319: u.u_base = 0; ! 320: u.u_offset = sizeof(u.u_exdata.A)+u.u_exdata.A.ux_tsize; ! 321: u.u_count = u.u_exdata.A.ux_dsize; ! 322: readi(ip); ! 323: /* ! 324: * set SUID/SGID protections, if no tracing ! 325: */ ! 326: if ((u.u_procp->p_flag&STRC)==0) { ! 327: u.u_uid = uid; ! 328: u.u_gid = gid; ! 329: } else ! 330: psignal(u.u_procp, SIGTRC); ! 331: } ! 332: u.u_tsize = ts; ! 333: u.u_dsize = ds; ! 334: u.u_ssize = ss; ! 335: u.u_sep = sep; ! 336: estabur(ts, ds, ss, sep, RO); ! 337: } ! 338: ! 339: /* ! 340: * Clear registers on exec ! 341: */ ! 342: setregs() ! 343: { ! 344: register int *rp; ! 345: register char *cp; ! 346: register i; ! 347: ! 348: for(rp = &u.u_signal[0]; rp < &u.u_signal[NSIG]; rp++) ! 349: if((*rp & 1) == 0) ! 350: *rp = 0; ! 351: for(cp = ®loc[0]; cp < ®loc[6];) ! 352: u.u_ar0[*cp++] = 0; ! 353: u.u_ar0[PC] = u.u_exdata.A.ux_entloc & ~01; ! 354: for(rp = (int *)&u.u_fps; rp < (int *)&u.u_fps.u_fpregs[6];) ! 355: *rp++ = 0; ! 356: for(i=0; i<NOFILE; i++) { ! 357: if (u.u_pofile[i]&EXCLOSE) { ! 358: closef(u.u_ofile[i]); ! 359: u.u_ofile[i] = NULL; ! 360: u.u_pofile[i] &= ~EXCLOSE; ! 361: } ! 362: } ! 363: /* ! 364: * Remember file name for accounting. ! 365: */ ! 366: u.u_acflag &= ~AFORK; ! 367: bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_comm, DIRSIZ); ! 368: } ! 369: ! 370: /* ! 371: * exit system call: ! 372: * pass back caller's arg ! 373: */ ! 374: rexit() ! 375: { ! 376: register struct a { ! 377: int rval; ! 378: } *uap; ! 379: ! 380: uap = (struct a *)u.u_ap; ! 381: exit((uap->rval & 0377) << 8); ! 382: } ! 383: ! 384: /* ! 385: * Release resources. ! 386: * Save u. area for parent to look at. ! 387: * Enter zombie state. ! 388: * Wake up parent and init processes, ! 389: * and dispose of children. ! 390: */ ! 391: exit(rv) ! 392: { ! 393: register int i; ! 394: register struct proc *p, *q; ! 395: register struct file *f; ! 396: ! 397: p = u.u_procp; ! 398: p->p_flag &= ~(STRC|SULOCK); ! 399: p->p_clktim = 0; ! 400: for(i=0; i<NSIG; i++) ! 401: u.u_signal[i] = 1; ! 402: for(i=0; i<NOFILE; i++) { ! 403: f = u.u_ofile[i]; ! 404: u.u_ofile[i] = NULL; ! 405: closef(f); ! 406: } ! 407: plock(u.u_cdir); ! 408: iput(u.u_cdir); ! 409: if (u.u_rdir) { ! 410: plock(u.u_rdir); ! 411: iput(u.u_rdir); ! 412: } ! 413: xfree(); ! 414: acct(); ! 415: mfree(coremap, p->p_size, p->p_addr); ! 416: p->p_stat = SZOMB; ! 417: ((struct xproc *)p)->xp_xstat = rv; ! 418: ((struct xproc *)p)->xp_utime = u.u_cutime + u.u_utime; ! 419: ((struct xproc *)p)->xp_stime = u.u_cstime + u.u_stime; ! 420: for(q = &proc[0]; q < &proc[NPROC]; q++) ! 421: if(q->p_ppid == p->p_pid) { ! 422: wakeup((caddr_t)&proc[1]); ! 423: q->p_ppid = 1; ! 424: if (q->p_stat==SSTOP) ! 425: setrun(q); ! 426: } ! 427: for(q = &proc[0]; q < &proc[NPROC]; q++) ! 428: if(p->p_ppid == q->p_pid) { ! 429: wakeup((caddr_t)q); ! 430: swtch(); ! 431: /* no return */ ! 432: } ! 433: swtch(); ! 434: } ! 435: ! 436: /* ! 437: * Wait system call. ! 438: * Search for a terminated (zombie) child, ! 439: * finally lay it to rest, and collect its status. ! 440: * Look also for stopped (traced) children, ! 441: * and pass back status from them. ! 442: */ ! 443: wait() ! 444: { ! 445: register f; ! 446: register struct proc *p; ! 447: ! 448: f = 0; ! 449: ! 450: loop: ! 451: for(p = &proc[0]; p < &proc[NPROC]; p++) ! 452: if(p->p_ppid == u.u_procp->p_pid) { ! 453: f++; ! 454: if(p->p_stat == SZOMB) { ! 455: u.u_r.V.r_val1 = p->p_pid; ! 456: u.u_r.V.r_val2 = ((struct xproc *)p)->xp_xstat; ! 457: u.u_cutime += ((struct xproc *)p)->xp_utime; ! 458: u.u_cstime += ((struct xproc *)p)->xp_stime; ! 459: p->p_pid = 0; ! 460: p->p_ppid = 0; ! 461: p->p_pgrp = 0; ! 462: p->p_sig = 0; ! 463: p->p_flag = 0; ! 464: p->p_wchan = 0; ! 465: p->p_stat = NULL; ! 466: return; ! 467: } ! 468: if(p->p_stat == SSTOP) { ! 469: if((p->p_flag&SWTED) == 0) { ! 470: p->p_flag |= SWTED; ! 471: u.u_r.V.r_val1 = p->p_pid; ! 472: u.u_r.V.r_val2 = (fsig(p)<<8) | 0177; ! 473: return; ! 474: } ! 475: continue; ! 476: } ! 477: } ! 478: if(f) { ! 479: sleep((caddr_t)u.u_procp, PWAIT); ! 480: goto loop; ! 481: } ! 482: u.u_error = ECHILD; ! 483: } ! 484: ! 485: /* ! 486: * fork system call. ! 487: */ ! 488: fork() ! 489: { ! 490: register struct proc *p1, *p2; ! 491: register a; ! 492: ! 493: /* ! 494: * Make sure there's enough swap space for max ! 495: * core image, thus reducing chances of running out ! 496: */ ! 497: if ((a = malloc(swapmap, ctod(MAXMEM))) == 0) { ! 498: u.u_error = ENOMEM; ! 499: goto out; ! 500: } ! 501: mfree(swapmap, ctod(MAXMEM), a); ! 502: a = 0; ! 503: p2 = NULL; ! 504: for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) { ! 505: if (p1->p_stat==NULL && p2==NULL) ! 506: p2 = p1; ! 507: else { ! 508: if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) ! 509: a++; ! 510: } ! 511: } ! 512: /* ! 513: * Disallow if ! 514: * No processes at all; ! 515: * not su and too many procs owned; or ! 516: * not su and would take last slot. ! 517: */ ! 518: if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) { ! 519: u.u_error = EAGAIN; ! 520: goto out; ! 521: } ! 522: p1 = u.u_procp; ! 523: if(newproc()) { ! 524: u.u_r.V.r_val1 = p1->p_pid; ! 525: u.u_start = time; ! 526: u.u_cstime = 0; ! 527: u.u_stime = 0; ! 528: u.u_cutime = 0; ! 529: u.u_utime = 0; ! 530: u.u_acflag = AFORK; ! 531: return; ! 532: } ! 533: u.u_r.V.r_val1 = p2->p_pid; ! 534: ! 535: out: ! 536: u.u_ar0[R7] += NBPW; ! 537: } ! 538: ! 539: /* ! 540: * break system call. ! 541: * -- bad planning: "break" is a dirty word in C. ! 542: */ ! 543: sbreak() ! 544: { ! 545: struct a { ! 546: char *nsiz; ! 547: }; ! 548: register a, n, d; ! 549: int i; ! 550: ! 551: /* ! 552: * set n to new data size ! 553: * set d to new-old ! 554: * set n to new total size ! 555: */ ! 556: ! 557: n = btoc((int)((struct a *)u.u_ap)->nsiz); ! 558: if(!u.u_sep) ! 559: n -= ctos(u.u_tsize) * stoc(1); ! 560: if(n < 0) ! 561: n = 0; ! 562: d = n - u.u_dsize; ! 563: n += USIZE+u.u_ssize; ! 564: if(estabur(u.u_tsize, u.u_dsize+d, u.u_ssize, u.u_sep, RO)) ! 565: return; ! 566: u.u_dsize += d; ! 567: if(d > 0) ! 568: goto bigger; ! 569: a = u.u_procp->p_addr + n - u.u_ssize; ! 570: i = n; ! 571: n = u.u_ssize; ! 572: while(n--) { ! 573: copyseg(a-d, a); ! 574: a++; ! 575: } ! 576: expand(i); ! 577: return; ! 578: ! 579: bigger: ! 580: expand(n); ! 581: a = u.u_procp->p_addr + n; ! 582: n = u.u_ssize; ! 583: while(n--) { ! 584: a--; ! 585: copyseg(a-d, a); ! 586: } ! 587: while(d--) ! 588: clearseg(--a); ! 589: } ! 590: ! 591:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.