-/* kern_proc.c 3.4 %H% */
+/* kern_proc.c 4.8 %G% */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/inode.h"
#include "../h/seg.h"
#include "../h/acct.h"
+#include "/usr/include/wait.h"
#include "../h/pte.h"
#include "../h/vm.h"
#include "../h/text.h"
+#include "../h/psl.h"
+#include "../h/vlimit.h"
+#include "../h/file.h"
/*
* exec system call, with and without environments.
register struct buf *bp;
register struct execa *uap;
int na, ne, ucp, ap, c;
+ int indir, uid, gid;
+ char *sharg;
struct inode *ip;
swblk_t bno;
+ char cfname[DIRSIZ];
+ char cfarg[SHSIZE];
if ((ip = namei(uchar, 0)) == NULL)
return;
+
bno = 0;
bp = 0;
+ indir = 0;
+ uid = u.u_uid;
+ gid = u.u_gid;
+
+ if (ip->i_mode & ISUID)
+ uid = ip->i_uid;
+ if (ip->i_mode & ISGID)
+ gid = ip->i_gid;
+
+ again:
if(access(ip, IEXEC))
goto bad;
+ if((u.u_procp->p_flag&STRC) && access(ip, IREAD))
+ goto bad;
if((ip->i_mode & IFMT) != IFREG ||
(ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) {
u.u_error = EACCES;
goto bad;
}
+
+ /*
+ * Read in first few bytes of file for segment sizes, ux_mag:
+ * 407 = plain executable
+ * 410 = RO text
+ * 413 = demand paged RO text
+ * Also an ASCII line beginning with #! is
+ * the file name of a ``shell'' and arguments may be prepended
+ * to the argument list if given here.
+ *
+ * SHELL NAMES ARE LIMITED IN LENGTH.
+ *
+ * ONLY ONE ARGUMENT MAY BE PASSED TO THE SHELL FROM
+ * THE ASCII LINE.
+ */
+ u.u_base = (caddr_t)&u.u_exdata;
+ u.u_count = sizeof(u.u_exdata);
+ u.u_offset = 0;
+ u.u_segflg = 1;
+ readi(ip);
+ u.u_segflg = 0;
+ if(u.u_error)
+ goto bad;
+ if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.Ux_A)
+ && u.u_exdata.ux_shell[0] != '#') {
+ u.u_error = ENOEXEC;
+ goto bad;
+ }
+ switch (u.u_exdata.ux_mag) {
+
+ case 0407:
+ u.u_exdata.ux_dsize += u.u_exdata.ux_tsize;
+ u.u_exdata.ux_tsize = 0;
+ break;
+
+ case 0413:
+ case 0410:
+ if (u.u_exdata.ux_tsize == 0) {
+ u.u_error = ENOEXEC;
+ goto bad;
+ }
+ break;
+
+ default:
+ if (u.u_exdata.ux_shell[0] != '#' ||
+ u.u_exdata.ux_shell[1] != '!' ||
+ indir) {
+ u.u_error = ENOEXEC;
+ goto bad;
+ }
+ cp = &u.u_exdata.ux_shell[2]; /* skip "#!" */
+ while (cp < &u.u_exdata.ux_shell[SHSIZE]) {
+ if (*cp == '\t')
+ *cp = ' ';
+ else if (*cp == '\n') {
+ *cp = '\0';
+ break;
+ }
+ cp++;
+ }
+ if (*cp != '\0') {
+ u.u_error = ENOEXEC;
+ goto bad;
+ }
+ cp = &u.u_exdata.ux_shell[2];
+ while (*cp == ' ')
+ cp++;
+ u.u_dirp = cp;
+ while (*cp && *cp != ' ')
+ cp++;
+ sharg = NULL;
+ if (*cp) {
+ *cp++ = '\0';
+ while (*cp == ' ')
+ cp++;
+ if (*cp) {
+ bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE);
+ sharg = cfarg;
+ }
+ }
+ bcopy((caddr_t)u.u_dbuf, (caddr_t)cfname, DIRSIZ);
+ indir = 1;
+ iput(ip);
+ ip = namei(schar, 0);
+ if (ip == NULL)
+ return;
+ goto again;
+ }
+
/*
* Collect arguments on "file" in swap space.
*/
ne = 0;
nc = 0;
uap = (struct execa *)u.u_ap;
- if ((bno = malloc(swapmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) {
+ if ((bno = rmalloc(argmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) {
swkill(u.u_procp, "exece");
goto bad;
}
if (bno % CLSIZE)
- panic("execa malloc");
+ panic("execa rmalloc");
if (uap->argp) for (;;) {
ap = NULL;
- if (uap->argp) {
+ if (na == 1 && indir) {
+ if (sharg == NULL)
+ ap = (int)uap->fname;
+ } else if (na == 2 && indir && sharg != NULL)
+ ap = (int)uap->fname;
+ else if (uap->argp) {
ap = fuword((caddr_t)uap->argp);
uap->argp++;
}
do {
if (nc >= NCARGS-1)
u.u_error = E2BIG;
- if ((c = fubyte((caddr_t)ap++)) < 0)
+ if (indir && na == 2 && sharg != NULL)
+ c = *sharg++ & 0377;
+ else if ((c = fubyte((caddr_t)ap++)) < 0)
u.u_error = EFAULT;
if (u.u_error) {
if (bp)
if ((nc&BMASK) == 0) {
if (bp)
bdwrite(bp);
- bp = getblk(swapdev, (daddr_t)(dbtofsb(swplo+bno)+(nc>>BSHIFT)));
+ bp = getblk(argdev,
+ (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT)));
cp = bp->b_un.b_addr;
}
nc++;
bdwrite(bp);
bp = 0;
nc = (nc + NBPW-1) & ~(NBPW-1);
- if (getxfile(ip, nc) || u.u_error) {
+ if (indir)
+ bcopy((caddr_t)cfname, (caddr_t)u.u_dbuf, DIRSIZ);
+ getxfile(ip, nc + (na+4)*NBPW, uid, gid);
+ if (u.u_error) {
badarg:
for (c = 0; c < nc; c += BSIZE)
- if (bp = baddr(swapdev, dbtofsb(swplo+bno)+(c>>BSHIFT))) {
+ if (bp = baddr(argdev, dbtofsb(bno)+(c>>BSHIFT))) {
bp->b_flags |= B_AGE; /* throw away */
bp->b_flags &= ~B_DELWRI; /* cancel io */
brelse(bp);
if ((nc&BMASK) == 0) {
if (bp)
brelse(bp);
- bp = bread(swapdev, (daddr_t)(dbtofsb(swplo+bno)+(nc>>BSHIFT)));
+ bp = bread(argdev,
+ (daddr_t)(dbtofsb(bno)+(nc>>BSHIFT)));
bp->b_flags |= B_AGE; /* throw away */
bp->b_flags &= ~B_DELWRI; /* cancel io */
cp = bp->b_un.b_addr;
if (bp)
brelse(bp);
if (bno)
- mfree(swapmap, ctod(clrnd((int) btoc(NCARGS))), bno);
+ rmfree(argmap, ctod(clrnd((int) btoc(NCARGS))), bno);
iput(ip);
}
/*
* Read in and set up memory for executed file.
- * Zero return is normal;
- * non-zero means only the text is being replaced
*/
-getxfile(ip, nargc)
+getxfile(ip, nargc, uid, gid)
register struct inode *ip;
{
- register sep;
register size_t ts, ds, ss;
- register int overlay;
- int pagi = 0;
-
- /*
- * read in first few bytes
- * of file for segment
- * sizes:
- * ux_mag = 407/410/411/405
- * 407 is plain executable
- * 410 is RO text
- * 411 is separated ID
- * 405 is overlaid text
- * 412 is demand paged plain executable (NOT IMPLEMENTED)
- * 413 is demand paged RO text
- */
-
- u.u_base = (caddr_t)&u.u_exdata;
- u.u_count = sizeof(u.u_exdata);
- u.u_offset = 0;
- u.u_segflg = 1;
- readi(ip);
- u.u_segflg = 0;
- if(u.u_error)
- goto bad;
- if (u.u_count!=0) {
- u.u_error = ENOEXEC;
- goto bad;
- }
- sep = 0;
- overlay = 0;
- switch (u.u_exdata.ux_mag) {
+ int pagi;
- case 0405:
- overlay++;
- break;
-
- case 0412:
- u.u_error = ENOEXEC;
- goto bad;
-
- case 0407:
- u.u_exdata.ux_dsize += u.u_exdata.ux_tsize;
- u.u_exdata.ux_tsize = 0;
- break;
-
- case 0413:
+ if (u.u_exdata.ux_mag == 0413)
pagi = SPAGI;
- /* fall into ... */
-
- case 0410:
- if (u.u_exdata.ux_tsize == 0) {
- u.u_error = ENOEXEC;
- goto bad;
- }
- break;
+ else
+ pagi = 0;
- case 0411:
- u.u_error = ENOEXEC;
- goto bad;
-
- default:
- u.u_error = ENOEXEC;
- goto bad;
- }
if(u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) {
- u.u_error = ETXTBSY;
- goto bad;
+ register struct file *fp;
+
+ for (fp = file; fp < fileNFILE; fp++)
+ if (fp->f_inode == ip && (fp->f_flag&FWRITE)) {
+ u.u_error = ETXTBSY;
+ goto bad;
+ }
}
/*
ts = clrnd(btoc(u.u_exdata.ux_tsize));
ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize)));
ss = clrnd(SSIZE + btoc(nargc));
- if (overlay) {
- if ((u.u_procp->p_flag & SPAGI) || u.u_sep==0 && ctos(ts) != ctos(u.u_tsize) || nargc) {
- u.u_error = ENOMEM;
- goto bad;
- }
- ds = u.u_dsize;
- ss = u.u_ssize;
- sep = u.u_sep;
- xfree();
- xalloc(ip, pagi);
- u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */
- } else {
- if (chksize(ts, ds, ss))
- goto bad;
- u.u_cdmap = zdmap;
- u.u_csmap = zdmap;
- if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL)
- goto bad;
-
- /*
- * At this point, committed to the new image!
- * Release virtual memory resources of old process, and
- * initialize the virtual memory of the new process.
- * If we resulted from vfork(), instead wakeup our
- * parent who will set SVFDONE when he has taken back
- * our resources.
- */
- u.u_prof.pr_scale = 0;
- if ((u.u_procp->p_flag & SVFORK) == 0)
- vrelvm();
- else {
- u.u_procp->p_flag &= ~SVFORK;
- u.u_procp->p_flag |= SKEEP;
- wakeup((caddr_t)u.u_procp);
- while ((u.u_procp->p_flag & SVFDONE) == 0)
- sleep((caddr_t)u.u_procp, PZERO - 1);
- u.u_procp->p_flag &= ~(SVFDONE|SKEEP);
- }
- u.u_procp->p_flag &= ~(SPAGI|SANOM|SUANOM);
- u.u_procp->p_flag |= pagi;
- u.u_dmap = u.u_cdmap;
- u.u_smap = u.u_csmap;
- vgetvm(ts, ds, ss);
-
- if (pagi == 0) {
- /*
- * Read in data segment.
- */
- u.u_base = (char *)ctob(ts);
- u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize;
- u.u_count = u.u_exdata.ux_dsize;
- readi(ip);
- }
- xalloc(ip, pagi);
- if (pagi && u.u_procp->p_textp)
- vinifod((struct fpte *)dptopte(u.u_procp, 0),
- PG_FTEXT, u.u_procp->p_textp->x_iptr,
- 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize));
+ if (chksize(ts, ds, ss))
+ goto bad;
+ u.u_cdmap = zdmap;
+ u.u_csmap = zdmap;
+ if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL)
+ goto bad;
- /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */
- mtpr(TBIA,1);
+ /*
+ * At this point, committed to the new image!
+ * Release virtual memory resources of old process, and
+ * initialize the virtual memory of the new process.
+ * If we resulted from vfork(), instead wakeup our
+ * parent who will set SVFDONE when he has taken back
+ * our resources.
+ */
+ u.u_prof.pr_scale = 0;
+ if ((u.u_procp->p_flag & SVFORK) == 0)
+ vrelvm();
+ else {
+ u.u_procp->p_flag &= ~SVFORK;
+ u.u_procp->p_flag |= SKEEP;
+ wakeup((caddr_t)u.u_procp);
+ while ((u.u_procp->p_flag & SVFDONE) == 0)
+ sleep((caddr_t)u.u_procp, PZERO - 1);
+ u.u_procp->p_flag &= ~(SVFDONE|SKEEP);
+ }
+ u.u_procp->p_flag &= ~(SPAGI|SANOM|SUANOM|SNUSIG);
+ u.u_procp->p_flag |= pagi;
+ u.u_dmap = u.u_cdmap;
+ u.u_smap = u.u_csmap;
+ vgetvm(ts, ds, ss);
+ if (pagi == 0) {
/*
- * set SUID/SGID protections, if no tracing
+ * Read in data segment.
*/
- if ((u.u_procp->p_flag&STRC)==0) {
- if(ip->i_mode&ISUID)
- if(u.u_uid != 0) {
- u.u_uid = ip->i_uid;
- u.u_procp->p_uid = ip->i_uid;
- }
- if(ip->i_mode&ISGID)
- u.u_gid = ip->i_gid;
- } else
- psignal(u.u_procp, SIGTRAP);
+ u.u_base = (char *)ctob(ts);
+ u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize;
+ u.u_count = u.u_exdata.ux_dsize;
+ readi(ip);
}
+ xalloc(ip, pagi);
+ if (pagi && u.u_procp->p_textp)
+ vinifod((struct fpte *)dptopte(u.u_procp, 0),
+ PG_FTEXT, u.u_procp->p_textp->x_iptr,
+ 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize));
+
+ /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */
+ mtpr(TBIA, 0);
+
+ /*
+ * set SUID/SGID protections, if no tracing
+ */
+ if ((u.u_procp->p_flag&STRC)==0) {
+#ifndef MELB
+ if(u.u_uid != 0)
+#endif
+ {
+ u.u_uid = uid;
+ u.u_procp->p_uid = uid;
+ }
+ u.u_gid = gid;
+ } else
+ psignal(u.u_procp, SIGTRAP);
u.u_tsize = ts;
u.u_dsize = ds;
u.u_ssize = ss;
- u.u_sep = sep;
bad:
- return(overlay);
+ return;
}
/*
{
register int (**rp)();
register i;
+#ifdef UCBIPC
+ register struct port *pt;
+#endif UCBIPC
+ long sigmask;
+
+ for(rp = &u.u_signal[0], sigmask = 1L; rp < &u.u_signal[NSIG];
+ sigmask <<= 1, rp++) {
+ switch (*rp) {
+
+ case SIG_IGN:
+ case SIG_DFL:
+ case SIG_HOLD:
+ continue;
- for(rp = &u.u_signal[0]; rp < &u.u_signal[NSIG]; rp++)
- if(((int)*rp & 1) == 0)
- *rp = 0;
+ default:
+ /*
+ * Normal or deferring catch; revert to default.
+ */
+ (void) spl6();
+ *rp = SIG_DFL;
+ if ((int)*rp & 1)
+ u.u_procp->p_siga0 |= sigmask;
+ else
+ u.u_procp->p_siga1 &= ~sigmask;
+ if ((int)*rp & 2)
+ u.u_procp->p_siga1 |= sigmask;
+ else
+ u.u_procp->p_siga1 &= ~sigmask;
+ (void) spl0();
+ continue;
+ }
+ }
/*
for(rp = &u.u_ar0[0]; rp < &u.u_ar0[16];)
*rp++ = 0;
u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */
for(i=0; i<NOFILE; i++) {
if (u.u_pofile[i]&EXCLOSE) {
+#ifndef UCBIPC
closef(u.u_ofile[i]);
u.u_ofile[i] = NULL;
+#else UCBIPC
+ if (u.u_pofile[i]&ISPORT) {
+ pt = u.u_oport[i];
+ if (--pt->pt_count == 0)
+ ptclose(pt);
+ u.u_pofile[i] &= ~ISPORT;
+ u.u_oport[i] = NULL;
+ } else {
+ closef(u.u_ofile[i]);
+ u.u_ofile[i] = NULL;
+ }
+#endif UCBIPC
+ u.u_pofile[i] &= ~EXCLOSE;
}
- u.u_pofile[i] &= ~EXCLOSE;
}
/*
* Remember file name for accounting.
register int i;
register struct proc *p, *q;
register struct file *f;
+#ifdef UCBIPC
+ register struct port *pt;
+#endif UCBIPC
register int x;
#ifdef PGINPROF
p->p_flag &= ~(STRC|SULOCK);
p->p_flag |= SWEXIT;
p->p_clktim = 0;
- rate.v_pgin -= p->p_aveflt;
- p->p_aveflt = 0;
+ (void) spl6();
+ if ((int)SIG_IGN & 1)
+ p->p_siga0 = ~0;
+ else
+ p->p_siga0 = 0;
+ if ((int)SIG_IGN & 2)
+ p->p_siga1 = ~0;
+ else
+ p->p_siga1 = 0;
+ (void) spl0();
+ p->p_cpticks = 0;
+ p->p_pctcpu = 0;
for(i=0; i<NSIG; i++)
u.u_signal[i] = SIG_IGN;
/*
p->p_flag &= ~SVFDONE;
}
for(i=0; i<NOFILE; i++) {
+#ifndef UCBIPC
f = u.u_ofile[i];
u.u_ofile[i] = NULL;
closef(f);
+#else UCBIPC
+ if (u.u_pofile[i]&ISPORT) {
+ pt = u.u_oport[i];
+ if (--pt->pt_count == 0)
+ ptclose(pt);
+ u.u_oport[i] = NULL;
+ } else {
+ f = u.u_ofile[i];
+ u.u_ofile[i] = NULL;
+ closef(f);
+ }
+#endif UCBIPC
}
plock(u.u_cdir);
iput(u.u_cdir);
plock(u.u_rdir);
iput(u.u_rdir);
}
+ u.u_limit[LIM_FSIZE] = INFINITY;
acct();
vrelpt(u.u_procp);
vrelu(u.u_procp, 0);
multprog--;
- spl7(); /* clock will get mad because of overlaying */
+/* spl7(); /* clock will get mad because of overlaying */
p->p_stat = SZOMB;
+ noproc = 1;
i = PIDHASH(p->p_pid);
x = p - proc;
if (pidhash[i] == x)
}
panic("exit");
}
+ if (p->p_pid == 1)
+ panic("init died");
done:
((struct xproc *)p)->xp_xstat = rv; /* overlay */
((struct xproc *)p)->xp_vm = u.u_vm; /* overlay */
vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm);
- for(q = &proc[0]; q < &proc[NPROC]; q++)
- if(q->p_ppid == p->p_pid) {
- wakeup((caddr_t)&proc[1]);
+ for(q = proc; q < procNPROC; q++)
+ if(q->p_pptr == p) {
+ q->p_pptr = &proc[1];
q->p_ppid = 1;
- if (q->p_stat==SSTOP)
- setrun(q);
+ wakeup((caddr_t)&proc[1]);
+ /*
+ * Traced processes are killed
+ * since their existence means someone is screwing up.
+ * Stopped processes are sent a hangup and a continue.
+ * This is designed to be ``safe'' for setuid
+ * processes since they must be willing to tolerate
+ * hangups anyways.
+ */
+ if (q->p_flag&STRC) {
+ q->p_flag &= ~STRC;
+ psignal(q, SIGKILL);
+ } else if (q->p_stat == SSTOP) {
+ psignal(q, SIGHUP);
+ psignal(q, SIGCONT);
+ }
+ /*
+ * Protect this process from future
+ * tty signals, clear TSTP/TTIN/TTOU if pending,
+ * and set SDETACH bit on procs.
+ */
+ (void) spgrp(q, -1);
}
- q = pfind(p->p_ppid);
- if (q)
- wakeup((caddr_t)q);
+ wakeup((caddr_t)p->p_pptr);
+ psignal(p->p_pptr, SIGCHLD);
swtch();
}
wait()
{
+ struct vtimes vm;
+ struct vtimes *vp;
- wait1((struct vtimes *)0);
+ if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
+ wait1(0, (struct vtimes *)0);
+ return;
+ }
+ vp = (struct vtimes *)u.u_ar0[R1];
+ wait1(u.u_ar0[R0], &vm);
+ if (u.u_error)
+ return;
+ (void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes));
}
/*
* Look also for stopped (traced) children,
* and pass back status from them.
*/
-wait1(vp)
+wait1(options, vp)
+ register options;
struct vtimes *vp;
{
register f;
register struct proc *p;
f = 0;
-
loop:
- for(p = &proc[0]; p < &proc[NPROC]; p++)
- if(p->p_ppid == u.u_procp->p_pid) {
+ for(p = proc; p < procNPROC; p++)
+ if(p->p_pptr == u.u_procp) {
f++;
if(p->p_stat == SZOMB) {
u.u_r.r_val1 = p->p_pid;
p->p_stat = NULL;
p->p_pid = 0;
p->p_ppid = 0;
+ p->p_pptr = 0;
p->p_sig = 0;
+ p->p_siga0 = 0;
+ p->p_siga1 = 0;
p->p_pgrp = 0;
p->p_flag = 0;
p->p_wchan = 0;
+ p->p_cursig = 0;
return;
}
- if(p->p_stat == SSTOP) {
- if((p->p_flag&SWTED) == 0) {
- p->p_flag |= SWTED;
- u.u_r.r_val1 = p->p_pid;
- u.u_r.r_val2 = (fsig(p)<<8) | 0177;
- return;
- }
- continue;
+ if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 &&
+ (p->p_flag&STRC || options&WUNTRACED)) {
+ p->p_flag |= SWTED;
+ u.u_r.r_val1 = p->p_pid;
+ u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED;
+ return;
}
}
- if(f) {
- sleep((caddr_t)u.u_procp, PWAIT);
- goto loop;
+ if (f==0) {
+ u.u_error = ECHILD;
+ return;
+ }
+ if (options&WNOHANG) {
+ u.u_r.r_val1 = 0;
+ return;
}
- u.u_error = ECHILD;
+ if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) {
+ u.u_eosys = RESTARTSYS;
+ return;
+ }
+ sleep((caddr_t)u.u_procp, PWAIT);
+ goto loop;
}
/*
a = 0;
p2 = NULL;
- for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) {
+ for(p1 = proc; p1 < procNPROC; p1++) {
if (p1->p_stat==NULL && p2==NULL)
p2 = p1;
else {
* not su and too many procs owned; or
* not su and would take last slot.
*/
- if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) {
+ if (p2==NULL || (u.u_uid!=0 && (p2==procNPROC-1 || a>MAXUPRC))) {
u.u_error = EAGAIN;
if (!isvfork) {
(void) vsexpand(0, &u.u_cdmap, 1);
if (n < 0)
n = 0;
d = clrnd(n - u.u_dsize);
+ if (ctob(u.u_dsize+d) > u.u_limit[LIM_DATA]) {
+ u.u_error = ENOMEM;
+ return;
+ }
if (chksize(u.u_tsize, u.u_dsize+d, u.u_ssize))
return;
if (swpexpand(u.u_dsize+d, u.u_ssize, &u.u_dmap, &u.u_smap)==0)