xref: /plan9/sys/src/9/port/sysproc.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include	"u.h"
23e12c5d1SDavid du Colombier #include	"../port/lib.h"
33e12c5d1SDavid du Colombier #include	"mem.h"
43e12c5d1SDavid du Colombier #include	"dat.h"
53e12c5d1SDavid du Colombier #include	"fns.h"
63e12c5d1SDavid du Colombier #include	"../port/error.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier #include	<a.out.h>
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier int	shargs(char*, int, char**);
113e12c5d1SDavid du Colombier 
123e12c5d1SDavid du Colombier long
133e12c5d1SDavid du Colombier sysr1(ulong *arg)
143e12c5d1SDavid du Colombier {
153e12c5d1SDavid du Colombier 	xsummary();
163e12c5d1SDavid du Colombier 	print("[%s %s %d] r1 = %d\n", u->p->user, u->p->text, u->p->pid, arg[0]);
173e12c5d1SDavid du Colombier 	return 0;
183e12c5d1SDavid du Colombier }
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier long
213e12c5d1SDavid du Colombier sysrfork(ulong *arg)
223e12c5d1SDavid du Colombier {
233e12c5d1SDavid du Colombier 	KMap *k;
243e12c5d1SDavid du Colombier 	Pgrp *opg;
253e12c5d1SDavid du Colombier 	Egrp *oeg;
263e12c5d1SDavid du Colombier 	Fgrp *ofg;
273e12c5d1SDavid du Colombier 	int n, i;
283e12c5d1SDavid du Colombier 	Proc *p, *parent;
293e12c5d1SDavid du Colombier 	ulong upa, pid, flag;
303e12c5d1SDavid du Colombier 	/*
313e12c5d1SDavid du Colombier 	 * used to compute last valid system stack address for copy
323e12c5d1SDavid du Colombier 	 */
333e12c5d1SDavid du Colombier 	int lastvar;
343e12c5d1SDavid du Colombier 
353e12c5d1SDavid du Colombier 	flag = arg[0];
363e12c5d1SDavid du Colombier 	p = u->p;
373e12c5d1SDavid du Colombier 	if((flag&RFPROC) == 0) {
383e12c5d1SDavid du Colombier 		if(flag & (RFNAMEG|RFCNAMEG)) {
393e12c5d1SDavid du Colombier 			if((flag & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG))
403e12c5d1SDavid du Colombier 				error(Ebadarg);
413e12c5d1SDavid du Colombier 			opg = p->pgrp;
423e12c5d1SDavid du Colombier 			p->pgrp = newpgrp();
433e12c5d1SDavid du Colombier 			if(flag & RFNAMEG)
443e12c5d1SDavid du Colombier 				pgrpcpy(p->pgrp, opg);
453e12c5d1SDavid du Colombier 			closepgrp(opg);
463e12c5d1SDavid du Colombier 		}
473e12c5d1SDavid du Colombier 		if(flag & (RFENVG|RFCENVG)) {
483e12c5d1SDavid du Colombier 			if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG))
493e12c5d1SDavid du Colombier 				error(Ebadarg);
503e12c5d1SDavid du Colombier 			oeg = p->egrp;
513e12c5d1SDavid du Colombier 			p->egrp = smalloc(sizeof(Egrp));
523e12c5d1SDavid du Colombier 			p->egrp->ref = 1;
533e12c5d1SDavid du Colombier 			if(flag & RFENVG)
543e12c5d1SDavid du Colombier 				envcpy(p->egrp, oeg);
553e12c5d1SDavid du Colombier 			closeegrp(oeg);
563e12c5d1SDavid du Colombier 		}
573e12c5d1SDavid du Colombier 		if(flag & RFFDG) {
583e12c5d1SDavid du Colombier 			ofg = p->fgrp;
593e12c5d1SDavid du Colombier 			p->fgrp = dupfgrp(ofg);
603e12c5d1SDavid du Colombier 			closefgrp(ofg);
613e12c5d1SDavid du Colombier 		}
623e12c5d1SDavid du Colombier 		else
633e12c5d1SDavid du Colombier 		if(flag & RFCFDG) {
643e12c5d1SDavid du Colombier 			ofg = p->fgrp;
653e12c5d1SDavid du Colombier 			p->fgrp = smalloc(sizeof(Fgrp));
663e12c5d1SDavid du Colombier 			p->fgrp->ref = 1;
673e12c5d1SDavid du Colombier 			closefgrp(ofg);
683e12c5d1SDavid du Colombier 		}
693e12c5d1SDavid du Colombier 		if(flag & RFNOTEG)
703e12c5d1SDavid du Colombier 			p->noteid = incref(&noteidalloc);
713e12c5d1SDavid du Colombier 		if(flag & (RFMEM|RFNOWAIT))
723e12c5d1SDavid du Colombier 			error(Ebadarg);
733e12c5d1SDavid du Colombier 		return 0;
743e12c5d1SDavid du Colombier 	}
753e12c5d1SDavid du Colombier 	/* Check flags before we commit */
763e12c5d1SDavid du Colombier 	if((flag & (RFFDG|RFCFDG)) == (RFFDG|RFCFDG))
773e12c5d1SDavid du Colombier 		error(Ebadarg);
783e12c5d1SDavid du Colombier 	if((flag & (RFNAMEG|RFCNAMEG)) == (RFNAMEG|RFCNAMEG))
793e12c5d1SDavid du Colombier 		error(Ebadarg);
803e12c5d1SDavid du Colombier 	if((flag & (RFENVG|RFCENVG)) == (RFENVG|RFCENVG))
813e12c5d1SDavid du Colombier 		error(Ebadarg);
823e12c5d1SDavid du Colombier 
833e12c5d1SDavid du Colombier 	p = newproc();
843e12c5d1SDavid du Colombier 	parent = u->p;
853e12c5d1SDavid du Colombier 
863e12c5d1SDavid du Colombier 	/* Page va of upage used as check in mapstack */
873e12c5d1SDavid du Colombier 	p->upage = newpage(0, 0, USERADDR|(p->pid&0xFFFF));
883e12c5d1SDavid du Colombier 	k = kmap(p->upage);
893e12c5d1SDavid du Colombier 	upa = VA(k);
903e12c5d1SDavid du Colombier 
913e12c5d1SDavid du Colombier 	/* Save time: only copy u-> data and useful stack */
923e12c5d1SDavid du Colombier 	memmove((void*)upa, u, sizeof(User));
933e12c5d1SDavid du Colombier 	n = USERADDR+BY2PG - (ulong)&lastvar;
943e12c5d1SDavid du Colombier 	n = (n+32) & ~(BY2WD-1);
953e12c5d1SDavid du Colombier 	memmove((void*)(upa+BY2PG-n), (void*)(USERADDR+BY2PG-n), n);
963e12c5d1SDavid du Colombier 	((User *)upa)->p = p;
973e12c5d1SDavid du Colombier 	kunmap(k);
983e12c5d1SDavid du Colombier 
993e12c5d1SDavid du Colombier 	/* Make a new set of memory segments */
1003e12c5d1SDavid du Colombier 	n = flag & RFMEM;
1013e12c5d1SDavid du Colombier 	for(i = 0; i < NSEG; i++)
1023e12c5d1SDavid du Colombier 		if(parent->seg[i])
103bd389b36SDavid du Colombier 			p->seg[i] = dupseg(parent->seg, i, n);
1043e12c5d1SDavid du Colombier 
1053e12c5d1SDavid du Colombier 	/* Refs */
1063e12c5d1SDavid du Colombier 	incref(u->dot);
1073e12c5d1SDavid du Colombier 
1083e12c5d1SDavid du Colombier 	/* File descriptors */
1093e12c5d1SDavid du Colombier 	if(flag & (RFFDG|RFCFDG)) {
1103e12c5d1SDavid du Colombier 		if(flag & RFFDG)
1113e12c5d1SDavid du Colombier 			p->fgrp = dupfgrp(parent->fgrp);
1123e12c5d1SDavid du Colombier 		else {
1133e12c5d1SDavid du Colombier 			p->fgrp = smalloc(sizeof(Fgrp));
1143e12c5d1SDavid du Colombier 			p->fgrp->ref = 1;
1153e12c5d1SDavid du Colombier 		}
1163e12c5d1SDavid du Colombier 	}
1173e12c5d1SDavid du Colombier 	else {
1183e12c5d1SDavid du Colombier 		p->fgrp = parent->fgrp;
1193e12c5d1SDavid du Colombier 		incref(p->fgrp);
1203e12c5d1SDavid du Colombier 	}
1213e12c5d1SDavid du Colombier 
1223e12c5d1SDavid du Colombier 	/* Process groups */
1233e12c5d1SDavid du Colombier 	if(flag & (RFNAMEG|RFCNAMEG)) {
1243e12c5d1SDavid du Colombier 		p->pgrp = newpgrp();
125bd389b36SDavid du Colombier 		if(flag & RFNAMEG)
1263e12c5d1SDavid du Colombier 			pgrpcpy(p->pgrp, parent->pgrp);
1273e12c5d1SDavid du Colombier 	}
1283e12c5d1SDavid du Colombier 	else {
1293e12c5d1SDavid du Colombier 		p->pgrp = parent->pgrp;
1303e12c5d1SDavid du Colombier 		incref(p->pgrp);
1313e12c5d1SDavid du Colombier 	}
1323e12c5d1SDavid du Colombier 
1333e12c5d1SDavid du Colombier 	/* Environment group */
1343e12c5d1SDavid du Colombier 	if(flag & (RFENVG|RFCENVG)) {
1353e12c5d1SDavid du Colombier 		p->egrp = smalloc(sizeof(Egrp));
1363e12c5d1SDavid du Colombier 		p->egrp->ref = 1;
1373e12c5d1SDavid du Colombier 		if(flag & RFENVG)
1383e12c5d1SDavid du Colombier 			envcpy(p->egrp, parent->egrp);
1393e12c5d1SDavid du Colombier 	}
1403e12c5d1SDavid du Colombier 	else {
1413e12c5d1SDavid du Colombier 		p->egrp = parent->egrp;
1423e12c5d1SDavid du Colombier 		incref(p->egrp);
1433e12c5d1SDavid du Colombier 	}
1443e12c5d1SDavid du Colombier 
1453e12c5d1SDavid du Colombier 	p->hang = parent->hang;
1463e12c5d1SDavid du Colombier 	p->procmode = parent->procmode;
1473e12c5d1SDavid du Colombier 
1483e12c5d1SDavid du Colombier 	if(setlabel(&p->sched)){
1493e12c5d1SDavid du Colombier 		/*
1503e12c5d1SDavid du Colombier 		 *  use u->p instead of p, because we don't trust the compiler, after a
1513e12c5d1SDavid du Colombier 		 *  gotolabel, to find the correct contents of a local variable.
1523e12c5d1SDavid du Colombier 		 */
1533e12c5d1SDavid du Colombier 		p = u->p;
1543e12c5d1SDavid du Colombier 		p->state = Running;
1553e12c5d1SDavid du Colombier 		p->mach = m;
1563e12c5d1SDavid du Colombier 		m->proc = p;
1573e12c5d1SDavid du Colombier 		spllo();
1583e12c5d1SDavid du Colombier 		return 0;
1593e12c5d1SDavid du Colombier 	}
1603e12c5d1SDavid du Colombier 
1613e12c5d1SDavid du Colombier 	p->parent = parent;
1623e12c5d1SDavid du Colombier 	p->parentpid = parent->pid;
1633e12c5d1SDavid du Colombier 	if(flag&RFNOWAIT)
1643e12c5d1SDavid du Colombier 		p->parentpid = 1;
1653e12c5d1SDavid du Colombier 	else {
1663e12c5d1SDavid du Colombier 		lock(&parent->exl);
1673e12c5d1SDavid du Colombier 		parent->nchild++;
1683e12c5d1SDavid du Colombier 		unlock(&parent->exl);
1693e12c5d1SDavid du Colombier 	}
1703e12c5d1SDavid du Colombier 	if((flag&RFNOTEG) == 0)
1713e12c5d1SDavid du Colombier 		p->noteid = parent->noteid;
1723e12c5d1SDavid du Colombier 
1733e12c5d1SDavid du Colombier 	p->fpstate = parent->fpstate;
1743e12c5d1SDavid du Colombier 	pid = p->pid;
1753e12c5d1SDavid du Colombier 	memset(p->time, 0, sizeof(p->time));
1763e12c5d1SDavid du Colombier 	p->time[TReal] = MACHP(0)->ticks;
1773e12c5d1SDavid du Colombier 	memmove(p->text, parent->text, NAMELEN);
1783e12c5d1SDavid du Colombier 	memmove(p->user, parent->user, NAMELEN);
1793e12c5d1SDavid du Colombier 	/*
1803e12c5d1SDavid du Colombier 	 *  since the bss/data segments are now shareable,
1813e12c5d1SDavid du Colombier 	 *  any mmu info about this process is now stale
1823e12c5d1SDavid du Colombier 	 *  (i.e. has bad properties) and has to be discarded.
1833e12c5d1SDavid du Colombier 	 */
1843e12c5d1SDavid du Colombier 	flushmmu();
185*219b2ee8SDavid du Colombier 	p->priority = u->p->priority;
186*219b2ee8SDavid du Colombier 	p->basepri = u->p->basepri;
187*219b2ee8SDavid du Colombier 	p->mp = u->p->mp;
1883e12c5d1SDavid du Colombier 	ready(p);
189*219b2ee8SDavid du Colombier 	sched();
1903e12c5d1SDavid du Colombier 	return pid;
1913e12c5d1SDavid du Colombier }
1923e12c5d1SDavid du Colombier 
1933e12c5d1SDavid du Colombier static ulong
1943e12c5d1SDavid du Colombier l2be(long l)
1953e12c5d1SDavid du Colombier {
1963e12c5d1SDavid du Colombier 	uchar *cp;
1973e12c5d1SDavid du Colombier 
1983e12c5d1SDavid du Colombier 	cp = (uchar*)&l;
1993e12c5d1SDavid du Colombier 	return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
2003e12c5d1SDavid du Colombier }
2013e12c5d1SDavid du Colombier 
2023e12c5d1SDavid du Colombier long
2033e12c5d1SDavid du Colombier sysexec(ulong *arg)
2043e12c5d1SDavid du Colombier {
2053e12c5d1SDavid du Colombier 	Proc *p;
2063e12c5d1SDavid du Colombier 	Segment *s, *ts;
2073e12c5d1SDavid du Colombier 	ulong t, d, b;
2083e12c5d1SDavid du Colombier 	int i;
2093e12c5d1SDavid du Colombier 	Chan *tc;
2103e12c5d1SDavid du Colombier 	char **argv, **argp;
2113e12c5d1SDavid du Colombier 	char *a, *charp, *file;
2123e12c5d1SDavid du Colombier 	char *progarg[sizeof(Exec)/2+1], elem[NAMELEN];
2133e12c5d1SDavid du Colombier 	ulong ssize, spage, nargs, nbytes, n, bssend;
2143e12c5d1SDavid du Colombier 	int indir;
2153e12c5d1SDavid du Colombier 	Exec exec;
2163e12c5d1SDavid du Colombier 	char line[sizeof(Exec)];
2173e12c5d1SDavid du Colombier 	Fgrp *f;
2183e12c5d1SDavid du Colombier 	Image *img;
2193e12c5d1SDavid du Colombier 	ulong magic, text, entry, data, bss;
2203e12c5d1SDavid du Colombier 
2213e12c5d1SDavid du Colombier 	p = u->p;
2223e12c5d1SDavid du Colombier 	validaddr(arg[0], 1, 0);
2233e12c5d1SDavid du Colombier 	file = (char*)arg[0];
2243e12c5d1SDavid du Colombier 	indir = 0;
2253e12c5d1SDavid du Colombier     Header:
2263e12c5d1SDavid du Colombier 	tc = namec(file, Aopen, OEXEC, 0);
2273e12c5d1SDavid du Colombier 	if(waserror()){
2283e12c5d1SDavid du Colombier 		close(tc);
2293e12c5d1SDavid du Colombier 		nexterror();
2303e12c5d1SDavid du Colombier 	}
2313e12c5d1SDavid du Colombier 	if(!indir)
2323e12c5d1SDavid du Colombier 		strcpy(elem, u->elem);
2333e12c5d1SDavid du Colombier 
2343e12c5d1SDavid du Colombier 	n = (*devtab[tc->type].read)(tc, &exec, sizeof(Exec), 0);
2353e12c5d1SDavid du Colombier 	if(n < 2)
2363e12c5d1SDavid du Colombier     Err:
2373e12c5d1SDavid du Colombier 		error(Ebadexec);
2383e12c5d1SDavid du Colombier 	magic = l2be(exec.magic);
2393e12c5d1SDavid du Colombier 	text = l2be(exec.text);
2403e12c5d1SDavid du Colombier 	entry = l2be(exec.entry);
2413e12c5d1SDavid du Colombier 	if(n==sizeof(Exec) && magic==AOUT_MAGIC){
2423e12c5d1SDavid du Colombier 		if((text&KZERO)
2433e12c5d1SDavid du Colombier 		|| entry < UTZERO+sizeof(Exec)
2443e12c5d1SDavid du Colombier 		|| entry >= UTZERO+sizeof(Exec)+text)
2453e12c5d1SDavid du Colombier 			goto Err;
2463e12c5d1SDavid du Colombier 		goto Binary;
2473e12c5d1SDavid du Colombier 	}
2483e12c5d1SDavid du Colombier 
2493e12c5d1SDavid du Colombier 	/*
2503e12c5d1SDavid du Colombier 	 * Process #! /bin/sh args ...
2513e12c5d1SDavid du Colombier 	 */
2523e12c5d1SDavid du Colombier 	memmove(line, &exec, sizeof(Exec));
2533e12c5d1SDavid du Colombier 	if(indir || line[0]!='#' || line[1]!='!')
2543e12c5d1SDavid du Colombier 		goto Err;
2553e12c5d1SDavid du Colombier 	n = shargs(line, n, progarg);
2563e12c5d1SDavid du Colombier 	if(n == 0)
2573e12c5d1SDavid du Colombier 		goto Err;
2583e12c5d1SDavid du Colombier 	indir = 1;
2593e12c5d1SDavid du Colombier 	/*
2603e12c5d1SDavid du Colombier 	 * First arg becomes complete file name
2613e12c5d1SDavid du Colombier 	 */
2623e12c5d1SDavid du Colombier 	progarg[n++] = file;
2633e12c5d1SDavid du Colombier 	progarg[n] = 0;
2643e12c5d1SDavid du Colombier 	validaddr(arg[1], BY2WD, 1);
2653e12c5d1SDavid du Colombier 	arg[1] += BY2WD;
2663e12c5d1SDavid du Colombier 	file = progarg[0];
2673e12c5d1SDavid du Colombier 	progarg[0] = elem;
2683e12c5d1SDavid du Colombier 	poperror();
2693e12c5d1SDavid du Colombier 	close(tc);
2703e12c5d1SDavid du Colombier 	goto Header;
2713e12c5d1SDavid du Colombier 
2723e12c5d1SDavid du Colombier     Binary:
2733e12c5d1SDavid du Colombier 	poperror();
2743e12c5d1SDavid du Colombier 	data = l2be(exec.data);
2753e12c5d1SDavid du Colombier 	bss = l2be(exec.bss);
2763e12c5d1SDavid du Colombier 	t = (UTZERO+sizeof(Exec)+text+(BY2PG-1)) & ~(BY2PG-1);
2773e12c5d1SDavid du Colombier 	d = (t + data + (BY2PG-1)) & ~(BY2PG-1);
2783e12c5d1SDavid du Colombier 	bssend = t + data + bss;
2793e12c5d1SDavid du Colombier 	b = (bssend + (BY2PG-1)) & ~(BY2PG-1);
2803e12c5d1SDavid du Colombier 	if((t|d|b) & KZERO)
2813e12c5d1SDavid du Colombier 		error(Ebadexec);
2823e12c5d1SDavid du Colombier 
2833e12c5d1SDavid du Colombier 	/*
2843e12c5d1SDavid du Colombier 	 * Args: pass 1: count
2853e12c5d1SDavid du Colombier 	 */
2863e12c5d1SDavid du Colombier 	nbytes = BY2WD;		/* hole for profiling clock at top of stack */
2873e12c5d1SDavid du Colombier 	nargs = 0;
2883e12c5d1SDavid du Colombier 	if(indir){
2893e12c5d1SDavid du Colombier 		argp = progarg;
2903e12c5d1SDavid du Colombier 		while(*argp){
2913e12c5d1SDavid du Colombier 			a = *argp++;
2923e12c5d1SDavid du Colombier 			nbytes += strlen(a) + 1;
2933e12c5d1SDavid du Colombier 			nargs++;
2943e12c5d1SDavid du Colombier 		}
2953e12c5d1SDavid du Colombier 	}
2963e12c5d1SDavid du Colombier 	evenaddr(arg[1]);
2973e12c5d1SDavid du Colombier 	argp = (char**)arg[1];
2983e12c5d1SDavid du Colombier 	validaddr((ulong)argp, BY2WD, 0);
2993e12c5d1SDavid du Colombier 	while(*argp){
3003e12c5d1SDavid du Colombier 		a = *argp++;
3013e12c5d1SDavid du Colombier 		if(((ulong)argp&(BY2PG-1)) < BY2WD)
3023e12c5d1SDavid du Colombier 			validaddr((ulong)argp, BY2WD, 0);
3033e12c5d1SDavid du Colombier 		validaddr((ulong)a, 1, 0);
304*219b2ee8SDavid du Colombier 		nbytes += (vmemchr(a, 0, 0x7FFFFFFF) - a) + 1;
3053e12c5d1SDavid du Colombier 		nargs++;
3063e12c5d1SDavid du Colombier 	}
3073e12c5d1SDavid du Colombier 	ssize = BY2WD*(nargs+1) + ((nbytes+(BY2WD-1)) & ~(BY2WD-1));
308bd389b36SDavid du Colombier 
3093e12c5d1SDavid du Colombier 	/*
3103e12c5d1SDavid du Colombier 	 * 8-byte align SP for those (e.g. sparc) that need it.
3113e12c5d1SDavid du Colombier 	 * execregs() will subtract another 4 bytes for argc.
3123e12c5d1SDavid du Colombier 	 */
3133e12c5d1SDavid du Colombier 	if((ssize+4) & 7)
3143e12c5d1SDavid du Colombier 		ssize += 4;
3153e12c5d1SDavid du Colombier 	spage = (ssize+(BY2PG-1)) >> PGSHIFT;
3163e12c5d1SDavid du Colombier 	/*
3173e12c5d1SDavid du Colombier 	 * Build the stack segment, putting it in kernel virtual for the moment
3183e12c5d1SDavid du Colombier 	 */
3193e12c5d1SDavid du Colombier 	if(spage > TSTKSIZ)
3203e12c5d1SDavid du Colombier 		error(Enovmem);
3213e12c5d1SDavid du Colombier 
3223e12c5d1SDavid du Colombier 	p->seg[ESEG] = newseg(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG);
3233e12c5d1SDavid du Colombier 
3243e12c5d1SDavid du Colombier 	/*
3253e12c5d1SDavid du Colombier 	 * Args: pass 2: assemble; the pages will be faulted in
3263e12c5d1SDavid du Colombier 	 */
3273e12c5d1SDavid du Colombier 	argv = (char**)(TSTKTOP - ssize);
3283e12c5d1SDavid du Colombier 	charp = (char*)(TSTKTOP - nbytes);
3293e12c5d1SDavid du Colombier 	if(indir)
3303e12c5d1SDavid du Colombier 		argp = progarg;
3313e12c5d1SDavid du Colombier 	else
3323e12c5d1SDavid du Colombier 		argp = (char**)arg[1];
3333e12c5d1SDavid du Colombier 
3343e12c5d1SDavid du Colombier 	for(i=0; i<nargs; i++){
3353e12c5d1SDavid du Colombier 		if(indir && *argp==0) {
3363e12c5d1SDavid du Colombier 			indir = 0;
3373e12c5d1SDavid du Colombier 			argp = (char**)arg[1];
3383e12c5d1SDavid du Colombier 		}
3393e12c5d1SDavid du Colombier 		*argv++ = charp + (USTKTOP-TSTKTOP);
3403e12c5d1SDavid du Colombier 		n = strlen(*argp) + 1;
3413e12c5d1SDavid du Colombier 		memmove(charp, *argp++, n);
3423e12c5d1SDavid du Colombier 		charp += n;
3433e12c5d1SDavid du Colombier 	}
3443e12c5d1SDavid du Colombier 
3453e12c5d1SDavid du Colombier 	memmove(p->text, elem, NAMELEN);
3463e12c5d1SDavid du Colombier 
3473e12c5d1SDavid du Colombier 	/*
348bd389b36SDavid du Colombier 	 * Committed.
349bd389b36SDavid du Colombier 	 * Free old memory.
350bd389b36SDavid du Colombier 	 * Special segments are maintained accross exec
3513e12c5d1SDavid du Colombier 	 */
3523e12c5d1SDavid du Colombier 	for(i = SSEG; i <= BSEG; i++) {
3533e12c5d1SDavid du Colombier 		putseg(p->seg[i]);
354*219b2ee8SDavid du Colombier 		/* prevent a second free if we have an error */
355*219b2ee8SDavid du Colombier 		p->seg[i] = 0;
356*219b2ee8SDavid du Colombier 	}
357*219b2ee8SDavid du Colombier 	for(i = BSEG+1; i < NSEG; i++) {
358*219b2ee8SDavid du Colombier 		s = p->seg[i];
359*219b2ee8SDavid du Colombier 		if(s != 0 && (s->type&SG_CEXEC)) {
360*219b2ee8SDavid du Colombier 			putseg(s);
361*219b2ee8SDavid du Colombier 			p->seg[i] = 0;
362*219b2ee8SDavid du Colombier 		}
3633e12c5d1SDavid du Colombier 	}
3643e12c5d1SDavid du Colombier 
3653e12c5d1SDavid du Colombier 	/*
3663e12c5d1SDavid du Colombier 	 * Close on exec
3673e12c5d1SDavid du Colombier 	 */
3683e12c5d1SDavid du Colombier 	f = u->p->fgrp;
3693e12c5d1SDavid du Colombier 	for(i=0; i<=f->maxfd; i++)
3703e12c5d1SDavid du Colombier 		fdclose(i, CCEXEC);
3713e12c5d1SDavid du Colombier 
3723e12c5d1SDavid du Colombier 	/* Text.  Shared. Attaches to cache image if possible */
3733e12c5d1SDavid du Colombier 	/* attachimage returns a locked cache image */
3743e12c5d1SDavid du Colombier 	img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (t-UTZERO)>>PGSHIFT);
3753e12c5d1SDavid du Colombier 	ts = img->s;
3763e12c5d1SDavid du Colombier 	p->seg[TSEG] = ts;
3773e12c5d1SDavid du Colombier 	ts->flushme = 1;
3783e12c5d1SDavid du Colombier 	ts->fstart = 0;
3793e12c5d1SDavid du Colombier 	ts->flen = sizeof(Exec)+text;
3803e12c5d1SDavid du Colombier 	unlock(img);
3813e12c5d1SDavid du Colombier 
3823e12c5d1SDavid du Colombier 	/* Data. Shared. */
3833e12c5d1SDavid du Colombier 	s = newseg(SG_DATA, t, (d-t)>>PGSHIFT);
3843e12c5d1SDavid du Colombier 	p->seg[DSEG] = s;
3853e12c5d1SDavid du Colombier 
3863e12c5d1SDavid du Colombier 	/* Attached by hand */
3873e12c5d1SDavid du Colombier 	incref(img);
3883e12c5d1SDavid du Colombier 	s->image = img;
3893e12c5d1SDavid du Colombier 	s->fstart = ts->fstart+ts->flen;
3903e12c5d1SDavid du Colombier 	s->flen = data;
3913e12c5d1SDavid du Colombier 
3923e12c5d1SDavid du Colombier 	/* BSS. Zero fill on demand */
3933e12c5d1SDavid du Colombier 	p->seg[BSEG] = newseg(SG_BSS, d, (b-d)>>PGSHIFT);
3943e12c5d1SDavid du Colombier 
3953e12c5d1SDavid du Colombier 	/*
3963e12c5d1SDavid du Colombier 	 * Move the stack
3973e12c5d1SDavid du Colombier 	 */
3983e12c5d1SDavid du Colombier 	s = p->seg[ESEG];
3993e12c5d1SDavid du Colombier 	p->seg[ESEG] = 0;
4003e12c5d1SDavid du Colombier 	p->seg[SSEG] = s;
4013e12c5d1SDavid du Colombier 	s->base = USTKTOP-USTKSIZE;
4023e12c5d1SDavid du Colombier 	s->top = USTKTOP;
4033e12c5d1SDavid du Colombier 	relocateseg(s, TSTKTOP-USTKTOP);
4043e12c5d1SDavid du Colombier 
405*219b2ee8SDavid du Colombier 	/*
406*219b2ee8SDavid du Colombier 	 *  '/' processes are higher priority (hack to make /ip more responsive).
407*219b2ee8SDavid du Colombier 	 */
408*219b2ee8SDavid du Colombier 	if(devchar[tc->type] == L'/')
409*219b2ee8SDavid du Colombier 		u->p->basepri = PriRoot;
410*219b2ee8SDavid du Colombier 	u->p->priority = u->p->basepri;
4113e12c5d1SDavid du Colombier 	close(tc);
4123e12c5d1SDavid du Colombier 
4133e12c5d1SDavid du Colombier 	/*
4143e12c5d1SDavid du Colombier 	 *  At this point, the mmu contains info about the old address
4153e12c5d1SDavid du Colombier 	 *  space and needs to be flushed
4163e12c5d1SDavid du Colombier 	 */
4173e12c5d1SDavid du Colombier 	flushmmu();
4183e12c5d1SDavid du Colombier 	qlock(&p->debug);
4193e12c5d1SDavid du Colombier 	u->nnote = 0;
4203e12c5d1SDavid du Colombier 	u->notify = 0;
4213e12c5d1SDavid du Colombier 	u->notified = 0;
4223e12c5d1SDavid du Colombier 	procsetup(p);
4233e12c5d1SDavid du Colombier 	qunlock(&p->debug);
4243e12c5d1SDavid du Colombier 	if(p->hang)
4253e12c5d1SDavid du Colombier 		p->procctl = Proc_stopme;
4263e12c5d1SDavid du Colombier 
4273e12c5d1SDavid du Colombier 	return execregs(entry, ssize, nargs);
4283e12c5d1SDavid du Colombier }
4293e12c5d1SDavid du Colombier 
4303e12c5d1SDavid du Colombier int
4313e12c5d1SDavid du Colombier shargs(char *s, int n, char **ap)
4323e12c5d1SDavid du Colombier {
4333e12c5d1SDavid du Colombier 	int i;
4343e12c5d1SDavid du Colombier 
435bd389b36SDavid du Colombier 	s += 2;
436bd389b36SDavid du Colombier 	n -= 2;		/* skip #! */
4373e12c5d1SDavid du Colombier 	for(i=0; s[i]!='\n'; i++)
4383e12c5d1SDavid du Colombier 		if(i == n-1)
4393e12c5d1SDavid du Colombier 			return 0;
4403e12c5d1SDavid du Colombier 	s[i] = 0;
4413e12c5d1SDavid du Colombier 	*ap = 0;
4423e12c5d1SDavid du Colombier 	i = 0;
4433e12c5d1SDavid du Colombier 	for(;;){
4443e12c5d1SDavid du Colombier 		while(*s==' ' || *s=='\t')
4453e12c5d1SDavid du Colombier 			s++;
4463e12c5d1SDavid du Colombier 		if(*s == 0)
4473e12c5d1SDavid du Colombier 			break;
4483e12c5d1SDavid du Colombier 		i++;
4493e12c5d1SDavid du Colombier 		*ap++ = s;
4503e12c5d1SDavid du Colombier 		*ap = 0;
4513e12c5d1SDavid du Colombier 		while(*s && *s!=' ' && *s!='\t')
4523e12c5d1SDavid du Colombier 			s++;
4533e12c5d1SDavid du Colombier 		if(*s == 0)
4543e12c5d1SDavid du Colombier 			break;
4553e12c5d1SDavid du Colombier 		else
4563e12c5d1SDavid du Colombier 			*s++ = 0;
4573e12c5d1SDavid du Colombier 	}
4583e12c5d1SDavid du Colombier 	return i;
4593e12c5d1SDavid du Colombier }
4603e12c5d1SDavid du Colombier 
4613e12c5d1SDavid du Colombier int
4623e12c5d1SDavid du Colombier return0(void *a)
4633e12c5d1SDavid du Colombier {
4643e12c5d1SDavid du Colombier 	USED(a);
4653e12c5d1SDavid du Colombier 	return 0;
4663e12c5d1SDavid du Colombier }
4673e12c5d1SDavid du Colombier 
4683e12c5d1SDavid du Colombier long
4693e12c5d1SDavid du Colombier syssleep(ulong *arg)
4703e12c5d1SDavid du Colombier {
471*219b2ee8SDavid du Colombier 	int n;
472*219b2ee8SDavid du Colombier 
473*219b2ee8SDavid du Colombier 	n = arg[0];
474*219b2ee8SDavid du Colombier 	if(n == 0){
475*219b2ee8SDavid du Colombier 		sched();	/* yield */
476*219b2ee8SDavid du Colombier 		return 0;
477*219b2ee8SDavid du Colombier 	}
478*219b2ee8SDavid du Colombier 	if(MS2TK(n) == 0)	/* sleep for at least one tick */
479*219b2ee8SDavid du Colombier 		n = TK2MS(1);
480*219b2ee8SDavid du Colombier 	tsleep(&u->p->sleep, return0, 0, n);
4813e12c5d1SDavid du Colombier 
4823e12c5d1SDavid du Colombier 	return 0;
4833e12c5d1SDavid du Colombier }
4843e12c5d1SDavid du Colombier 
4853e12c5d1SDavid du Colombier long
4863e12c5d1SDavid du Colombier sysalarm(ulong *arg)
4873e12c5d1SDavid du Colombier {
4883e12c5d1SDavid du Colombier 	return procalarm(arg[0]);
4893e12c5d1SDavid du Colombier }
4903e12c5d1SDavid du Colombier 
4913e12c5d1SDavid du Colombier long
4923e12c5d1SDavid du Colombier sysexits(ulong *arg)
4933e12c5d1SDavid du Colombier {
4943e12c5d1SDavid du Colombier 	char *status;
4953e12c5d1SDavid du Colombier 	char *inval = "invalid exit string";
496*219b2ee8SDavid du Colombier 	char buf[ERRLEN];
4973e12c5d1SDavid du Colombier 
4983e12c5d1SDavid du Colombier 	status = (char*)arg[0];
4993e12c5d1SDavid du Colombier 	if(status){
5003e12c5d1SDavid du Colombier 		if(waserror())
5013e12c5d1SDavid du Colombier 			status = inval;
5023e12c5d1SDavid du Colombier 		else{
5033e12c5d1SDavid du Colombier 			validaddr((ulong)status, 1, 0);
504*219b2ee8SDavid du Colombier 			if(vmemchr(status, 0, ERRLEN) == 0){
505*219b2ee8SDavid du Colombier 				memmove(buf, status, ERRLEN);
506*219b2ee8SDavid du Colombier 				buf[ERRLEN-1] = 0;
507*219b2ee8SDavid du Colombier 				status = buf;
508*219b2ee8SDavid du Colombier 			}
5093e12c5d1SDavid du Colombier 		}
5103e12c5d1SDavid du Colombier 		poperror();
5113e12c5d1SDavid du Colombier 
5123e12c5d1SDavid du Colombier 	}
5133e12c5d1SDavid du Colombier 	pexit(status, 1);
5143e12c5d1SDavid du Colombier 	return 0;		/* not reached */
5153e12c5d1SDavid du Colombier }
5163e12c5d1SDavid du Colombier 
5173e12c5d1SDavid du Colombier long
5183e12c5d1SDavid du Colombier syswait(ulong *arg)
5193e12c5d1SDavid du Colombier {
5203e12c5d1SDavid du Colombier 	if(arg[0]){
5213e12c5d1SDavid du Colombier 		validaddr(arg[0], sizeof(Waitmsg), 1);
5223e12c5d1SDavid du Colombier 		evenaddr(arg[0]);
5233e12c5d1SDavid du Colombier 	}
5243e12c5d1SDavid du Colombier 	return pwait((Waitmsg*)arg[0]);
5253e12c5d1SDavid du Colombier }
5263e12c5d1SDavid du Colombier 
5273e12c5d1SDavid du Colombier long
5283e12c5d1SDavid du Colombier sysdeath(ulong *arg)
5293e12c5d1SDavid du Colombier {
5303e12c5d1SDavid du Colombier 	USED(arg);
5313e12c5d1SDavid du Colombier 	pprint("deprecated system call\n");
5323e12c5d1SDavid du Colombier 	pexit("Suicide", 0);
5333e12c5d1SDavid du Colombier 	return 0;	/* not reached */
5343e12c5d1SDavid du Colombier }
5353e12c5d1SDavid du Colombier 
5363e12c5d1SDavid du Colombier long
5373e12c5d1SDavid du Colombier syserrstr(ulong *arg)
5383e12c5d1SDavid du Colombier {
539*219b2ee8SDavid du Colombier 	char tmp[ERRLEN];
540*219b2ee8SDavid du Colombier 
5413e12c5d1SDavid du Colombier 	validaddr(arg[0], ERRLEN, 1);
542*219b2ee8SDavid du Colombier 	memmove(tmp, (char*)arg[0], ERRLEN);
5433e12c5d1SDavid du Colombier 	memmove((char*)arg[0], u->error, ERRLEN);
544*219b2ee8SDavid du Colombier 	memmove(u->error, tmp, ERRLEN);
5453e12c5d1SDavid du Colombier 	return 0;
5463e12c5d1SDavid du Colombier }
5473e12c5d1SDavid du Colombier 
5483e12c5d1SDavid du Colombier long
5493e12c5d1SDavid du Colombier sysnotify(ulong *arg)
5503e12c5d1SDavid du Colombier {
5513e12c5d1SDavid du Colombier 	USED(arg);
5523e12c5d1SDavid du Colombier 	if(arg[0] != 0)
5533e12c5d1SDavid du Colombier 		validaddr(arg[0], sizeof(ulong), 0);
5543e12c5d1SDavid du Colombier 	u->notify = (int(*)(void*, char*))(arg[0]);
5553e12c5d1SDavid du Colombier 	return 0;
5563e12c5d1SDavid du Colombier }
5573e12c5d1SDavid du Colombier 
5583e12c5d1SDavid du Colombier long
5593e12c5d1SDavid du Colombier sysnoted(ulong *arg)
5603e12c5d1SDavid du Colombier {
561*219b2ee8SDavid du Colombier 	if(arg[0]!=NRSTR && !u->notified)
5623e12c5d1SDavid du Colombier 		error(Egreg);
5633e12c5d1SDavid du Colombier 	return 0;
5643e12c5d1SDavid du Colombier }
5653e12c5d1SDavid du Colombier 
5663e12c5d1SDavid du Colombier long
5673e12c5d1SDavid du Colombier syssegbrk(ulong *arg)
5683e12c5d1SDavid du Colombier {
5693e12c5d1SDavid du Colombier 	Segment *s;
5703e12c5d1SDavid du Colombier 	int i;
5713e12c5d1SDavid du Colombier 
572*219b2ee8SDavid du Colombier 	for(i = 0; i < NSEG; i++) {
5733e12c5d1SDavid du Colombier 		if(s = u->p->seg[i]) {
5743e12c5d1SDavid du Colombier 			if(arg[0] >= s->base && arg[0] < s->top) {
5753e12c5d1SDavid du Colombier 				switch(s->type&SG_TYPE) {
5763e12c5d1SDavid du Colombier 				case SG_TEXT:
5773e12c5d1SDavid du Colombier 				case SG_DATA:
578*219b2ee8SDavid du Colombier 				case SG_STACK:
5793e12c5d1SDavid du Colombier 					error(Ebadarg);
5803e12c5d1SDavid du Colombier 				default:
5813e12c5d1SDavid du Colombier 					return ibrk(arg[1], i);
5823e12c5d1SDavid du Colombier 				}
5833e12c5d1SDavid du Colombier 			}
5843e12c5d1SDavid du Colombier 		}
585*219b2ee8SDavid du Colombier 	}
5863e12c5d1SDavid du Colombier 
5873e12c5d1SDavid du Colombier 	error(Ebadarg);
5883e12c5d1SDavid du Colombier 	return 0;		/* not reached */
5893e12c5d1SDavid du Colombier }
5903e12c5d1SDavid du Colombier 
5913e12c5d1SDavid du Colombier long
5923e12c5d1SDavid du Colombier syssegattach(ulong *arg)
5933e12c5d1SDavid du Colombier {
5943e12c5d1SDavid du Colombier 	return segattach(u->p, arg[0], (char*)arg[1], arg[2], arg[3]);
5953e12c5d1SDavid du Colombier }
5963e12c5d1SDavid du Colombier 
5973e12c5d1SDavid du Colombier long
5983e12c5d1SDavid du Colombier syssegdetach(ulong *arg)
5993e12c5d1SDavid du Colombier {
6003e12c5d1SDavid du Colombier 	int i;
6013e12c5d1SDavid du Colombier 	Segment *s;
6023e12c5d1SDavid du Colombier 
6033e12c5d1SDavid du Colombier 	s = 0;
6043e12c5d1SDavid du Colombier 	for(i = 0; i < NSEG; i++)
6053e12c5d1SDavid du Colombier 		if(s = u->p->seg[i]) {
6063e12c5d1SDavid du Colombier 			qlock(&s->lk);
6073e12c5d1SDavid du Colombier 			if((arg[0] >= s->base && arg[0] < s->top) ||
6083e12c5d1SDavid du Colombier 			   (s->top == s->base && arg[0] == s->base))
6093e12c5d1SDavid du Colombier 				goto found;
6103e12c5d1SDavid du Colombier 			qunlock(&s->lk);
6113e12c5d1SDavid du Colombier 		}
6123e12c5d1SDavid du Colombier 
6133e12c5d1SDavid du Colombier 	error(Ebadarg);
6143e12c5d1SDavid du Colombier 
6153e12c5d1SDavid du Colombier found:
6163e12c5d1SDavid du Colombier 	if((ulong)arg >= s->base && (ulong)arg < s->top) {
6173e12c5d1SDavid du Colombier 		qunlock(&s->lk);
6183e12c5d1SDavid du Colombier 		error(Ebadarg);
6193e12c5d1SDavid du Colombier 	}
6203e12c5d1SDavid du Colombier 	u->p->seg[i] = 0;
6213e12c5d1SDavid du Colombier 	qunlock(&s->lk);
6223e12c5d1SDavid du Colombier 	putseg(s);
6233e12c5d1SDavid du Colombier 
6243e12c5d1SDavid du Colombier 	/* Ensure we flush any entries from the lost segment */
6253e12c5d1SDavid du Colombier 	flushmmu();
6263e12c5d1SDavid du Colombier 	return 0;
6273e12c5d1SDavid du Colombier }
6283e12c5d1SDavid du Colombier 
6293e12c5d1SDavid du Colombier long
6303e12c5d1SDavid du Colombier syssegfree(ulong *arg)
6313e12c5d1SDavid du Colombier {
6323e12c5d1SDavid du Colombier 	Segment *s;
6333e12c5d1SDavid du Colombier 	ulong from, pages;
6343e12c5d1SDavid du Colombier 
6353e12c5d1SDavid du Colombier 	from = PGROUND(arg[0]);
6363e12c5d1SDavid du Colombier 	s = seg(u->p, from, 1);
6373e12c5d1SDavid du Colombier 	if(s == 0)
6383e12c5d1SDavid du Colombier 		error(Ebadarg);
6393e12c5d1SDavid du Colombier 
6403e12c5d1SDavid du Colombier 	pages = (arg[1]+BY2PG-1)/BY2PG;
6413e12c5d1SDavid du Colombier 
6423e12c5d1SDavid du Colombier 	if(from+pages*BY2PG > s->top) {
6433e12c5d1SDavid du Colombier 		qunlock(&s->lk);
6443e12c5d1SDavid du Colombier 		error(Ebadarg);
6453e12c5d1SDavid du Colombier 	}
6463e12c5d1SDavid du Colombier 
6473e12c5d1SDavid du Colombier 	mfreeseg(s, from, pages);
6483e12c5d1SDavid du Colombier 	qunlock(&s->lk);
649bd389b36SDavid du Colombier 	flushmmu();
6503e12c5d1SDavid du Colombier 
6513e12c5d1SDavid du Colombier 	return 0;
6523e12c5d1SDavid du Colombier }
6533e12c5d1SDavid du Colombier 
6543e12c5d1SDavid du Colombier /* For binary compatability */
6553e12c5d1SDavid du Colombier long
6563e12c5d1SDavid du Colombier sysbrk_(ulong *arg)
6573e12c5d1SDavid du Colombier {
6583e12c5d1SDavid du Colombier 	return ibrk(arg[0], BSEG);
6593e12c5d1SDavid du Colombier }
6603e12c5d1SDavid du Colombier 
6613e12c5d1SDavid du Colombier long
6623e12c5d1SDavid du Colombier sysrendezvous(ulong *arg)
6633e12c5d1SDavid du Colombier {
6643e12c5d1SDavid du Colombier 	Proc *p, **l;
665*219b2ee8SDavid du Colombier 	int tag;
6663e12c5d1SDavid du Colombier 	ulong val;
6673e12c5d1SDavid du Colombier 
6683e12c5d1SDavid du Colombier 	tag = arg[0];
6693e12c5d1SDavid du Colombier 	l = &REND(u->p->pgrp, tag);
6703e12c5d1SDavid du Colombier 
6713e12c5d1SDavid du Colombier 	lock(u->p->pgrp);
6723e12c5d1SDavid du Colombier 	for(p = *l; p; p = p->rendhash) {
6733e12c5d1SDavid du Colombier 		if(p->rendtag == tag) {
6743e12c5d1SDavid du Colombier 			*l = p->rendhash;
6753e12c5d1SDavid du Colombier 			val = p->rendval;
6763e12c5d1SDavid du Colombier 			p->rendval = arg[1];
677*219b2ee8SDavid du Colombier 			/* Hard race avoidance */
678*219b2ee8SDavid du Colombier 			while(p->mach != 0)
6793e12c5d1SDavid du Colombier 				;
6803e12c5d1SDavid du Colombier 			ready(p);
6813e12c5d1SDavid du Colombier 			unlock(u->p->pgrp);
6823e12c5d1SDavid du Colombier 			return val;
6833e12c5d1SDavid du Colombier 		}
6843e12c5d1SDavid du Colombier 		l = &p->rendhash;
6853e12c5d1SDavid du Colombier 	}
6863e12c5d1SDavid du Colombier 
6873e12c5d1SDavid du Colombier 	/* Going to sleep here */
6883e12c5d1SDavid du Colombier 	p = u->p;
6893e12c5d1SDavid du Colombier 	p->rendtag = tag;
6903e12c5d1SDavid du Colombier 	p->rendval = arg[1];
6913e12c5d1SDavid du Colombier 	p->rendhash = *l;
6923e12c5d1SDavid du Colombier 	*l = p;
6933e12c5d1SDavid du Colombier 	u->p->state = Rendezvous;
694*219b2ee8SDavid du Colombier 	unlock(p->pgrp);
695*219b2ee8SDavid du Colombier 
6963e12c5d1SDavid du Colombier 	sched();
6973e12c5d1SDavid du Colombier 
6983e12c5d1SDavid du Colombier 	return u->p->rendval;
6993e12c5d1SDavid du Colombier }
700