|
|
1.1 root 1: #include "sys/param.h"
2: #include "sys/systm.h"
3: #include "sys/inode.h"
4: #include "sys/dir.h"
5: #include "sys/user.h"
6: #include "sys/psl.h"
7: #include "sys/stat.h"
8: #include "sys/buf.h"
9: #include "sys/pte.h"
10: #include "sys/cmap.h"
11: #include "sys/mtpr.h"
12: #include "sys/vmparam.h"
13: #include "sys/vmmac.h"
14: #include "sys/proc.h"
15: #include "sys/text.h"
16: #include "sys/file.h"
17: #include "sys/reg.h"
18: #include "sys/pioctl.h"
19: #include "sys/conf.h"
20:
21: /* I/O via /proc returns EBUSY if any of these bits are set in p_flag: */
22:
23: #define SPRBUSY (SLOCK|SPAGE|SKEEP|SWEXIT|SPROCIO)
24:
25: #define SYSADR ((caddr_t)0x80000000) /* virtual address of system seg. */
26: #define SYSP btop(0x80000000) /* virtual page no. of system seg. */
27:
28: /* <text page no.> + P1OFF(p) == <stack page no.> of same location */
29:
30: #define P1OFF(p) (SYSP - (p)->p_szpt*NPTEPG)
31:
32: #define TEXT 0
33: #define DATA 1
34: #define STACK 2
35: #define USERAREA 3
36:
37: #define min(a,b) ((a) <= (b) ? (a) : (b))
38:
39: /* inumber to pid */
40: #define PRMAGIC 64
41:
42: #define PROCDEV (dev_t)0
43: #define PRROOT 2
44:
45: struct proc *prpidlock, *prpidwant, *pritop();
46:
47: struct pte *Prbufmap; char *priobuf;
48: struct pte *Prusrmap; struct user *prusrutl;
49: struct pte *prclmap();
50:
51: int prput(), prread(), prwrite(), prstat();
52: int prmount(), prioctl(), prnami();
53:
54: struct fstypsw prfs =
55: fsinit(prput, nulldev, prread, prwrite, nulldev, prstat,
56: prnami, prmount, prioctl, nullopen, nodev);
57:
58: prput(ip)
59: struct inode *ip;
60: { struct proc *p;
61: if(ip->i_number == PRROOT)
62: return;
63: if ((p = pritop(ip)) == NULL)
64: return;
65: p->p_trace = 0;
66: }
67:
68: #define SDSIZ sizeof(struct direct)
69:
70: prread(ip)
71: struct inode *ip;
72: {
73: static struct direct dotbuf[] = {
74: { PRROOT, "."},
75: { PRROOT, ".."}
76: };
77: struct direct dirbuf;
78: register int i, n, j;
79: int minproc, maxproc, modoff;
80: struct proc *p;
81:
82: if (ip->i_number == PRROOT) { /* fake up . .. and the proc inodes */
83: if (Lsign(u.u_offset) < 0 || Ltol(u.u_offset) >= ip->i_size ||
84: u.u_count <= 0)
85: return;
86: if (Ltol(u.u_offset) < 2*SDSIZ) {
87: iomove((caddr_t)dotbuf + Ltol(u.u_offset),
88: min(u.u_count, 2*SDSIZ - Ltol(u.u_offset)), B_READ);
89: if (u.u_count <= 0 || u.u_error)
90: return;
91: }
92: minproc = (Ltol(u.u_offset) - 2*SDSIZ)/SDSIZ;
93: maxproc = (Ltol(u.u_offset) + u.u_count - 1)/SDSIZ;
94: modoff = Ltol(u.u_offset) % SDSIZ;
95: for (j = 0; j < DIRSIZ; j++)
96: dirbuf.d_name[j] = 0;
97: for (i=minproc; i<min(maxproc,proccnt); i++) {
98: if (proc[i].p_stat == 0)
99: dirbuf.d_ino = 0;
100: else {
101: n = proc[i].p_pid;
102: dirbuf.d_ino = n + PRMAGIC;
103: for (j = 4; j >= 0; j--)
104: dirbuf.d_name[j] = n%10 + '0', n /= 10;
105: }
106: iomove((caddr_t)&dirbuf + modoff,
107: min(u.u_count, SDSIZ - modoff), B_READ);
108: if (u.u_count <= 0 || u.u_error)
109: return;
110: modoff = 0;
111: }
112: } else if ((p = pritop(ip)) != NULL) {
113: if (prlock(p))
114: return;
115: prusrio(p, B_READ);
116: prunlock(p);
117: }
118: }
119:
120: prwrite(ip)
121: struct inode *ip;
122: {
123: register struct proc *p;
124: if (ip->i_number == PRROOT) {
125: u.u_error = EISDIR;
126: } else if ((p = pritop(ip)) != NULL) {
127: if (prlock(p))
128: return;
129: prusrio(p, B_WRITE);
130: prunlock(p);
131: }
132: }
133:
134: prstat(ip, ub)
135: struct inode *ip;
136: struct stat *ub;
137: { struct stat ds; struct proc *p = (struct proc *)0;
138: if(ip->i_number == PRROOT || (p = pritop(ip)) != NULL) {
139: ds.st_dev = -1; /* who knows */
140: ds.st_ino = ip->i_number;
141: ds.st_mode = ip->i_mode;
142: ds.st_nlink = ip->i_nlink;
143: ds.st_uid = ip->i_uid;
144: ds.st_gid = ip->i_gid;
145: ds.st_rdev = -1;
146: if (p) ip->i_size =
147: (int)ptob(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES);
148: ds.st_size = ip->i_size;
149: ds.st_atime = ds.st_mtime = ds.st_ctime = time;
150: if(copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)) < 0)
151: u.u_error = EFAULT;
152: }
153: }
154:
155: prnami(p, flagp, follow)
156: register struct nx *p;
157: struct argnamei *flagp;
158: {
159: register struct inode *dp;
160: register char *cp;
161: register int n;
162:
163: cp = p->cp;
164: dp = p->dp;
165: if ((dp->i_mode & IFMT) != IFDIR) {
166: u.u_error = ENOTDIR;
167: goto error;
168: }
169: if (access(dp, IEXEC))
170: goto error;
171: if (flagp->flag != NI_SEARCH) {
172: u.u_error = EACCES;
173: goto error;
174: }
175: rootloop:
176: if (cp[0] == 0) /* "" == root */
177: return (0);
178: if (cp[0] == '.') {
179: if (cp[1] == 0) /* "." */
180: return (0);
181: if (cp[1] == '/') { /* "./" ... */
182: cp += 2;
183: p->cp = cp;
184: goto rootloop;
185: }
186: if (cp[1] == '.' && (cp[2] == 0 || cp[2] == '/')) { /* ".." */
187: p->dp = dp->i_mpoint;
188: iput(dp);
189: plock(p->dp);
190: p->dp->i_count++;
191: return (1); /* cp still points to ".." */
192: }
193: u.u_error = ENOENT; /* ".somethingelse" */
194: goto error;
195: }
196: n = 0;
197: while (*cp >= '0' && *cp <= '9') {
198: n *= 10;
199: n += *cp++ - '0';
200: }
201: if (*cp) { /* non-digit, or /proc/123/... */
202: u.u_error = ENOENT;
203: goto error;
204: }
205: p->dp = iget(dp, PROCDEV, n + PRMAGIC);
206: if (p->dp == NULL)
207: goto error;
208: if (p->dp->i_count == 1 && prfillin(p->dp))
209: goto error;
210: iput(dp);
211: return (0);
212:
213: error:
214: p->dp = NULL;
215: iput(dp);
216: return (0);
217: }
218:
219: prfillin(ip)
220: register struct inode *ip;
221: {
222: register struct proc *p;
223: register int n;
224:
225: ip->i_un.i_proc = NULL; /* safety */
226: n = ip->i_number - PRMAGIC;
227: for (p = proc; p < procNPROC; p++)
228: if (p->p_stat && p->p_pid == n)
229: break;
230: if (p == procNPROC || p->p_stat == SZOMB || p->p_trace) {
231: iput(ip);
232: u.u_error = ENOENT;
233: return (1);
234: }
235: p->p_trace = ip;
236: if (p->p_textp && p->p_textp->x_iptr && access(p->p_textp->x_iptr, IREAD))
237: ip->i_mode = IFREG; /* regular, no permissions */
238: else
239: ip->i_mode = IFREG | 0600; /* regular, r/w only by owner */
240: ip->i_nlink = 1;
241: ip->i_uid = p->p_uid;
242: ip->i_gid = 1; /* who cares */
243: ip->i_size = (int)ptob(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES);
244: ip->i_un.i_proc = p;
245: ip->i_un.i_sigmask = 0; /* signal trace mask */
246: return (0);
247: }
248:
249: prmount(sip, ip, flag, mnt, fstyp)
250: struct inode *sip, *ip;
251: {
252: if (!suser())
253: return;
254: if (mnt)
255: pron(sip, ip, flag, fstyp);
256: else
257: proff(ip, fstyp);
258: }
259:
260: pron(sip, ip, flag, fstyp)
261: struct inode *sip;
262: register struct inode *ip;
263: {
264: register struct inode *rip;
265: struct inode pi;
266:
267: if (ip->i_fstyp == fstyp) {
268: u.u_error = EBUSY;
269: return;
270: }
271: pi.i_fstyp = fstyp;
272: pi.i_mpoint = NULL;
273: if ((rip = iget(&pi, PROCDEV, (ino_t)PRROOT)) == NULL)
274: return;
275: if (rip->i_count != 1) { /* already mounted */
276: iput(rip);
277: u.u_error = EBUSY;
278: return;
279: }
280: rip->i_mpoint = ip;
281: rip->i_mode = IFDIR|0555;
282: rip->i_nlink = 2;
283: rip->i_uid = rip->i_gid = 0;
284: rip->i_size = (proccnt+2) * sizeof(struct direct);
285: prele(rip);
286: ip->i_mroot = rip;
287: ip->i_count++;
288: }
289:
290: proff(mip, fstyp)
291: struct inode *mip;
292: {
293: struct inode *rip;
294:
295: plock(mip);
296: rip = mip->i_mroot;
297: mip->i_mroot = NULL;
298: iput(mip);
299: plock(rip);
300: iput(rip);
301: }
302:
303: /* special tracing stuff */
304: prioctl(ip, cmd, cmaddr)
305: struct inode *ip;
306: caddr_t cmaddr;
307: {
308: register struct proc *p; struct text *xp; struct inode *ixp;
309: int n; /* mostly for integer arguments */
310:
311: if ((p = pritop(ip)) == NULL)
312: return;
313: switch (cmd) {
314: default:
315: u.u_error = ENOTTY;
316: return;
317:
318: case PIOCGETPR: /* read struct proc */
319: if (copyout((char *)p, cmaddr, sizeof(struct proc)))
320: u.u_error = EFAULT;
321: return;
322:
323: case PIOCOPENT: /* open text file for reading */
324: if ((xp = p->p_textp) && (ixp = xp->x_iptr)) {
325: plock(ixp);
326: ixp->i_count++;
327: open1(ixp, FREAD, 0); /* fairly magic linkage */
328: } else
329: u.u_error = ENOENT;
330: return;
331:
332: case PIOCSTOP: /* send STOP signal and... */
333: if (p->p_stat != SSTOP)
334: psignal(p, SIGSTOP);
335: /* fall through */
336: case PIOCWSTOP: /* wait for process to STOP */
337: if (p->p_stat != SSTOP)
338: tsleep((caddr_t)p->p_trace, PZERO+1, 0);
339: if (p->p_pid != (ip->i_number - PRMAGIC)
340: || p->p_stat == SZOMB)
341: u.u_error = ENOENT;
342: else if (p->p_stat != SSTOP)
343: u.u_error = EINTR;
344: return;
345:
346: case PIOCRUN: /* make process runnable */
347: if (p->p_stat == SSTOP)
348: setrun(p);
349: return;
350:
351: case PIOCSMASK: /* set signal trace mask */
352: if (copyin(cmaddr, (caddr_t)&ip->i_un.i_sigmask, sizeof(long))) {
353: u.u_error = EFAULT;
354: return;
355: }
356: if (ip->i_un.i_sigmask)
357: p->p_flag |= (STRC|SPROCTR);
358: else
359: p->p_flag &= ~(STRC|SPROCTR);
360: return;
361:
362: case PIOCCSIG: /* clear current signal */
363: p->p_cursig = 0;
364: return;
365:
366: case PIOCSSIG: /* set current signal */
367: if (p->p_stat != SSTOP)
368: u.u_error = EBUSY;
369: else if (copyin(cmaddr, (caddr_t)&n, sizeof(n)))
370: u.u_error = EFAULT;
371: else if ((unsigned)n > NSIG)
372: u.u_error = EINVAL;
373: else
374: p->p_cursig = n;
375: return;
376:
377: case PIOCKILL: /* send signal */
378: if (copyin(cmaddr, (caddr_t)&n, sizeof(n)))
379: u.u_error = EFAULT;
380: else if ((unsigned)n > NSIG)
381: u.u_error = EINVAL;
382: else
383: psignal(p, n);
384: return;
385:
386: case PIOCSEXEC: /* stop on exec */
387: p->p_flag |= SSEXEC;
388: return;
389:
390: case PIOCREXEC: /* run on exec */
391: p->p_flag &= ~SSEXEC;
392: return;
393:
394: case PIOCNICE: /* set nice priority */
395: if (copyin(cmaddr, (caddr_t)&n, sizeof(n))) {
396: u.u_error = EFAULT;
397: return;
398: }
399: n += p->p_nice;
400: if (n >= 2*NZERO)
401: n = 2*NZERO -1;
402: if (n < 0)
403: n = 0;
404: if (n < p->p_nice && !suser())
405: return;
406: p->p_nice = n;
407: (void) setpri(p);
408: return;
409: }
410: }
411:
412: /* Lock the process p. */
413:
414: prlock(p)
415: register struct proc *p;
416: {
417: int s;
418:
419: if (p != u.u_procp) {
420: waitloop:
421: if (prpidlock == p) { /* wait if p has the interlock */
422: prpidwant = u.u_procp;
423: if (tsleep((caddr_t)&prpidlock, PZERO+1, 0) == TS_SIG)
424: return (u.u_error = EINTR);
425: goto waitloop;
426: }
427: if (p->p_flag & SPAGE) { /* wait if p is paging */
428: p->p_flag |= SPROCWT;
429: if (tsleep((caddr_t)&(p->p_stat), PZERO+1, 0) == TS_SIG)
430: return (u.u_error = EINTR);
431: goto waitloop;
432: }
433:
434: s = spl6(); /* keep clock out */
435:
436: if (p->p_flag&SPRBUSY || (p->p_stat != SSLEEP &&
437: p->p_stat != SRUN && p->p_stat != SSTOP)) {
438: splx(s);
439: return (u.u_error = EBUSY);
440: }
441: if (p->p_flag&SLOAD && p->p_stat == SRUN)
442: remrq(p); /* he's now invisible to swtch() */
443:
444: /* interlock; also causes swapin, inhibits swapout, setrq, remrq */
445:
446: p->p_flag |= SPROCIO;
447:
448: splx(s); /* now do your worst, we don't care */
449: }
450: u.u_procp->p_flag |= SKEEP; /* if we get swapped, could deadlock */
451:
452: while ((p->p_flag&SLOAD) == 0) {
453: /* sched will see SPROCIO, swap him in, and signal us */
454: if (tsleep((caddr_t)&p->p_addr, PZERO+1, 0) == TS_SIG) {
455: prunlock(p);
456: return (u.u_error = EINTR);
457: }
458: }
459: while (prpidlock) {
460: prpidwant = u.u_procp;
461: if (tsleep((caddr_t)&prpidlock, PZERO+1, 0) == TS_SIG) {
462: prunlock(p);
463: return (u.u_error = EINTR);
464: }
465: }
466: prpidlock = u.u_procp;
467: /* now map his user area into kernel space */
468: uaccess(p, Prusrmap, prusrutl);
469:
470: return (u.u_error = 0);
471: }
472:
473: /* Undo prlock. */
474:
475: prunlock(p)
476: register struct proc *p;
477: {
478: int s;
479:
480: u.u_procp->p_flag &= ~SKEEP;
481:
482: if (p != u.u_procp) {
483: s = spl6(); /* keep clock out during process state change */
484: p->p_flag &= ~SPROCIO;
485: if (p->p_flag&SLOAD && p->p_stat == SRUN)
486: setrq(p); /* visible again to swtch() */
487: splx(s);
488: }
489: if (prpidlock == u.u_procp) {
490: prpidlock = 0;
491: if (prpidwant) {
492: prpidwant = 0;
493: wakeup((caddr_t)&prpidlock);
494: }
495: }
496: return 0;
497: }
498:
499: /* Read/write from/to process p. */
500:
501: #define REGADR(i) ((caddr_t)(regbase + i))
502: #define SEEKADR ((caddr_t)Ltol(u.u_offset))
503:
504: prusrio(p, flag)
505: register struct proc *p; int flag;
506: {
507: register int *regbase;
508: caddr_t maxadr; int segment, resid;
509:
510: u.u_error = 0;
511: if ((u_long)SEEKADR >= (u_long)(maxadr = SYSADR))
512: u.u_error = EIO;
513: else if (SEEKADR >= (caddr_t)USRSTACK)
514: segment = USERAREA;
515: else if (SEEKADR >= (maxadr = (caddr_t)USRSTACK) - (int)ptob(p->p_ssize))
516: segment = STACK;
517: else if (SEEKADR < (maxadr = ptob(p->p_tsize)))
518: segment = TEXT;
519: else if (SEEKADR < (maxadr = ptob(p->p_tsize+p->p_dsize)))
520: segment = DATA;
521: else
522: u.u_error = EIO;
523: if (p->p_flag & SSYS && segment != USERAREA) /* too conservative? */
524: u.u_error = EIO;
525:
526: if (u.u_error) return;
527:
528: if ((flag & B_READ) == 0) switch(segment) {
529: case TEXT:
530: prxdup(p);
531: break;
532: case USERAREA:
533: regbase = prusrutl->u_ar0;
534: if (SEEKADR < REGADR(AP) ||
535: (u_long)SEEKADR >= (u_long)(maxadr = REGADR(PS+1)))
536: u.u_error = EIO;
537: else if (SEEKADR >= REGADR(PC)) ;
538: else if (SEEKADR < (maxadr = REGADR(FP+1))) ;
539: else if (SEEKADR < REGADR(R0))
540: u.u_error = EIO;
541: else if (SEEKADR < (maxadr = REGADR(R11+1))) ;
542: else if (SEEKADR < REGADR(SP) || SEEKADR >= (maxadr = REGADR(SP+1)))
543: u.u_error = EIO;
544: regbase = (int *)((u_long)prusrutl + (u_long)regbase - (u_long)&u);
545: if ((regbase[PS]&PSL_USERSET) != PSL_USERSET ||
546: (regbase[PS]&PSL_USERCLR) != 0)
547: u.u_error = EBUSY;
548: break;
549: }
550:
551: if (u.u_error) return;
552:
553: resid = u.u_count;
554: if ((u_long)(Ltol(u.u_offset) + u.u_count) >= (u_long)maxadr)
555: u.u_count = maxadr - (caddr_t)Ltol(u.u_offset);
556: resid -= u.u_count;
557:
558: if (segment == USERAREA) {
559: iomove((caddr_t)prusrutl + ((u_long)Ltol(u.u_offset) - (u_long)&u),
560: u.u_count, flag);
561: if ((flag & B_READ) == 0) {
562: regbase[PS] |= PSL_USERSET;
563: regbase[PS] &= ~PSL_USERCLR;
564: }
565: } else
566: priomove(p, flag);
567:
568: u.u_count += resid;
569: }
570:
571: /* Move data between the object process and us. */
572:
573: priomove(p, flag)
574: register struct proc *p;
575: {
576: register struct pte *pte;
577: register clofset, clcount;
578: int waslocked;
579:
580: while (u.u_count > 0 && u.u_error == 0) {
581: pte = prclmap(p, (caddr_t)Ltol(u.u_offset), &waslocked);
582: clofset = Ltol(u.u_offset) & CLOFSET;
583: clcount = min(u.u_count, CLSIZE*NBPG - clofset);
584: iomove(&priobuf[clofset], clcount, flag);
585: prclunmap(pte, flag | waslocked);
586: }
587: }
588:
589: /* Map and lock a cluster from process into system space. */
590:
591: struct pte *
592: prclmap(p, vaddr, flagp)
593: register struct proc *p;
594: register caddr_t vaddr;
595: int *flagp;
596: {
597: register i;
598: register struct pte *pte;
599: i = clbase(btop(vaddr));
600: if (isassv(p, i))
601: i -= P1OFF(p);
602: pte = p->p_p0br + i;
603:
604: *flagp = 0;
605: if (pte->pg_v) {
606: if (cmap[pgtocm(pte->pg_pfnum)].c_lock)
607: *flagp = B_PHYS;
608: else
609: mlock(pte->pg_pfnum);
610: } else {
611: p->p_flag |= SDLYU;
612: pagein(vaddr, prusrutl);
613: p->p_flag &= ~SDLYU;
614: if (!pte->pg_v)
615: panic("prclmap: pte not valid after pagein");
616: }
617: for (i=0; i<CLSIZE; i++) {
618: *(int *)(Prbufmap + i) = PG_V | PG_KW | (pte->pg_pfnum + i);
619: mtpr(TBIS, &priobuf[i*NBPG]);
620: }
621: return pte;
622: }
623:
624: /* Release a cluster, updating its pte's. */
625:
626: prclunmap(pte, flag)
627: register struct pte *pte;
628: {
629: register i;
630: if ((flag & B_PHYS) == 0)
631: munlock(pte->pg_pfnum);
632: if ((flag & B_READ) == 0) /* Write to device writes memory */
633: for (i=0; i<CLSIZE; i++)
634: (pte+i)->pg_m = 1;
635: }
636:
637: /* Prepare the process' text segment for writing, duplicating it if necessary. */
638:
639: prxdup(p)
640: register struct proc *p;
641: {
642: register struct text *xp, *pxp;
643:
644: if ((pxp = p->p_textp) == 0)
645: return 0;
646: if (!(pxp->x_flag&XPAGI) && pxp->x_count == 1) {
647: pxp->x_flag |= XTRC|XWRIT;
648: return 0;
649: }
650: if (pxp->x_flag&XTRC)
651: panic("prxdup");
652:
653: for (xp = text; xp < textNTEXT && xp->x_iptr; xp++)
654: /* void */ ;
655: if (xp >= textNTEXT)
656: return (u.u_error = ENOSPC);
657:
658: xp->x_flag = XLOCK|XTRC|XLOAD;
659: xp->x_size = pxp->x_size;
660: if (vsxalloc(xp) == NULL)
661: return (u.u_error = ENOSPC);
662:
663: xp->x_count = 1;
664: xp->x_ccount = 0;
665: xp->x_rssize = 0;
666: (xp->x_iptr = pxp->x_iptr)->i_count++;
667:
668: xlock(pxp);
669: --pxp->x_count;
670: pxp->x_flag &= ~XLOCK;
671: xccdec(pxp, p);
672:
673: p->p_textp = xp;
674: xlink(p);
675: p->p_flag &= ~SPAGI;
676:
677: prxread(p, prusrutl);
678:
679: xp->x_flag |= XWRIT;
680: xp->x_flag &= ~XLOAD;
681: xunlock(xp);
682: return u.u_error;
683: }
684:
685: prxread(p, up)
686: register struct proc *p;
687: struct user *up;
688: {
689: register struct inode *ip = p->p_textp->x_iptr;
690: register count; register struct pte *pte;
691: register caddr_t vaddr = 0; int waslocked;
692:
693: caddr_t ubase = u.u_base; unsigned int ucount = u.u_count;
694: off_t uoffset = Ltol(u.u_offset);
695:
696: plock(ip);
697: ip->i_flag |= ITEXT;
698:
699: count = up->u_exdata.ux_tsize;
700: if (up->u_exdata.ux_mag == 0413) /* 0413 on 4k file sys */
701: u.u_offset = ltoL(BSIZE(0));
702: else
703: u.u_offset = ltoL(sizeof(u.u_exdata));
704:
705: u.u_segflg = SEGSYS;
706: u.u_count = 0;
707: while (count > 0 && u.u_count == 0) {
708: pte = prclmap(p, vaddr, &waslocked);
709: u.u_base = (caddr_t)priobuf;
710: count -= u.u_count = min(count, CLSIZE*NBPG);
711: vaddr += u.u_count;
712: readi(ip);
713: prclunmap(pte, B_WRITE | waslocked);
714: }
715: prele(ip);
716:
717: u.u_base = ubase; u.u_count = ucount;
718: u.u_offset = ltoL(uoffset); u.u_segflg = SEGUDATA;
719:
720: return (count ? (u.u_error = EIO) : 0);
721: }
722:
723: struct proc *
724: pritop(ip)
725: struct inode *ip;
726: {
727: register struct proc *p;
728:
729: if ((p = ip->i_un.i_proc) == NULL
730: || p->p_pid != ip->i_number - PRMAGIC
731: || p->p_stat == 0 || p->p_stat == SZOMB) {
732: u.u_error = ENOENT; /* should really be ENXIO */
733: return (NULL);
734: }
735: return (p);
736: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.