|
|
1.1 root 1: /* $Header: /kernel/kersrc/i286/RCS/exec.c,v 1.1 92/07/17 15:21:27 bin Exp Locker: bin $ */
2: /* (lgl-
3: * The information contained herein is a trade secret of Mark Williams
4: * Company, and is confidential information. It is provided under a
5: * license agreement, and may be copied or disclosed only under the
6: * terms of that agreement. Any reproduction or disclosure of this
7: * material without the express written authorization of Mark Williams
8: * Company or persuant to the license agreement is unlawful.
9: *
10: * COHERENT Version 2.3.37
11: * Copyright (c) 1982, 1983, 1984.
12: * An unpublished work by Mark Williams Company, Chicago.
13: * All rights reserved.
14: -lgl) */
15: /*
16: * This file contains a special version
17: * of "sys exec" for the i8086. This version has
18: * no driver load code in it (save space) and has
19: * special load code so that the text of a shared
20: * and separated image can be shared.
21: * Loadable kernel processes are partially supported:
22: * the process text and data must be ld'ed with the system
23: * and the l.out executed must have no loadable or allocateable
24: * segments.
25: *
26: * $Log: exec.c,v $
27: * Revision 1.1 92/07/17 15:21:27 bin
28: * Initial revision
29: *
30: * Revision 1.1 88/03/24 17:39:26 src
31: * Initial revision
32: *
33: * 88/01/21 Allan Cornish /usr/src/sys/i8086/src/exec.c
34: * Segments are now de-associated from processes before freeing the segment.
35: *
36: * 87/12/03 Allan Cornish /usr/src/sys/i8086/src/exec.c
37: * ld_start() now reverts to kernel mode [depth=0] from user mode [depth=1].
38: *
39: * 87/11/25 Allan Cornish /usr/src/sys/i8086/src/exec.c
40: * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
41: *
42: * 87/11/14 Allan Cornish /usr/src/sys/i8086/src/exec.c
43: * Init code+data now split into icodep/icodes and idatap/idatas.
44: *
45: * 87/11/05 Allan Cornish /usr/src/sys/i8086/src/exec.c
46: * New seg struct now used to allow extended addressing.
47: *
48: * 87/10/09 Allan Cornish /usr/src/sys/i8086/src/exec.c
49: * pload() now handles new format [separate code] loadable device drivers.
50: *
51: * 87/10/08 Allan Cornish /usr/src/sys/i8086/src/exec.c
52: * Exsread() initializes the (IO).io_flag field to 0.
53: */
54: #include <sys/coherent.h>
55: #include <acct.h>
56: #include <sys/buf.h>
57: #include <canon.h>
58: #include <sys/con.h>
59: #include <errno.h>
60: #include <sys/filsys.h>
61: #include <sys/ino.h>
62: #include <sys/inode.h>
63: #include <l.out.h>
64: #include <sys/proc.h>
65: #include <sys/sched.h>
66: #include <sys/seg.h>
67: #include <signal.h>
68: #include <sys/i8086.h>
69:
70: /*
71: * Sizes.
72: */
73: #define sh ((fsize_t)sizeof(struct ldheader))
74: #define si lssize[L_SHRI]
75: #define pi lssize[L_PRVI]
76: #define bi lssize[L_BSSI]
77: #define sd lssize[L_SHRD]
78: #define pd lssize[L_PRVD]
79: #define bd lssize[L_BSSD]
80:
81: /*
82: * Segments.
83: */
84: #define upsp pp->p_segp[SIUSERP]
85: #define sssp pp->p_segp[SISTACK]
86: #define sisp pp->p_segp[SISTEXT]
87: #define pisp pp->p_segp[SIPTEXT]
88: #define pdsp pp->p_segp[SIPDATA]
89:
90: /*
91: * Loadable driver initiation point.
92: */
93: static
94: ld_start()
95: {
96: register SEG * sp;
97: register int ret;
98:
99: /*
100: * Kernel processes start by default at user level.
101: * Revert to kernel level.
102: */
103: if ( depth == 1 )
104: depth--;
105:
106: /*
107: * Initialize memory references.
108: */
109: u.u_btime = timer.t_time;
110: sproto();
111: segload();
112:
113:
114: /*
115: * Invoke the driver if it has a shared or private code segment.
116: */
117: ret = 100;
118: if ( (sp = SELF->p_segp[SISTEXT]) || (sp = SELF->p_segp[SIPTEXT]) ) {
119: ret = ld_xcall( sp->s_faddr );
120: }
121:
122: uexit( ret );
123: }
124:
125: /*
126: * Set up the first process, a small programme which will exec
127: * the init programme.
128: */
129: eveinit(sp)
130: SEG *sp;
131: {
132: register PROC *pp;
133: SELF = pp = eprocp;
134:
135: /*
136: * Record user area.
137: */
138: pp->p_segp[SIUSERP] = sp;
139:
140: /*
141: * Allocate, record, initialize code segment, make it executable.
142: */
143: if ((sp=salloc((fsize_t)icodes, 0)) == NULL)
144: panic("eveinit(code)");
145: pp->p_segp[SIPTEXT] = sp;
146: kfcopy( icodep, sp->s_faddr, icodes );
147: sp->s_flags |= SFTEXT;
148: vremap(sp);
149:
150: /*
151: * Allocate, record, and initialize data segment.
152: */
153: if ((sp=salloc((fsize_t)idatas, 0)) == NULL)
154: panic("eveinit(data)");
155: pp->p_segp[SIPDATA] = sp;
156: kfcopy( idatap, sp->s_faddr, idatas );
157:
158: /*
159: * Allocate and record stack segment.
160: */
161: if ((sp=salloc((fsize_t)UPASIZE, SFDOWN)) == NULL)
162: panic("eveinit()");
163: pp->p_segp[SISTACK] = sp;
164:
165: /*
166: * Start process.
167: */
168: u.u_argp = 0;
169: if (sproto() == 0)
170: panic("eveinit()");
171: segload();
172: }
173:
174: /*
175: * Load a driver which has already been linked into the system image.
176: */
177: pload( np )
178: char * np;
179: {
180: register INODE * ip;
181: register PROC * cpp;
182: struct seg * sp;
183: fsize_t lssize[NUSEG]; /* Segment sizes */
184: int lflag; /* l_flags from l.out */
185: vaddr_t pc; /* l_entry from l.out */
186: int r; /* Flag for "exload" */
187: int s;
188: extern char end[];
189:
190:
191: if (super() == 0) {
192: return( -1 );
193: }
194:
195: /*
196: * Coalesce memory BEFORE loading driver, since it can't be moved.
197: */
198: krunch(10000);
199:
200: if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL) {
201: return( -1 );
202: }
203:
204: /*
205: * New format loadable drivers must have separate code/data.
206: * It must have executable code, but no initialized data.
207: * Uninitialized data must match the kernel data size.
208: */
209: if ( ((lflag & (LF_KER|LF_SHR|LF_SEP)) != (LF_SEP|LF_KER))
210: || (si==0) || (sd!=0) || (pd!=0) || (bd != (int)end) ) {
211: u.u_error = EBADFMT;
212: idetach(ip);
213: return( -1 );
214: }
215:
216: /*
217: * Allocate and initialize driver code segment.
218: * NOTE: Must be system segment to prevent relocation.
219: */
220: sp = ssalloc(&r, ip, SFTEXT|SFHIGH|SFNSWP|SFSYST, si+pi+bi, sh, si+pi);
221:
222: /*
223: * Release driver object file.
224: */
225: idetach(ip);
226:
227: if ( r < 0 ) {
228: u.u_error = ENOMEM;
229: return( -1 );
230: }
231:
232: /*
233: * Spawn kernel process to service driver.
234: */
235: if ((cpp = process(ld_start)) == NULL ) {
236: u.u_error = ENOMEM;
237: sfree(sp);
238: return( -1 );
239: }
240:
241: /*
242: * Record the basename of the loaded driver.
243: */
244: kscopy( u.u_direct.d_name, cpp->p_segp[SIUSERP],
245: offset(uproc,u_comm[0]), sizeof(u.u_comm) );
246:
247: /*
248: * Record the driver code segment in the process's private code.
249: */
250: cpp->p_segp[SIPTEXT] = sp;
251: cpp->p_cval = CVCHILD;
252: cpp->p_sval = SVCHILD;
253: cpp->p_rval = RVCHILD;
254: cpp->p_ppid = 1;
255:
256: /*
257: * Make the process executable.
258: */
259: s = sphi();
260: setrun( cpp );
261: spl( s );
262:
263: /*
264: * Return driver process id.
265: */
266: return( cpp->p_pid );
267: }
268:
269: /*
270: * Given a major number, undo the previous function.
271: */
272: puload(m)
273: int m;
274: {
275: register CON *cp;
276: register DRV *dp;
277:
278: dp = &drvl[m];
279: lock(dp->d_gate);
280: if (m>=drvn || (cp=dp->d_conp)==NULL) {
281: u.u_error = ENXIO;
282: goto ret;
283: }
284: (*cp->c_uload)();
285: if ( ! u.u_error)
286: dp->d_conp = NULL;
287: ret:
288: unlock(dp->d_gate);
289: return (0);
290: }
291:
292: /*
293: * Pass control to an image in a file.
294: * Make sure the format is acceptable. Release
295: * the old segments. Read in the new ones. Some special
296: * care is taken so that shared and (more important) shared
297: * and separated images can be run on the 8086.
298: */
299: pexece(np, argp, envp)
300: char *np;
301: char *argp[];
302: char *envp[];
303: {
304: register INODE *ip; /* Load file INODE */
305: register PROC *pp; /* A cheap copy of SELF */
306: register SEG *ssp; /* New stack segment */
307: register SEG *segp;
308: register fsize_t ss; /* Segment size temp. */
309: register int i; /* For looping over segments */
310: int r; /* Flag for "exload" */
311: int lflag; /* l_flags from l.out */
312: vaddr_t pc; /* l_entry from l.out */
313: vaddr_t sp; /* Initial stack pointer */
314: fsize_t lssize[NUSEG]; /* Segment sizes */
315: fsize_t codsize; /* Total if CS segment */
316: fsize_t datsize; /* Total of DS segment */
317: extern fsize_t exround(); /* Paragraph rounder */
318:
319: pp = SELF;
320: if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL) {
321: return;
322: }
323:
324: if ( (lflag & LF_SEP) == 0 ) {
325: u.u_error = EBADFMT;
326: idetach(ip);
327: return;
328: }
329:
330: /*
331: * Kernel processes are now supported through the sload() system call.
332: * 87/10/09 Allan Cornish.
333: */
334: if ((lflag&LF_KER) != 0) {
335: u.u_error = EBADFMT;
336: idetach(ip);
337: return;
338: }
339:
340: /*
341: * If a shared and separated image
342: * has stuff in segments that makes it impossible
343: * to share, give an error immediately so that we don't
344: * lose the parent.
345: */
346: lflag &= LF_SHR|LF_SEP;
347:
348: if (lflag==(LF_SHR|LF_SEP) && (pi!=0 || bi!=0)) {
349: u.u_error = EBADFMT;
350: idetach(ip);
351: return;
352: }
353:
354: if ((ssp=exstack(&sp, argp, envp)) == NULL) {
355: idetach(ip);
356: return;
357: }
358:
359: switch (lflag) {
360: case LF_SEP:
361: codsize = si+pi+bi;
362: datsize = ssp->s_size+sd+pd+bd;
363: break;
364: case LF_SHR|LF_SEP:
365: codsize = si;
366: datsize = ssp->s_size+exround(sd)+pd+bd;
367: break;
368: }
369: codsize = (codsize+(BSIZE-1)) & ~(BSIZE-1);
370: datsize = (datsize+(BSIZE-1)) & ~(BSIZE-1);
371: if ( (codsize >= MAXU) || (datsize >= MAXU) ) {
372: u.u_error = E2BIG;
373: idetach(ip);
374: return;
375: }
376:
377: /*
378: * At this point the file has been
379: * validated as an object module, and the
380: * argument list has been built. Release all of
381: * the original segments. At this point we have
382: * committed to the new image. A "sys exec" that
383: * gets an I/O error is doomed.
384: * NOTE: User-area segment is NOT released.
385: * Segment pointer in proc is erased BEFORE invoking sfree().
386: */
387: for ( i = 1; i < NUSEG; ++i ) {
388: if ((segp = pp->p_segp[i]) != NULL) {
389: pp->p_segp[i] = NULL;
390: sfree(segp);
391: }
392: }
393:
394: /*
395: * Read in the loadable segments.
396: */
397: sssp = ssp;
398: switch (lflag) {
399: case 0:
400: ss = si+pi+sd+pd;
401: pdsp = ssalloc(&r, ip, 0, ss+bi+bd, sh, ss);
402: if (r < 0)
403: goto out;
404: break;
405:
406: case LF_SHR:
407: ss = exround(si+sd);
408: pdsp = ssalloc(&r, ip, 0, ss+pi+pd+bi+bd, sh, si);
409: if (r < 0)
410: goto out;
411: if (exsread(pdsp, ip, sd, sh+si+pi, si) == NULL)
412: goto out;
413: if (exsread(pdsp, ip, pi, sh+si, ss) == NULL)
414: goto out;
415: if (exsread(pdsp, ip, pd, sh+si+pi+sd, ss+pi) == NULL)
416: goto out;
417: break;
418:
419: case LF_SEP:
420: pisp = ssalloc(&r, ip, SFTEXT, si+pi+bi, sh, si+pi);
421: if (r < 0)
422: goto out;
423: pdsp = ssalloc(&r, ip, 0, sd+pd+bd, sh+si+pi, sd+pd);
424: if (r < 0)
425: goto out;
426: break;
427:
428: case LF_SHR|LF_SEP:
429: /* pi=0, bi=0 */
430: sisp = ssalloc(&r, ip, SFSHRX|SFTEXT, si, sh, si);
431: if (r < 0)
432: goto out;
433: ss = exround(sd);
434: pdsp = ssalloc(&r, ip, 0, ss+pd+bd, sh+si, sd);
435: if (r<0 || exsread(pdsp, ip, pd, sh+si+sd, ss) == NULL)
436: goto out;
437: }
438: if (sproto() == 0)
439: goto out;
440: #if 0
441: if ( (datsize != pdsp->s_size) ||
442: ( (lflag==LF_SEP) && (codsize != pisp->s_size) ) ||
443: ( (lflag==(LF_SEP|LF_SHR)) && (codsize != sisp->s_size) ) ) {
444: printf("\nExec ERROR: codsize: 0x%X datsize: 0x%X\n",
445: codsize, datsize);
446: printf(
447: "pdsp->s_size: 0x%X pisp->s_size: 0x%X sisp->s_size: 0x%X\n",
448: pdsp->s_size, pisp->s_size, sisp->s_size);
449: }
450: #endif
451: /*
452: * The new image is read in
453: * and mapped. Perform the final grunge
454: * (set-uid stuff, accounting, loading up
455: * registers, etc).
456: */
457: u.u_flag &= ~AFORK;
458: kkcopy(u.u_direct.d_name, u.u_comm, sizeof(u.u_comm));
459: if (iaccess(ip, IPR) == 0) { /* Can't read ? no dump or trace */
460: pp->p_flags |= PFNDMP;
461: pp->p_flags &= ~PFTRAC;
462: }
463: if (iaccess(ip, IPW) == 0) /* Can't write ? no trace */
464: pp->p_flags &= ~PFTRAC;
465: if ((ip->i_mode&ISUID) != 0) { /* Set user id ? no trace */
466: pp->p_uid = u.u_uid = ip->i_uid;
467: pp->p_flags &= ~PFTRAC;
468: }
469: if ((ip->i_mode&ISGID) != 0) { /* Set group id ? no trace */
470: u.u_gid = ip->i_gid;
471: pp->p_flags &= ~PFTRAC;
472: }
473: for (i=0; i<NSIG; ++i)
474: if (u.u_sfunc[i] != SIG_IGN)
475: u.u_sfunc[i] = SIG_DFL;
476: if ((pp->p_flags&PFTRAC) != 0) /* Being traced */
477: sendsig(SIGTRAP, pp);
478: idetach(ip);
479: msetusr(pc, sp);
480: segload();
481: return (0);
482:
483: /*
484: * We did not make it.
485: * Release the INODE for the load
486: * file, and return through the "sys exit"
487: * code with a "SIGSYS", or with the signal actually received
488: * if we are aborting due to interrupted exec.
489: */
490: out:
491: idetach(ip);
492: if (u.u_error == EINTR)
493: pexit(nondsig());
494: pexit(SIGSYS);
495: }
496:
497: /*
498: * Open an l.out, make sure it is an l.out and executable and return the
499: * appropriate information.
500: */
501: INODE *
502: exlopen(np, ssizep, flagp, pcp)
503: char *np;
504: fsize_t *ssizep;
505: int *flagp;
506: vaddr_t *pcp;
507: {
508: register INODE *ip;
509: register struct ldheader *ldp;
510: register int n;
511: register BUF *bp;
512: int m;
513:
514: /*
515: * Make sure the file is really an executable l.out and read the
516: * header in.
517: */
518: if (ftoi(np, 'r') != 0)
519: return (NULL);
520: ip = u.u_cdiri;
521: if (iaccess(ip, IPE) == 0) {
522: idetach(ip);
523: return (NULL);
524: }
525: if ((ip->i_mode&(IPE|IPE<<3|IPE<<6))==0 || (ip->i_mode&IFMT)!=IFREG) {
526: u.u_error = EACCES;
527: idetach(ip);
528: return (NULL);
529: }
530: if ((bp=vread(ip, (daddr_t)0)) == NULL) {
531: u.u_error = EBADFMT;
532: idetach(ip);
533: return (NULL);
534: }
535:
536: /*
537: * Copy everything we need from the l.out header and check magic
538: * number and machine type.
539: */
540: ldp = FP_OFF(bp->b_faddr);
541: m = ldp->l_magic;
542: canint(m);
543: if (m != L_MAGIC) {
544: u.u_error = ENOEXEC;
545: brelease(bp);
546: idetach(ip);
547: return (NULL);
548: }
549: m = ldp->l_machine;
550: canint(m);
551: if (m != mactype) {
552: u.u_error = EBADFMT;
553: brelease(bp);
554: idetach(ip);
555: return (NULL);
556: }
557: kkcopy(ldp->l_ssize, ssizep, NXSEG*sizeof(fsize_t));
558: for (n=0; n<NXSEG; n++)
559: cansize(ssizep[n]);
560: *flagp = ldp->l_flag;
561: canint(*flagp);
562: *pcp = ldp->l_entry;
563: canvaddr(*pcp);
564: brelease(bp);
565: return (ip);
566: }
567:
568: /*
569: * Given a segment `sp', read `ss' bytes from the inode `ip' starting
570: * at seek address `sa' into offset `so' in the segment.
571: */
572: SEG *
573: exsread(sp, ip, ss, sa, so)
574: register SEG *sp;
575: INODE *ip;
576: fsize_t ss;
577: fsize_t sa;
578: fsize_t so;
579: {
580: while (ss > 0) {
581: u.u_io.io_seg = IOPHY;
582: u.u_io.io_seek = sa;
583: u.u_io.io_phys = sp->s_paddr + so;
584: u.u_io.io_flag = 0;
585: if (ss >= 4096) {
586: u.u_io.io_ioc = 4096;
587: ss -= 4096;
588: } else {
589: u.u_io.io_ioc = ss;
590: ss = 0;
591: }
592: sp->s_lrefc++;
593: iread(ip, &u.u_io);
594: sp->s_lrefc--;
595: if (nondsig()) {
596: u.u_error = EINTR;
597: break;
598: }
599: sa += 4096;
600: so += 4096;
601: }
602: if (u.u_error == 0)
603: return (sp);
604: return (NULL);
605: }
606:
607: /*
608: * Given a pointer to a list of arguments and a pointer to a list of
609: * environments, return a stack with the arguments and environments on it.
610: */
611: SEG *
612: exstack(iusp, argp, envp)
613: char **iusp; /* Back patch sp value */
614: char *argp[]; /* Arguments for new process */
615: char *envp[]; /* Environments for new process */
616: {
617: SEG *sp; /* Stack segment pointer */
618: struct adata { /* Storage for arg and env data */
619: char **up; /* User vector pointer */
620: int np; /* Number of pointers in vector */
621: int nc; /* Number of characters in strings */
622: } arg, env;
623: struct sdata { /* To keep segment pointers */
624: vaddr_t base; /* Top of segment virtual */
625: vaddr_t ap; /* Argc, argv, envp pointer */
626: vaddr_t vp; /* Argv[i], envp[i] pointer */
627: vaddr_t cp; /* Argv[i][j], envp[i][j] pointer */
628: } aux, stk;
629: aold_t aold; /* Auxiliary map storage */
630: register char **usrvp; /* Vector pointer into user seg */
631: register char *usrcp; /* Character pointer into user seg */
632: register int c; /* Character fetched from user */
633: register int chrsz; /* Size of strings */
634: register struct adata *adp; /* Arg and env scanner */
635: register int vecsz; /* Size of vectors */
636: register int stksz; /* Size of stack argument region */
637:
638: /* Validate and evaluate size of args and envs */
639: arg.up = argp;
640: env.up = envp;
641: chrsz = 0;
642: vecsz = 0;
643: for (adp = &arg; ; adp = &env) {
644: adp->np = 0;
645: adp->nc = 0;
646: if (excount(adp->up, &adp->np, &adp->nc) == 0)
647: return (NULL);
648: chrsz += adp->nc * sizeof(char);
649: vecsz += adp->np * sizeof(char *);
650: if (adp == &env)
651: break;
652: }
653:
654: /* Calculate stack size and allocate it */
655: chrsz = roundu(chrsz, sizeof(int));
656: stksz = sizeof(int) /* argc */
657: + sizeof(char **) /* argv */
658: + sizeof(char **) /* envp */
659: + vecsz /* argv[i] and envp[i] */
660: + chrsz /* *argv[i] and *envp[i] */
661: + sizeof(int) /* Mystery zero word */
662: + sizeof(char *) /* Splimit for z8000 */
663: + sizeof(int); /* errno */
664: stksz += ISTSIZE;
665: if (stksz > MADSIZE) {
666: u.u_error = E2BIG;
667: return (NULL);
668: }
669: if ((sp=salloc((fsize_t)stksz, SFDOWN)) == NULL)
670: return (NULL);
671: stksz -= ISTSIZE;
672:
673: /*
674: * Initialize segment data.
675: */
676: asave(aold);
677:
678: abase(FP_SEL(sp->s_faddr));
679: aux.base = sp->s_size;
680: aux.ap = aux.base - stksz;
681: aux.vp = aux.ap + sizeof(int) + 2*sizeof(char **);
682: aux.cp = aux.vp + vecsz;
683:
684: stk.base = ISTVIRT;
685: stk.ap = stk.base - stksz;
686: stk.vp = stk.ap + sizeof(int) + 2*sizeof(char **);
687: stk.cp = stk.vp + vecsz;
688:
689: /*
690: * Write argc.
691: */
692: aputi((int *)aux.ap, arg.np-1);
693: aux.ap += sizeof(int);
694:
695: /*
696: * Arguments and environments.
697: */
698: for (adp = &arg; ; adp = &env) {
699:
700: /* Write argv or envp */
701: aputp((char ***)aux.ap, (char **)stk.vp);
702: aux.ap += sizeof(char **);
703: if ((usrvp = adp->up) != NULL) {
704:
705: /* Write argv[i] or envp[i] */
706: while ((usrcp = getupd(usrvp++)) != NULL) {
707: aputp((char **)aux.vp, (char *)stk.cp);
708: aux.vp += sizeof(char *);
709: stk.vp += sizeof(char *);
710:
711: /* Write argv[i][j] or envp[i][j] */
712: do {
713: c = getubd(usrcp++);
714: aputc((char *)aux.cp, c);
715: aux.cp += sizeof(char);
716: stk.cp += sizeof(char);
717: } while (c != '\0');
718: }
719: }
720:
721: /* Write argv[argc] or envp[envc] */
722: aputp((char **)aux.vp, NULL);
723: aux.vp += sizeof(char *);
724: stk.vp += sizeof(char *);
725: if (adp == &env)
726: break;
727: }
728:
729: /*
730: * Clear out the slop.
731: */
732: aux.base -= sizeof(int);
733: aputi((int *) aux.base, 0); /* errno */
734: aux.base -= sizeof(char *);
735: aputp((char **) aux.base, (char *)stk.base - sp->s_size + SOVSIZE);
736: aux.base -= sizeof(int);
737: aputi((int *) aux.base, 0); /* mystery word */
738:
739: arest(aold);
740:
741: /*
742: * Patch some values and return.
743: */
744: *iusp = stk.ap; /* Patch initial usp */
745: u.u_argc = arg.np-1;
746: u.u_argp = stk.vp; /* Points after NULL of envs */
747: return (sp);
748: }
749:
750: /*
751: * Given a pointer to a list of arguments, a pointer to an argument count
752: * and a pointer to a byte count, update incrementally the argument count
753: * and the byte count.
754: */
755: excount(usrvp, nap, nbp)
756: register char **usrvp;
757: int *nap;
758: int *nbp;
759: {
760: register char *usrcp;
761: register int c;
762: register unsigned nb;
763: register unsigned na;
764:
765: na = 1;
766: nb = 0;
767: if (usrvp != NULL) {
768: for (;;) {
769: usrcp = getupd(usrvp++);
770: if (u.u_error)
771: return (0);
772: if (usrcp == NULL)
773: break;
774: na++;
775: for (;;) {
776: c = getubd(usrcp++);
777: if (u.u_error)
778: return (0);
779: nb++;
780: if (c == '\0')
781: break;
782: }
783: }
784: }
785: *nap += na;
786: *nbp += nb;
787: return (1);
788: }
789:
790: /*
791: * Round up a size to a paragraph
792: * (mod 16) boundry.
793: * This is really mod 512 to make swapping work
794: */
795: fsize_t
796: exround(s)
797: fsize_t s;
798: {
799: return ((s+15)&~0x0F);
800: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.