|
|
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.