|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "../port/error.h" ! 7: ! 8: #include <a.out.h> ! 9: ! 10: int shargs(char*, int, char**); ! 11: ! 12: long ! 13: sysr1(ulong *arg) ! 14: { ! 15: xsummary(); ! 16: print("[%s %s %d] r1 = %d\n", u->p->user, u->p->text, u->p->pid, arg[0]); ! 17: return 0; ! 18: } ! 19: ! 20: long ! 21: sysrfork(ulong *arg) ! 22: { ! 23: KMap *k; ! 24: Pgrp *opg; ! 25: Egrp *oeg; ! 26: Fgrp *ofg; ! 27: int n, i; ! 28: Proc *p, *parent; ! 29: ulong upa, pid, flag; ! 30: /* ! 31: * used to compute last valid system stack address for copy ! 32: */ ! 33: int lastvar; ! 34: ! 35: flag = arg[0]; ! 36: p = u->p; ! 37: if((flag&RFPROC) == 0) { ! 38: if(flag & (RFNAMEG|RFCNAMEG)) { ! 39: if((flag & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG)) ! 40: error(Ebadarg); ! 41: opg = p->pgrp; ! 42: p->pgrp = newpgrp(); ! 43: if(flag & RFNAMEG) ! 44: pgrpcpy(p->pgrp, opg); ! 45: closepgrp(opg); ! 46: } ! 47: if(flag & (RFENVG|RFCENVG)) { ! 48: if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG)) ! 49: error(Ebadarg); ! 50: oeg = p->egrp; ! 51: p->egrp = smalloc(sizeof(Egrp)); ! 52: p->egrp->ref = 1; ! 53: if(flag & RFENVG) ! 54: envcpy(p->egrp, oeg); ! 55: closeegrp(oeg); ! 56: } ! 57: if(flag & RFFDG) { ! 58: ofg = p->fgrp; ! 59: p->fgrp = dupfgrp(ofg); ! 60: closefgrp(ofg); ! 61: } ! 62: else ! 63: if(flag & RFCFDG) { ! 64: ofg = p->fgrp; ! 65: p->fgrp = smalloc(sizeof(Fgrp)); ! 66: p->fgrp->ref = 1; ! 67: closefgrp(ofg); ! 68: } ! 69: if(flag & RFNOTEG) ! 70: p->noteid = incref(¬eidalloc); ! 71: if(flag & (RFMEM|RFNOWAIT)) ! 72: error(Ebadarg); ! 73: return 0; ! 74: } ! 75: /* Check flags before we commit */ ! 76: if((flag & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG)) ! 77: error(Ebadarg); ! 78: if((flag & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG)) ! 79: error(Ebadarg); ! 80: if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG)) ! 81: error(Ebadarg); ! 82: ! 83: p = newproc(); ! 84: parent = u->p; ! 85: ! 86: /* Page va of upage used as check in mapstack */ ! 87: p->upage = newpage(0, 0, USERADDR|(p->pid&0xFFFF)); ! 88: k = kmap(p->upage); ! 89: upa = VA(k); ! 90: ! 91: /* Save time: only copy u-> data and useful stack */ ! 92: memmove((void*)upa, u, sizeof(User)); ! 93: n = USERADDR+BY2PG - (ulong)&lastvar; ! 94: n = (n+32) & ~(BY2WD-1); ! 95: memmove((void*)(upa+BY2PG-n), (void*)(USERADDR+BY2PG-n), n); ! 96: ((User *)upa)->p = p; ! 97: kunmap(k); ! 98: ! 99: /* Make a new set of memory segments */ ! 100: n = flag & RFMEM; ! 101: for(i = 0; i < NSEG; i++) ! 102: if(parent->seg[i]) ! 103: p->seg[i] = dupseg(parent->seg, i, n); ! 104: ! 105: /* Refs */ ! 106: incref(u->dot); ! 107: ! 108: /* File descriptors */ ! 109: if(flag & (RFFDG|RFCFDG)) { ! 110: if(flag & RFFDG) ! 111: p->fgrp = dupfgrp(parent->fgrp); ! 112: else { ! 113: p->fgrp = smalloc(sizeof(Fgrp)); ! 114: p->fgrp->ref = 1; ! 115: } ! 116: } ! 117: else { ! 118: p->fgrp = parent->fgrp; ! 119: incref(p->fgrp); ! 120: } ! 121: ! 122: /* Process groups */ ! 123: if(flag & (RFNAMEG|RFCNAMEG)) { ! 124: p->pgrp = newpgrp(); ! 125: if(flag & RFNAMEG) ! 126: pgrpcpy(p->pgrp, parent->pgrp); ! 127: } ! 128: else { ! 129: p->pgrp = parent->pgrp; ! 130: incref(p->pgrp); ! 131: } ! 132: ! 133: /* Environment group */ ! 134: if(flag & (RFENVG|RFCENVG)) { ! 135: p->egrp = smalloc(sizeof(Egrp)); ! 136: p->egrp->ref = 1; ! 137: if(flag & RFENVG) ! 138: envcpy(p->egrp, parent->egrp); ! 139: } ! 140: else { ! 141: p->egrp = parent->egrp; ! 142: incref(p->egrp); ! 143: } ! 144: ! 145: p->hang = parent->hang; ! 146: p->procmode = parent->procmode; ! 147: ! 148: if(setlabel(&p->sched)){ ! 149: /* ! 150: * use u->p instead of p, because we don't trust the compiler, after a ! 151: * gotolabel, to find the correct contents of a local variable. ! 152: */ ! 153: p = u->p; ! 154: p->state = Running; ! 155: p->mach = m; ! 156: m->proc = p; ! 157: spllo(); ! 158: return 0; ! 159: } ! 160: ! 161: p->parent = parent; ! 162: p->parentpid = parent->pid; ! 163: if(flag&RFNOWAIT) ! 164: p->parentpid = 1; ! 165: else { ! 166: lock(&parent->exl); ! 167: parent->nchild++; ! 168: unlock(&parent->exl); ! 169: } ! 170: if((flag&RFNOTEG) == 0) ! 171: p->noteid = parent->noteid; ! 172: ! 173: p->fpstate = parent->fpstate; ! 174: pid = p->pid; ! 175: memset(p->time, 0, sizeof(p->time)); ! 176: p->time[TReal] = MACHP(0)->ticks; ! 177: memmove(p->text, parent->text, NAMELEN); ! 178: memmove(p->user, parent->user, NAMELEN); ! 179: /* ! 180: * since the bss/data segments are now shareable, ! 181: * any mmu info about this process is now stale ! 182: * (i.e. has bad properties) and has to be discarded. ! 183: */ ! 184: flushmmu(); ! 185: p->priority = u->p->priority; ! 186: p->basepri = u->p->basepri; ! 187: p->mp = u->p->mp; ! 188: ready(p); ! 189: sched(); ! 190: return pid; ! 191: } ! 192: ! 193: static ulong ! 194: l2be(long l) ! 195: { ! 196: uchar *cp; ! 197: ! 198: cp = (uchar*)&l; ! 199: return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3]; ! 200: } ! 201: ! 202: long ! 203: sysexec(ulong *arg) ! 204: { ! 205: Proc *p; ! 206: Segment *s, *ts; ! 207: ulong t, d, b; ! 208: int i; ! 209: Chan *tc; ! 210: char **argv, **argp; ! 211: char *a, *charp, *file; ! 212: char *progarg[sizeof(Exec)/2+1], elem[NAMELEN]; ! 213: ulong ssize, spage, nargs, nbytes, n, bssend; ! 214: int indir; ! 215: Exec exec; ! 216: char line[sizeof(Exec)]; ! 217: Fgrp *f; ! 218: Image *img; ! 219: ulong magic, text, entry, data, bss; ! 220: ! 221: p = u->p; ! 222: validaddr(arg[0], 1, 0); ! 223: file = (char*)arg[0]; ! 224: indir = 0; ! 225: Header: ! 226: tc = namec(file, Aopen, OEXEC, 0); ! 227: if(waserror()){ ! 228: close(tc); ! 229: nexterror(); ! 230: } ! 231: if(!indir) ! 232: strcpy(elem, u->elem); ! 233: ! 234: n = (*devtab[tc->type].read)(tc, &exec, sizeof(Exec), 0); ! 235: if(n < 2) ! 236: Err: ! 237: error(Ebadexec); ! 238: magic = l2be(exec.magic); ! 239: text = l2be(exec.text); ! 240: entry = l2be(exec.entry); ! 241: if(n==sizeof(Exec) && magic==AOUT_MAGIC){ ! 242: if((text&KZERO) ! 243: || entry < UTZERO+sizeof(Exec) ! 244: || entry >= UTZERO+sizeof(Exec)+text) ! 245: goto Err; ! 246: goto Binary; ! 247: } ! 248: ! 249: /* ! 250: * Process #! /bin/sh args ... ! 251: */ ! 252: memmove(line, &exec, sizeof(Exec)); ! 253: if(indir || line[0]!='#' || line[1]!='!') ! 254: goto Err; ! 255: n = shargs(line, n, progarg); ! 256: if(n == 0) ! 257: goto Err; ! 258: indir = 1; ! 259: /* ! 260: * First arg becomes complete file name ! 261: */ ! 262: progarg[n++] = file; ! 263: progarg[n] = 0; ! 264: validaddr(arg[1], BY2WD, 1); ! 265: arg[1] += BY2WD; ! 266: file = progarg[0]; ! 267: progarg[0] = elem; ! 268: poperror(); ! 269: close(tc); ! 270: goto Header; ! 271: ! 272: Binary: ! 273: poperror(); ! 274: data = l2be(exec.data); ! 275: bss = l2be(exec.bss); ! 276: t = (UTZERO+sizeof(Exec)+text+(BY2PG-1)) & ~(BY2PG-1); ! 277: d = (t + data + (BY2PG-1)) & ~(BY2PG-1); ! 278: bssend = t + data + bss; ! 279: b = (bssend + (BY2PG-1)) & ~(BY2PG-1); ! 280: if((t|d|b) & KZERO) ! 281: error(Ebadexec); ! 282: ! 283: /* ! 284: * Args: pass 1: count ! 285: */ ! 286: nbytes = BY2WD; /* hole for profiling clock at top of stack */ ! 287: nargs = 0; ! 288: if(indir){ ! 289: argp = progarg; ! 290: while(*argp){ ! 291: a = *argp++; ! 292: nbytes += strlen(a) + 1; ! 293: nargs++; ! 294: } ! 295: } ! 296: evenaddr(arg[1]); ! 297: argp = (char**)arg[1]; ! 298: validaddr((ulong)argp, BY2WD, 0); ! 299: while(*argp){ ! 300: a = *argp++; ! 301: if(((ulong)argp&(BY2PG-1)) < BY2WD) ! 302: validaddr((ulong)argp, BY2WD, 0); ! 303: validaddr((ulong)a, 1, 0); ! 304: nbytes += (vmemchr(a, 0, 0x7FFFFFFF) - a) + 1; ! 305: nargs++; ! 306: } ! 307: ssize = BY2WD*(nargs+1) + ((nbytes+(BY2WD-1)) & ~(BY2WD-1)); ! 308: ! 309: /* ! 310: * 8-byte align SP for those (e.g. sparc) that need it. ! 311: * execregs() will subtract another 4 bytes for argc. ! 312: */ ! 313: if((ssize+4) & 7) ! 314: ssize += 4; ! 315: spage = (ssize+(BY2PG-1)) >> PGSHIFT; ! 316: /* ! 317: * Build the stack segment, putting it in kernel virtual for the moment ! 318: */ ! 319: if(spage > TSTKSIZ) ! 320: error(Enovmem); ! 321: ! 322: p->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG); ! 323: ! 324: /* ! 325: * Args: pass 2: assemble; the pages will be faulted in ! 326: */ ! 327: argv = (char**)(TSTKTOP - ssize); ! 328: charp = (char*)(TSTKTOP - nbytes); ! 329: if(indir) ! 330: argp = progarg; ! 331: else ! 332: argp = (char**)arg[1]; ! 333: ! 334: for(i=0; i<nargs; i++){ ! 335: if(indir && *argp==0) { ! 336: indir = 0; ! 337: argp = (char**)arg[1]; ! 338: } ! 339: *argv++ = charp + (USTKTOP-TSTKTOP); ! 340: n = strlen(*argp) + 1; ! 341: memmove(charp, *argp++, n); ! 342: charp += n; ! 343: } ! 344: ! 345: memmove(p->text, elem, NAMELEN); ! 346: ! 347: /* ! 348: * Committed. ! 349: * Free old memory. ! 350: * Special segments are maintained accross exec ! 351: */ ! 352: for(i = SSEG; i <= BSEG; i++) { ! 353: putseg(p->seg[i]); ! 354: /* prevent a second free if we have an error */ ! 355: p->seg[i] = 0; ! 356: } ! 357: for(i = BSEG+1; i < NSEG; i++) { ! 358: s = p->seg[i]; ! 359: if(s != 0 && (s->type&SG_CEXEC)) { ! 360: putseg(s); ! 361: p->seg[i] = 0; ! 362: } ! 363: } ! 364: ! 365: /* ! 366: * Close on exec ! 367: */ ! 368: f = u->p->fgrp; ! 369: for(i=0; i<=f->maxfd; i++) ! 370: fdclose(i, CCEXEC); ! 371: ! 372: /* Text. Shared. Attaches to cache image if possible */ ! 373: /* attachimage returns a locked cache image */ ! 374: img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (t-UTZERO)>>PGSHIFT); ! 375: ts = img->s; ! 376: p->seg[TSEG] = ts; ! 377: ts->flushme = 1; ! 378: ts->fstart = 0; ! 379: ts->flen = sizeof(Exec)+text; ! 380: unlock(img); ! 381: ! 382: /* Data. Shared. */ ! 383: s = newseg(SG_DATA, t, (d-t)>>PGSHIFT); ! 384: p->seg[DSEG] = s; ! 385: ! 386: /* Attached by hand */ ! 387: incref(img); ! 388: s->image = img; ! 389: s->fstart = ts->fstart+ts->flen; ! 390: s->flen = data; ! 391: ! 392: /* BSS. Zero fill on demand */ ! 393: p->seg[BSEG] = newseg(SG_BSS, d, (b-d)>>PGSHIFT); ! 394: ! 395: /* ! 396: * Move the stack ! 397: */ ! 398: s = p->seg[ESEG]; ! 399: p->seg[ESEG] = 0; ! 400: p->seg[SSEG] = s; ! 401: s->base = USTKTOP-USTKSIZE; ! 402: s->top = USTKTOP; ! 403: relocateseg(s, TSTKTOP-USTKTOP); ! 404: ! 405: /* ! 406: * '/' processes are higher priority (hack to make /ip more responsive). ! 407: */ ! 408: if(devchar[tc->type] == L'/') ! 409: u->p->basepri = PriRoot; ! 410: u->p->priority = u->p->basepri; ! 411: close(tc); ! 412: ! 413: /* ! 414: * At this point, the mmu contains info about the old address ! 415: * space and needs to be flushed ! 416: */ ! 417: flushmmu(); ! 418: qlock(&p->debug); ! 419: u->nnote = 0; ! 420: u->notify = 0; ! 421: u->notified = 0; ! 422: procsetup(p); ! 423: qunlock(&p->debug); ! 424: if(p->hang) ! 425: p->procctl = Proc_stopme; ! 426: ! 427: return execregs(entry, ssize, nargs); ! 428: } ! 429: ! 430: int ! 431: shargs(char *s, int n, char **ap) ! 432: { ! 433: int i; ! 434: ! 435: s += 2; ! 436: n -= 2; /* skip #! */ ! 437: for(i=0; s[i]!='\n'; i++) ! 438: if(i == n-1) ! 439: return 0; ! 440: s[i] = 0; ! 441: *ap = 0; ! 442: i = 0; ! 443: for(;;){ ! 444: while(*s==' ' || *s=='\t') ! 445: s++; ! 446: if(*s == 0) ! 447: break; ! 448: i++; ! 449: *ap++ = s; ! 450: *ap = 0; ! 451: while(*s && *s!=' ' && *s!='\t') ! 452: s++; ! 453: if(*s == 0) ! 454: break; ! 455: else ! 456: *s++ = 0; ! 457: } ! 458: return i; ! 459: } ! 460: ! 461: int ! 462: return0(void *a) ! 463: { ! 464: USED(a); ! 465: return 0; ! 466: } ! 467: ! 468: long ! 469: syssleep(ulong *arg) ! 470: { ! 471: int n; ! 472: ! 473: n = arg[0]; ! 474: if(n == 0){ ! 475: sched(); /* yield */ ! 476: return 0; ! 477: } ! 478: if(MS2TK(n) == 0) /* sleep for at least one tick */ ! 479: n = TK2MS(1); ! 480: tsleep(&u->p->sleep, return0, 0, n); ! 481: ! 482: return 0; ! 483: } ! 484: ! 485: long ! 486: sysalarm(ulong *arg) ! 487: { ! 488: return procalarm(arg[0]); ! 489: } ! 490: ! 491: long ! 492: sysexits(ulong *arg) ! 493: { ! 494: char *status; ! 495: char *inval = "invalid exit string"; ! 496: char buf[ERRLEN]; ! 497: ! 498: status = (char*)arg[0]; ! 499: if(status){ ! 500: if(waserror()) ! 501: status = inval; ! 502: else{ ! 503: validaddr((ulong)status, 1, 0); ! 504: if(vmemchr(status, 0, ERRLEN) == 0){ ! 505: memmove(buf, status, ERRLEN); ! 506: buf[ERRLEN-1] = 0; ! 507: status = buf; ! 508: } ! 509: } ! 510: poperror(); ! 511: ! 512: } ! 513: pexit(status, 1); ! 514: return 0; /* not reached */ ! 515: } ! 516: ! 517: long ! 518: syswait(ulong *arg) ! 519: { ! 520: if(arg[0]){ ! 521: validaddr(arg[0], sizeof(Waitmsg), 1); ! 522: evenaddr(arg[0]); ! 523: } ! 524: return pwait((Waitmsg*)arg[0]); ! 525: } ! 526: ! 527: long ! 528: sysdeath(ulong *arg) ! 529: { ! 530: USED(arg); ! 531: pprint("deprecated system call\n"); ! 532: pexit("Suicide", 0); ! 533: return 0; /* not reached */ ! 534: } ! 535: ! 536: long ! 537: syserrstr(ulong *arg) ! 538: { ! 539: char tmp[ERRLEN]; ! 540: ! 541: validaddr(arg[0], ERRLEN, 1); ! 542: memmove(tmp, (char*)arg[0], ERRLEN); ! 543: memmove((char*)arg[0], u->error, ERRLEN); ! 544: memmove(u->error, tmp, ERRLEN); ! 545: return 0; ! 546: } ! 547: ! 548: long ! 549: sysnotify(ulong *arg) ! 550: { ! 551: USED(arg); ! 552: if(arg[0] != 0) ! 553: validaddr(arg[0], sizeof(ulong), 0); ! 554: u->notify = (int(*)(void*, char*))(arg[0]); ! 555: return 0; ! 556: } ! 557: ! 558: long ! 559: sysnoted(ulong *arg) ! 560: { ! 561: if(arg[0]!=NRSTR && !u->notified) ! 562: error(Egreg); ! 563: return 0; ! 564: } ! 565: ! 566: long ! 567: syssegbrk(ulong *arg) ! 568: { ! 569: Segment *s; ! 570: int i; ! 571: ! 572: for(i = 0; i < NSEG; i++) { ! 573: if(s = u->p->seg[i]) { ! 574: if(arg[0] >= s->base && arg[0] < s->top) { ! 575: switch(s->type&SG_TYPE) { ! 576: case SG_TEXT: ! 577: case SG_DATA: ! 578: case SG_STACK: ! 579: error(Ebadarg); ! 580: default: ! 581: return ibrk(arg[1], i); ! 582: } ! 583: } ! 584: } ! 585: } ! 586: ! 587: error(Ebadarg); ! 588: return 0; /* not reached */ ! 589: } ! 590: ! 591: long ! 592: syssegattach(ulong *arg) ! 593: { ! 594: return segattach(u->p, arg[0], (char*)arg[1], arg[2], arg[3]); ! 595: } ! 596: ! 597: long ! 598: syssegdetach(ulong *arg) ! 599: { ! 600: int i; ! 601: Segment *s; ! 602: ! 603: s = 0; ! 604: for(i = 0; i < NSEG; i++) ! 605: if(s = u->p->seg[i]) { ! 606: qlock(&s->lk); ! 607: if((arg[0] >= s->base && arg[0] < s->top) || ! 608: (s->top == s->base && arg[0] == s->base)) ! 609: goto found; ! 610: qunlock(&s->lk); ! 611: } ! 612: ! 613: error(Ebadarg); ! 614: ! 615: found: ! 616: if((ulong)arg >= s->base && (ulong)arg < s->top) { ! 617: qunlock(&s->lk); ! 618: error(Ebadarg); ! 619: } ! 620: u->p->seg[i] = 0; ! 621: qunlock(&s->lk); ! 622: putseg(s); ! 623: ! 624: /* Ensure we flush any entries from the lost segment */ ! 625: flushmmu(); ! 626: return 0; ! 627: } ! 628: ! 629: long ! 630: syssegfree(ulong *arg) ! 631: { ! 632: Segment *s; ! 633: ulong from, pages; ! 634: ! 635: from = PGROUND(arg[0]); ! 636: s = seg(u->p, from, 1); ! 637: if(s == 0) ! 638: error(Ebadarg); ! 639: ! 640: pages = (arg[1]+BY2PG-1)/BY2PG; ! 641: ! 642: if(from+pages*BY2PG > s->top) { ! 643: qunlock(&s->lk); ! 644: error(Ebadarg); ! 645: } ! 646: ! 647: mfreeseg(s, from, pages); ! 648: qunlock(&s->lk); ! 649: flushmmu(); ! 650: ! 651: return 0; ! 652: } ! 653: ! 654: /* For binary compatability */ ! 655: long ! 656: sysbrk_(ulong *arg) ! 657: { ! 658: return ibrk(arg[0], BSEG); ! 659: } ! 660: ! 661: long ! 662: sysrendezvous(ulong *arg) ! 663: { ! 664: Proc *p, **l; ! 665: int tag; ! 666: ulong val; ! 667: ! 668: tag = arg[0]; ! 669: l = &REND(u->p->pgrp, tag); ! 670: ! 671: lock(u->p->pgrp); ! 672: for(p = *l; p; p = p->rendhash) { ! 673: if(p->rendtag == tag) { ! 674: *l = p->rendhash; ! 675: val = p->rendval; ! 676: p->rendval = arg[1]; ! 677: /* Hard race avoidance */ ! 678: while(p->mach != 0) ! 679: ; ! 680: ready(p); ! 681: unlock(u->p->pgrp); ! 682: return val; ! 683: } ! 684: l = &p->rendhash; ! 685: } ! 686: ! 687: /* Going to sleep here */ ! 688: p = u->p; ! 689: p->rendtag = tag; ! 690: p->rendval = arg[1]; ! 691: p->rendhash = *l; ! 692: *l = p; ! 693: u->p->state = Rendezvous; ! 694: unlock(p->pgrp); ! 695: ! 696: sched(); ! 697: ! 698: return u->p->rendval; ! 699: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.