|
|
1.1 root 1: /* $Header: /src386/STREAMS/coh.386/RCS/exec.c,v 2.3 93/08/09 13:35:18 bin Exp Locker: bin $ */
2: /*
3: * Processing of the exec () system call.
4: *
5: * $Log: exec.c,v $
6: * Revision 2.3 93/08/09 13:35:18 bin
7: * Kernel 82 changes
8: *
9: * Revision 2.2 93/07/26 15:22:36 nigel
10: * Nigel's R80
11: *
12: * Revision 2.3 93/07/26 14:47:30 nigel
13: * Nigel's R80
14: *
15: */
16:
17: #include <common/_gregset.h>
18: #include <common/_tricks.h>
19: #include <kernel/sigproc.h>
20:
21: #include <sys/coherent.h>
22: #include <sys/acct.h>
23: #include <sys/buf.h>
24: #include <canon.h>
25: #include <sys/con.h>
26: #include <sys/errno.h>
27: #include <fcntl.h>
28: #include <sys/filsys.h>
29: #include <sys/ino.h>
30: #include <sys/inode.h>
31: #include <sys/file.h>
32: #include <a.out.h>
33: #include <l.out.h>
34: #include <sys/proc.h>
35: #include <sys/sched.h>
36: #include <sys/seg.h>
37: #include <signal.h>
38: #include <sys/stat.h>
39: #include <sys/fd.h>
40:
41: /*
42: * Round section and segment start address to nearest lower click boundary.
43: */
44:
45: static void
46: xecrnd(xsp)
47: struct xecseg * xsp;
48: {
49: int diff;
50:
51: diff = xsp->fbase & (NBPC - 1);
52: xsp->mbase -= diff;
53: xsp->fbase -= diff;
54: xsp->size += diff;
55: }
56:
57: /*
58: * Pass control to an image in a file.
59: * Make sure the format is acceptable. Release
60: * the old segments. Read in the new ones. Some special
61: * care is taken so that shared and (more important) shared
62: * and separated images can be run on the 8086.
63: */
64:
65: pexece(np, argp, envp, regsetp)
66: char * np;
67: char * argp [];
68: char * envp [];
69: gregset_t * regsetp;
70: {
71: struct xechdr head;
72: register INODE *ip; /* Load file INODE */
73: register PROC *pp; /* A cheap copy of SELF */
74: register SEG *segp;
75: SEG *ssegp;
76: register int i; /* For looping over segments*/
77: int roundup;
78: int shrdsize;
79: struct xecnode * xlist = NULL; /* list head */
80: struct xecnode * xp;
81: struct xecseg tempseg;
82: unsigned int textSize;
83: struct direct dir;
84:
85: pp = SELF;
86: memset (& head, 0, sizeof (head));
87: if ((ip = exlopen (& head, np, & shrdsize, & xlist, & dir)) == NULL)
88: goto done;
89:
90: roundup = shrdsize & 0xf;
91: ssegp = exstack (& head, argp, envp,
92: __xmode_286 (regsetp) ? sizeof (short) :
93: sizeof (int));
94:
95: if (! ssegp) {
96: idetach(ip);
97: goto done;
98: }
99:
100: /* Release shared memory. */
101: shmAllDt ();
102:
103: /*
104: * At this point the file has been
105: * validated as an object module, and the
106: * argument list has been built. Release all of
107: * the original segments. At this point we have
108: * committed to the new image. A "sys exec" that
109: * gets an I/O error is doomed.
110: * NOTE: User-area segment is NOT released.
111: * Segment pointer in proc is erased BEFORE invoking sfree().
112: */
113:
114: for (i = 1 ; i < NUSEG ; ++ i) {
115: if ((segp = pp->p_segp [i]) != NULL) {
116: pp->p_segp [i] = NULL;
117: sfree (segp);
118: }
119: }
120: pp->p_segp [SISTACK] = ssegp;
121:
122: /*
123: * Read in the loadable segments.
124: */
125:
126: switch (head.magic) {
127: case XMAGIC (I286MAGIC, I_MAGIC):
128: if ((segp = ssalloc (ip, SFTEXT,
129: head.segs [SISTEXT].size)) == NULL)
130: goto out;
131: pp->p_segp [SISTEXT] = segp;
132:
133: if (! exsread (segp, ip, & head.segs [SISTEXT], 0))
134: goto out;
135:
136: if ((segp = ssalloc (ip, 0, roundup +
137: head.segs [SIPDATA].size +
138: head.segs [SIBSS].size)) == NULL)
139: goto out;
140: pp->p_segp [SIPDATA] = segp;
141:
142: if (! exsread(segp, ip, & head.segs [SIPDATA], shrdsize)) {
143: goto out;
144: }
145: head.segs [SIPDATA].size += roundup;
146: break;
147:
148: case XMAGIC (I386MAGIC, Z_MAGIC):
149: /*
150: * Round segment address down to nearest click boundary.
151: * Ciaran did this. I'm not sure why, but will preserve
152: * it for now. -hws-
153: */
154:
155: tempseg = head.segs [SISTEXT]; /* save pre-rounding value */
156: xecrnd (head.segs + SISTEXT);
157: xecrnd (head.segs + SIPDATA);
158:
159: /*
160: * Compute text segment size by taking highest address
161: * seen in any text section.
162: */
163:
164: textSize = head.segs [SISTEXT].size +
165: head.segs [SISTEXT].mbase;
166: for (xp = xlist ; xp ; xp = xp->xn) {
167: unsigned int tmpSize;
168: if (xp->segtype != SISTEXT)
169: continue;
170: tmpSize = xp->xseg.size + xp->xseg.mbase;
171: if (tmpSize > textSize)
172: textSize = tmpSize;
173: }
174:
175: /* Entry point must be within text segment. */
176: if (head.entry >= textSize)
177: goto out;
178:
179: if ((segp = ssalloc (ip, SFTEXT | SFSHRX,
180: textSize)) == NULL)
181: goto out;
182:
183: pp->p_segp [SISTEXT] = segp;
184:
185: if (segp->s_ip == 0) {
186: if (! exsread (segp, ip, & tempseg, 0))
187: goto out;
188:
189: /* load additional text sections, if any */
190: for (xp = xlist ; xp ; xp = xp->xn) {
191: if (xp->segtype != SISTEXT)
192: continue;
193: if (! exsread (segp, ip, & xlist->xseg, 0))
194: goto out;
195: }
196:
197: segp->s_ip = ip;
198: ip->i_refc ++;
199: }
200: if ((segp = ssalloc (ip, 0, head.segs [SIPDATA].size +
201: head.segs[SIBSS].size)) == NULL)
202: goto out;
203:
204: pp->p_segp [SIPDATA] = segp;
205:
206: if (segp->s_ip == 0 &&
207: ! exsread (segp, ip, & head.segs [SIPDATA], 0))
208: goto out;
209:
210: /* Deallocate nodes hooked into xlist by exlopen. */
211: while (xlist != NULL) {
212: struct xecnode * tmp = xlist->xn;
213: kfree (xlist);
214: xlist = tmp;
215: }
216: break;
217:
218: default:
219: panic("pexece");
220: }
221:
222: if (sproto (& head) == 0)
223: goto out;
224:
225: /*
226: * At this point, and no earlier, we can modify the user register
227: * image for the new process because now we are committed to executing
228: * the new image.
229: *
230: * As a general security thing, we begin by zeroing out the user-level
231: * register image.
232: */
233:
234: memset (regsetp, 0, sizeof (* regsetp));
235:
236: switch (head.magic) {
237: case XMAGIC (I286MAGIC, I_MAGIC):
238: regsetp->_i286._cs = SEG_286_UII | R_USR;
239: regsetp->_i286._ss = regsetp->_i286._es =
240: regsetp->_i286._ds = SEG_286_UD | R_USR;
241: regsetp->_i286._ip = head.entry;
242: regsetp->_i286._usp = head.initsp;
243: break;
244:
245: case XMAGIC (I386MAGIC, Z_MAGIC):
246: regsetp->_i386._cs = SEG_386_UI | R_USR;
247: regsetp->_i386._ss = regsetp->_i386._es =
248: regsetp->_i386._ds = SEG_386_UD | R_USR;
249: regsetp->_i386._eip = head.entry;
250: regsetp->_i386._uesp = head.initsp;
251: break;
252: }
253:
254:
255: /*
256: * The new image is read in
257: * and mapped. Perform the final grunge
258: * (set-uid stuff, accounting, loading up
259: * registers, etc).
260: */
261:
262: u.u_flag &= ~AFORK;
263:
264: memcpy (u.u_comm, dir.d_name, sizeof (u.u_comm));
265:
266: if (iaccess (ip, IPR) == 0) { /* Can't read ? no dump or trace */
267: pp->p_flags |= PFNDMP;
268: pp->p_flags &= ~PFTRAC;
269: }
270:
271:
272: /*
273: * Norm says Frank says we need to drop this for db to work.
274: */
275: #if 0
276: if (iaccess(ip, IPW) == 0) { /* Can't write ? no trace */
277: pp->p_flags &= ~PFTRAC;
278: printf("Can't write - no trace! ");
279: u.u_error = 0;
280: }
281: #endif
282:
283: if ((ip->i_mode & ISUID) != 0) { /* Set user id ? no trace */
284: pp->p_uid = u.u_uid = u.u_euid = ip->i_uid;
285: pp->p_flags &= ~PFTRAC;
286: }
287:
288: if ((ip->i_mode & ISGID) != 0) { /* Set group id ? no trace */
289: u.u_egid = u.u_gid = ip->i_gid;
290: pp->p_flags &= ~PFTRAC;
291: }
292:
293: for (i = 0 ; i < NOFILE; i ++) {
294: int j = fdgetflags (i);
295: if (j != -1 && (j & FD_CLOEXEC) != 0)
296: fdclose (i); /* close fd on exec bit set */
297: }
298:
299:
300: /*
301: * Default every signal that is not ignored.
302: */
303:
304: for (i = 1 ; i <= NSIG ; ++ i) {
305: __sigaction_t act;
306:
307: curr_signal_action (i, NULL, & act);
308: if (act.sa_handler != SIG_IGN) {
309: act.sa_handler = SIG_DFL;
310: act.sa_flags = 0;
311: __SIGSET_EMPTY (act.sa_mask);
312: curr_signal_action (i, & act, NULL);
313: }
314: }
315:
316: if (pp->p_flags & PFTRAC) /* Being traced */
317: sendsig (SIGTRAP, pp);
318: idetach (ip);
319:
320: /* initialize u area ndp fields */
321: ndpNewProc ();
322:
323: segload ();
324: goto done;
325:
326:
327: /*
328: * Alas, exec() has failed..
329: */
330: out:
331: /* Deallocate nodes hooked into xlist by exlopen. */
332: while (xlist != NULL) {
333: struct xecnode * tmp = xlist->xn;
334: kfree (xlist);
335: xlist = tmp;
336: }
337:
338: /* Release the INODE for the load file. */
339: idetach (ip);
340:
341: /* If we allocated a text segment, let it go. */
342: if ((segp = pp->p_segp [SISTEXT]) != NULL) {
343: pp->p_segp [SISTEXT] = NULL;
344: sfree (segp);
345: }
346:
347: /* If we allocated a data segment, let it go. */
348: if ((segp = pp->p_segp[SIPDATA]) != NULL) {
349: pp->p_segp [SIPDATA] = NULL;
350: sfree (segp);
351: }
352:
353: /*
354: * Return through the "sys exit" code with a "SIGSYS", or with the
355: * signal actually received if we are aborting due to interrupted exec.
356: */
357:
358: pexit (u.u_error == EINTR ? curr_signal_pending () : SIGSYS);
359:
360: done:
361: return 0;
362: }
363:
364:
365: /*
366: * Open a file, make sure it is l.out, coff, or v86 as well as
367: * executable.
368: *
369: * "xhp" points to a cleared xechdr supplied by the caller.
370: * "np" is the file name.
371: * "shrds" points to an int that will be written by exlopen().
372: * *shrds is set nonzero only for shared l.out.
373: *
374: * If file is COFF, there may be multiple text (or data?) sections.
375: * Use "xlist" linked structure to keep track of variably many sections
376: * after the first text and data sections.
377: *
378: * return NULL if failure, else return inode pointer for the file.
379: */
380:
381: INODE *
382: exlopen(xhp, np, shrds, xlist, dirent)
383: register struct xechdr *xhp;
384: char *np;
385: int *shrds;
386: struct xecnode ** xlist;
387: struct direct * dirent;
388: {
389: register INODE *ip;
390: int i, nscn, hdrsize;
391: register BUF *bp;
392: unsigned short magic;
393: struct ldheader head;
394: struct filehdr fhead;
395: struct aouthdr ahead;
396: struct scnhdr scnhdr;
397: IO io;
398:
399: /*
400: * Make sure the file is executable and read the header. Note that
401: * this about the only case of ftoi () with mode 'r' that actually
402: * uses the resulting filename information.
403: */
404:
405: if (ftoi (np, 'r', & io, dirent))
406: return NULL;
407:
408: ip = u.u_cdiri;
409: if (iaccess (ip, IPE) == 0) {
410: idetach (ip);
411: return NULL;
412: }
413:
414: if ((ip->i_mode & (IPE | (IPE << 3) | (IPE << 6))) == 0 ||
415: (ip->i_mode & IFMT) != IFREG) {
416: u.u_error = EACCES;
417: idetach (ip);
418: return NULL;
419: }
420:
421: if ((bp = vread (ip, (daddr_t) 0)) == NULL) {
422: u.u_error = ENOEXEC;
423: idetach (ip);
424: return NULL;
425: }
426:
427:
428: /*
429: * Copy everything we need from the l.out header and check magic
430: * number and machine type.
431: */
432:
433: * shrds = 0;
434: magic = * (unsigned short *) bp->b_vaddr;
435: canint (magic);
436:
437: switch (magic) {
438: case L_MAGIC: /* Coherent 286 format */
439: memcpy (& head, bp->b_vaddr, sizeof (struct ldheader));
440:
441: canint (head.l_machine);
442: if (head.l_machine != M_8086)
443: goto bad;
444:
445: for (i = 0 ; i < NXSEG ; i ++)
446: cansize (head.l_ssize [i]);
447:
448: canint (head.l_flag);
449: canvaddr (head.l_entry);
450:
451: /*
452: * If a shared and separated image
453: * has stuff in segments that makes it impossible
454: * to share, give an error immediately so that we don't
455: * lose the parent.
456: */
457: head.l_flag &= LF_SHR | LF_SEP | LF_KER;
458:
459: if ((head.l_flag & LF_SEP) == 0 ||
460: (head.l_flag & LF_KER) != 0 ||
461: head.l_ssize [L_PRVI] || head.l_ssize [L_BSSI])
462: goto bad;
463:
464: xhp->magic = XMAGIC (I286MAGIC,I_MAGIC);
465: xhp->entry = head.l_entry;
466:
467: xhp->segs [SISTEXT].fbase = sizeof (struct ldheader);
468: xhp->segs [SISTEXT].mbase = NBPS;
469: xhp->segs [SISTEXT].size = head.l_ssize [L_SHRI];
470:
471: xhp->segs [SIPDATA].fbase = sizeof (struct ldheader) +
472: xhp->segs [SISTEXT].size;
473: xhp->segs [SIPDATA].mbase = 0;
474: xhp->segs [SIPDATA].size = head.l_ssize [L_SHRD] +
475: head.l_ssize [L_PRVD];
476: if (head.l_flag & LF_SHR)
477: * shrds = head.l_ssize [L_SHRD];
478:
479: xhp->segs [SIBSS].fbase = 0;
480: xhp->segs [SIBSS].mbase = xhp->segs [SIPDATA].size;
481: xhp->segs [SIBSS].size = head.l_ssize [L_BSSD];
482:
483: xhp->segs [SISTACK].mbase = ISP_286; /* size 0, fbase 0 */
484: brelease (bp);
485: return ip;
486:
487: case I386MAGIC: /* ... COFF */
488: memcpy (& fhead, bp->b_vaddr, sizeof (struct filehdr));
489: hdrsize = sizeof (ahead) + sizeof (fhead);
490:
491: if (fhead.f_opthdr != sizeof (ahead) ||
492: (fhead.f_flags & F_EXEC) == 0 ||
493: fhead.f_nscns * sizeof (scnhdr) > BSIZE)
494: goto bad;
495:
496: memcpy (& ahead, bp->b_vaddr + sizeof (fhead),
497: sizeof (ahead));
498: if (ahead.magic != Z_MAGIC)
499: goto bad;
500:
501: xhp->magic = XMAGIC (I386MAGIC, ahead.magic);
502: xhp->entry = ahead.entry;
503:
504: for (i = 0 ; i < fhead.f_nscns ; i ++) {
505: memcpy (& scnhdr,
506: bp->b_vaddr + hdrsize + sizeof (scnhdr) * i,
507: sizeof (scnhdr));
508:
509: switch ((int) (scnhdr.s_flags)) {
510: case STYP_INFO:
511: continue;
512:
513: case STYP_BSS:
514: nscn = SIBSS;
515: break;
516:
517: case STYP_TEXT:
518: nscn = SISTEXT;
519: break;
520:
521: case STYP_DATA:
522: nscn = SIPDATA;
523: break;
524:
525: default:
526: goto bad;
527: }
528:
529: /* Text/data shouldn't collide with stack. */
530: if ((unsigned) scnhdr.s_vaddr >= ISP_386)
531: goto bad;
532:
533: /* Have we already seen a segment of this type? */
534: if (xhp->segs [nscn].size) {
535: struct xecnode * tmp;
536:
537: if (nscn != SISTEXT)
538: goto bad;
539:
540: /* insert new node at head of "xlist" */
541: tmp = (struct xecnode *)
542: kalloc (sizeof (struct xecnode));
543:
544: if (tmp == NULL) {
545: printf ("can't kalloc(xecnode)\n");
546: goto bad;
547: }
548:
549: tmp->xn = * xlist;
550: * xlist = tmp;
551: tmp->segtype = nscn;
552: tmp->xseg.mbase = scnhdr.s_vaddr;
553: tmp->xseg.fbase = scnhdr.s_scnptr;
554: tmp->xseg.size = scnhdr.s_size;
555: } else {
556: xhp->segs [nscn].mbase = scnhdr.s_vaddr;
557: xhp->segs [nscn].fbase = scnhdr.s_scnptr;
558: xhp->segs [nscn].size = scnhdr.s_size;
559: }
560: }
561:
562: /* Text and data segments must both be nonempty. */
563: if (! xhp->segs [SISTEXT].size || ! xhp->segs [SIPDATA].size)
564: goto bad;
565:
566: xhp->entry = ahead.entry;
567:
568: xhp->segs [SISTACK].mbase = ISP_386; /* size 0, fbase 0 */
569: xhp->magic = XMAGIC (I386MAGIC, ahead.magic);
570: brelease (bp);
571: return ip;
572: default:
573: bad:
574: brelease (bp);
575: u.u_error = ENOEXEC;
576: idetach (ip);
577: return NULL;
578: }
579: }
580:
581: static SEG *
582: exsread(sp, ip, xsp, shrdSz)
583: register SEG *sp;
584: INODE *ip;
585: struct xecseg *xsp;
586: int shrdSz;
587: {
588: register int sa, so;
589: IO io;
590:
591: sa = xsp->fbase;
592: so = xsp->mbase & (NBPC - 1);
593:
594: io.io_seg = IOPHY;
595: io.io_seek = sa;
596: io.io.pbase = MAPIO (sp->s_vmem, so);
597: io.io_flag = 0;
598:
599: if (shrdSz) { /* shared l.out? */
600:
601: /* Load SHRD. */
602: io.io_ioc = shrdSz;
603: sp->s_lrefc ++;
604: iread (ip, & io);
605: sp->s_lrefc --;
606:
607: if ((io.io_ioc = xsp->size - shrdSz) != 0) {
608:
609: /* Advance file and RAM offsets past SHRD. */
610: sa += shrdSz;
611: so += shrdSz;
612:
613: /* Advance RAM offset to next 16-byte boundary. */
614: so = (so + 15) & ~ 15; /* round up */
615:
616: /* Load PRVD. */
617: io.io_seg = IOPHY;
618: io.io_seek = sa;
619: io.io.pbase = MAPIO (sp->s_vmem, so);
620: io.io_flag = 0;
621:
622: sp->s_lrefc ++;
623: iread (ip, & io);
624: sp->s_lrefc --;
625: }
626: } else { /* NOT shared l.out */
627: io.io_ioc = xsp->size;
628:
629: sp->s_lrefc ++;
630: iread (ip, & io);
631: sp->s_lrefc --;
632: }
633:
634: /*
635: * NIGEL: This perturbs me. This check seems to really belong
636: * somewhere at the top-level, and/or from testing the return values
637: * from the read calls. Why isn't the residual from the read tested?
638: */
639:
640: if (curr_signal_pending ())
641: u.u_error = EINTR;
642:
643: if (u.u_error == 0)
644: return sp;
645: return NULL;
646: }
647:
648:
649: struct adata { /* Storage for arg and env data */
650: int np; /* Number of pointers in vector */
651: int nc; /* Number of characters in strings */
652: };
653:
654:
655: /*
656: * Given a pointer to a list of arguments and a pointer to a list of
657: * environments, return a stack with the arguments and environments on it.
658: */
659:
660: SEG *
661: exstack(xhp, argp, envp, wdin)
662: register struct xechdr *xhp;
663: caddr_t argp, envp;
664: {
665: register SEG *sp; /* Stack segment pointer */
666: struct sdata { /* To keep segment pointers */
667: caddr_t vp; /* Argv[i], envp[i] pointer */
668: caddr_t cp; /* Argv[i][j], envp[i][j] pointer */
669: } stk;
670: struct adata arg, env;
671: int chrsz, vecsz, stksz, wdmask, wdout, stkoff, stktop;
672: int stkenvp;
673: register int i;
674:
675: /* Validate and evaluate size of args and envs */
676: if (! excount (argp, & arg, wdin) || ! excount (envp, & env, wdin))
677: return NULL;
678:
679: /* Calculate stack size and allocate it */
680: chrsz = __ROUND_UP_TO_MULTIPLE (arg.nc + env.nc, sizeof (int));
681: vecsz = (arg.np + 1 + env.np + 1) * sizeof (long);
682: stksz = __ROUND_UP_TO_MULTIPLE (vecsz + chrsz + ISTSIZE, NBPC);
683:
684: if (stksz > MADSIZE || (sp = salloc (stksz, SFDOWN)) == NULL) {
685: u.u_error = E2BIG;
686: return NULL;
687: }
688:
689: /* Set up target stack */
690: stktop = xhp->segs [SISTACK].mbase;
691: stk.cp = stktop - chrsz;
692: stk.vp = stktop - chrsz - vecsz;
693: stkoff = MAPIO (sp->s_vmem, stksz - stktop);
694: u.u_argc = arg.np;
695: u.u_argp = stk.vp;
696: wdmask = -1;
697: if (wdin == sizeof (short))
698: wdmask = (unsigned short) wdmask;
699:
700: switch (stktop) {
701:
702: case ISP_386:
703: wdout = sizeof (long);
704: xhp->initsp = stk.vp - sizeof (long);
705: dmaout (sizeof (long), xhp->initsp + stkoff, & arg.np);
706: break;
707:
708: case ISP_286:
709: wdout = sizeof (short);
710: xhp->initsp = stk.vp - 3 * sizeof (short);
711: stkenvp = stk.vp + (arg.np + 1) * sizeof (short);
712: dmaout (sizeof (short), xhp->initsp + stkoff, & arg.np);
713: dmaout (sizeof (short), xhp->initsp + sizeof (short) + stkoff,
714: & stk.vp);
715: dmaout (sizeof (short), xhp->initsp + 2 * sizeof (short) +
716: stkoff, & stkenvp);
717: break;
718:
719: default:
720: panic("exstack");
721:
722: }
723:
724: /* Arguments */
725: for (i = 0 ; i < arg.np ; i ++, argp += wdin, stk.vp += wdout) {
726: dmaout (wdout, stk.vp + stkoff, & stk.cp);
727: stk.cp += exarg (stk.cp + stkoff, getupd (argp) & wdmask);
728: }
729:
730: /* skip null word after arguments */
731: stk.vp += wdout;
732:
733: /* Environments */
734: for (i = 0; i < env.np ; i ++, envp += wdin, stk.vp += wdout) {
735: dmaout (wdout, stk.vp + stkoff, & stk.cp);
736: stk.cp += exarg (stk.cp + stkoff, getupd (envp) & wdmask);
737: }
738:
739: return sp;
740: }
741:
742: exarg(out, in)
743: caddr_t in, out;
744: {
745: char c;
746: caddr_t init_in;
747:
748: init_in = in;
749: do {
750: c = getubd (in ++);
751: dmaout (sizeof (char), out ++, & c);
752: } while (c);
753: return in - init_in;
754: }
755:
756: /*
757: * Given a pointer to a list of arguments, a pointer to an argument count
758: * and a pointer to a byte count, count the #characters/#strings
759: * in the arguments
760: */
761: excount(usrvp, adp, wdin)
762: register caddr_t usrvp;
763: struct adata *adp;
764: {
765: register caddr_t usrcp;
766: register int c;
767: register unsigned nb;
768: register unsigned na;
769: int wdmask;
770:
771: wdmask = -1;
772: if (wdin == sizeof (short))
773: wdmask = (unsigned short) wdmask;
774: na = nb = 0;
775: if (usrvp != NULL) {
776: for (;;) {
777: usrcp = getupd (usrvp) & wdmask;
778: usrvp += wdin;
779: if (u.u_error)
780: return 0;
781: if (usrcp == NULL)
782: break;
783: na ++;
784: for (;;) {
785: c = getubd (usrcp ++);
786: if (u.u_error)
787: return 0;
788: nb ++;
789: if (c == '\0')
790: break;
791: }
792: }
793: }
794: adp->np = na;
795: adp->nc = nb;
796: return 1;
797: }
798:
799: /*
800: * Round up a size to a paragraph
801: * (mod 16) boundry.
802: * This is really mod 512 to make swapping work
803: */
804: off_t
805: exround(s)
806: off_t s;
807: {
808: return (s + 15) & ~ 0x0F;
809: }
810:
811: pload(np)
812: char * np;
813: {
814: return -1;
815:
816: }
817: /*
818: * Set up the first process, a small program which will exec
819: * the init program.
820: */
821: extern char aicodep[];
822:
823: eveinit()
824: {
825: SEG *sp;
826: register PROC *pp;
827: SELF = pp = eprocp;
828: /* static struct xechdr xecinit[NUSEG+1] = { {0},{0},{0},{ISP_386}}; */
829:
830: /*
831: * Allocate, record, initialize code segment, make it executable.
832: */
833: if ((sp = salloc (__ROUND_UP_TO_MULTIPLE (icodes, NBPC), 0)) == NULL)
834: panic ("eveinit(code)");
835: pp->p_segp [SIPDATA] = sp;
836:
837: /*
838: * Start process.
839: */
840: u.u_argp = 0;
841: if (sproto (0) == 0)
842: panic ("eveinit()");
843: segload ();
844: setspace (SEG_386_UD | R_USR);
845: kucopy (aicodep, 0, icodes);
846: }
847:
848: /*
849: * Given a major number, undo the previous function.
850: */
851: puload(m)
852: int m;
853: {
854: register CON *cp;
855: register DRV *dp;
856:
857: dp = & drvl [m];
858:
859: if (m >= drvn || (cp = dp->d_conp) == NULL) {
860: u.u_error = ENXIO;
861: goto ret;
862: }
863: (* cp->c_uload) ();
864: if (! u.u_error)
865: dp->d_conp = NULL;
866: ret:
867: return 0;
868: }
869:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.