|
|
1.1 root 1: /* (lgl-
2: * The information contained herein is a trade secret of Mark Williams
3: * Company, and is confidential information. It is provided under a
4: * license agreement, and may be copied or disclosed only under the
5: * terms of that agreement. Any reproduction or disclosure of this
6: * material without the express written authorization of Mark Williams
7: * Company or persuant to the license agreement is unlawful.
8: *
9: * COHERENT Version 2.3.37
10: * Copyright (c) 1982, 1983, 1984.
11: * An unpublished work by Mark Williams Company, Chicago.
12: * All rights reserved.
13: *
14: * Intel 386 port and extensions (16/32 bit compatibility)
15: * Copyright (c) Ciaran O'Donnell, Bievres (FRANCE), 1991
16: *
17: * $Log: exec.c,v $
18: * Revision 1.10 92/07/16 16:33:31 hal
19: * Kernel #58
20: *
21: * Revision 1.9 92/06/11 21:39:19 root
22: * Add close on exec.
23: *
24: * Revision 1.8 92/06/10 12:51:09 hal
25: * Do click roundup on call to salloc for eveinit.
26: * Assorted cosmetic changes.
27: *
28: * Revision 1.6 92/02/11 10:09:57 hal
29: * Execute shared l.out's now
30: *
31: * Revision 1.5 92/02/10 18:11:27 hal
32: * Ignore SHR bit in l.out's for now.
33: *
34: * Revision 1.4 92/01/23 18:15:28 hal
35: * Add "double sfree" fix from Ciaran.
36: *
37: * Revision 1.3 92/01/15 11:11:26 hal
38: * Remove exlock temporary fix.
39: *
40: * Revision 1.2 92/01/06 11:58:57 hal
41: * Compile with cc.mwc.
42: *
43: *
44: -lgl) */
45: #include <sys/coherent.h>
46: #include <acct.h>
47: #include <sys/buf.h>
48: #include <canon.h>
49: #include <sys/con.h>
50: #include <errno.h>
51: #include <fcntl.h>
52: #include <sys/filsys.h>
53: #include <sys/ino.h>
54: #include <sys/inode.h>
55: #include <a.out.h>
56: #include <l.out.h>
57: #include <sys/proc.h>
58: #include <sys/sched.h>
59: #include <sys/seg.h>
60: #include <signal.h>
61: #include <sys/reg.h>
62: #include <sys/stat.h>
63: #include <sys/fd.h>
64:
65: /*
66: * Pass control to an image in a file.
67: * Make sure the format is acceptable. Release
68: * the old segments. Read in the new ones. Some special
69: * care is taken so that shared and (more important) shared
70: * and separated images can be run on the 8086.
71: */
72: pexece(np, argp, envp)
73: char *np;
74: char *argp[];
75: char *envp[];
76: {
77: struct xechdr head;
78: register INODE *ip; /* Load file INODE */
79: register PROC *pp; /* A cheap copy of SELF */
80: register SEG *segp;
81: SEG *ssegp;
82: register int i; /* For looping over segments*/
83: register BUF *bp;
84: int roundup;
85: int shrdsize;
86:
87: pp = SELF;
88: kclear(&head, sizeof(head));
89: if ((ip=exlopen(&head, np, &shrdsize)) == NULL)
90: goto done;
91: roundup = (shrdsize) & 0xf;
92: ssegp = exstack(&head,argp, envp, wdsize());
93:
94: if (!ssegp) {
95: idetach(ip);
96: goto done;
97: }
98:
99: /*
100: * At this point the file has been
101: * validated as an object module, and the
102: * argument list has been built. Release all of
103: * the original segments. At this point we have
104: * committed to the new image. A "sys exec" that
105: * gets an I/O error is doomed.
106: * NOTE: User-area segment is NOT released.
107: * Segment pointer in proc is erased BEFORE invoking sfree().
108: */
109:
110: for ( i = 1; i < NUSEG; ++i ) {
111: if ((segp = pp->p_segp[i]) != NULL) {
112: pp->p_segp[i] = NULL;
113: sfree(segp);
114: }
115: }
116: pp->p_segp[SISTACK] = ssegp;
117:
118: /*
119: * Read in the loadable segments.
120: */
121: switch (head.magic) {
122: case XMAGIC( I286MAGIC,I_MAGIC ):
123: u.u_regl[CS] = SEG_286_UII | R_USR;
124: u.u_regl[DS] = SEG_286_UD | R_USR;
125: segp = pp->p_segp[SISTEXT] = ssalloc(ip,SFTEXT,
126: head.segs[SISTEXT].size);
127: if (!exsread(segp, ip, &head.segs[SISTEXT], 0)) {
128: goto out;
129: }
130: segp = ssalloc(ip,0,roundup+
131: head.segs[SIPDATA].size+head.segs[SIBSS].size);
132: pp->p_segp[SIPDATA] = segp;
133: if (!exsread(segp,ip,&head.segs[SIPDATA],shrdsize)) {
134: goto out;
135: }
136: head.segs[SIPDATA].size += roundup;
137: break;
138: case XMAGIC( I386MAGIC,Z_MAGIC ):
139: u.u_regl[CS] = SEG_386_UI | R_USR;
140: u.u_regl[DS] = SEG_386_UD | R_USR;
141: segp = pp->p_segp[SISTEXT] = ssalloc(ip,SFTEXT|SFSHRX,
142: head.segs[SISTEXT].size);
143: if (segp->s_ip==0) {
144: if (!exsread(segp, ip, &head.segs[SISTEXT], 0)) {
145: goto out;
146: }
147: segp->s_ip = ip;
148: ip->i_refc++;
149: }
150: segp = ssalloc(ip,0,
151: head.segs[SIPDATA].size+head.segs[SIBSS].size);
152: pp->p_segp[SIPDATA] = segp;
153: if (segp->s_ip==0 &&
154: !exsread(segp, ip, &head.segs[SIPDATA], 0)) {
155: goto out;
156: }
157: break;
158: default:
159: panic("pexece");
160: }
161:
162: u.u_regl[SS] = u.u_regl[ES] = u.u_regl[DS];
163: if (sproto(&head) == 0) {
164: goto out;
165: }
166:
167: /*
168: * The new image is read in
169: * and mapped. Perform the final grunge
170: * (set-uid stuff, accounting, loading up
171: * registers, etc).
172: */
173: u.u_flag &= ~AFORK;
174: kkcopy(u.u_direct.d_name, u.u_comm, sizeof(u.u_comm));
175: if (iaccess(ip, IPR) == 0) { /* Can't read ? no dump or trace */
176: pp->p_flags |= PFNDMP;
177: pp->p_flags &= ~PFTRAC;
178: }
179:
180: /*
181: * Norm says Frank says we need to drop this for db to work.
182: */
183: if (iaccess(ip, IPW) == 0) /* Can't write ? no trace */
184: pp->p_flags &= ~PFTRAC;
185:
186: if ((ip->i_mode&ISUID) != 0) { /* Set user id ? no trace */
187: pp->p_uid = u.u_uid = ip->i_uid;
188: pp->p_flags &= ~PFTRAC;
189: }
190: if ((ip->i_mode&ISGID) != 0) { /* Set group id ? no trace */
191: u.u_gid = ip->i_gid;
192: pp->p_flags &= ~PFTRAC;
193: }
194: for (i=0; i < NUFILE; i++) {
195: if (u.u_filep[i]!=NULL && (u.u_filep[i]->f_flag2&FD_CLOEXEC)) {
196: fdclose(i); /* close fd on exec bit set */
197: }
198: }
199: /*
200: * Default every signal that is not ignored.
201: */
202: for (i=0; i<NSIG; ++i) {
203: if (u.u_sfunc[i] != SIG_IGN) {
204: u.u_sfunc[i] = SIG_DFL;
205: pp->p_dfsig |= ((sig_t) 1) << (i - 1);
206: }
207: }
208: if ((pp->p_flags&PFTRAC) != 0) /* Being traced */
209: sendsig(SIGTRAP, pp);
210: idetach(ip);
211: msetusr(head.entry, head.initsp);
212:
213: segload();
214: goto done;
215:
216: /*
217: * We did not make it.
218: * Release the INODE for the load
219: * file, and return through the "sys exit"
220: * code with a "SIGSYS", or with the signal actually received
221: * if we are aborting due to interrupted exec.
222: */
223: out:
224: idetach(ip);
225: if (u.u_error == EINTR)
226: pexit(nondsig());
227: pexit(SIGSYS);
228:
229: done:
230: return 0;
231: }
232:
233: /*
234: * Open an l.out, make sure it is an l.out and executable and return the
235: * appropriate information.
236: */
237: INODE *
238: exlopen(xhp, np, shrds)
239: register struct xechdr *xhp;
240: char *np;
241: int *shrds;
242: {
243: register INODE *ip;
244: int i, nscn, diff, hdrsize;
245: register BUF *bp;
246: unsigned short magic;
247: struct ldheader head;
248: struct filehdr fhead;
249: struct aouthdr ahead;
250: struct scnhdr scnhdr;
251:
252: /*
253: * Make sure the file is really an executable l.out and read the
254: * header in.
255: */
256: if (ftoi(np, 'r') != 0)
257: return (NULL);
258: ip = u.u_cdiri;
259: if (iaccess(ip, IPE) == 0) {
260: idetach(ip);
261: return (NULL);
262: }
263: if ((ip->i_mode&(IPE|IPE<<3|IPE<<6))==0 || (ip->i_mode&IFMT)!=IFREG) {
264: u.u_error = EACCES;
265: idetach(ip);
266: return (NULL);
267: }
268: if ((bp=vread(ip, (daddr_t)0)) == NULL)
269: goto bad;
270: /*
271: * Copy everything we need from the l.out header and check magic
272: * number and machine type.
273: */
274: *shrds = 0; /* set return arg shrds nonzero only for shared l.out */
275: kkcopy(bp->b_vaddr, &magic, sizeof(magic));
276: canint(magic);
277: switch (magic) {
278: case L_MAGIC: /* Coherent 286 format */
279: kkcopy(bp->b_vaddr, &head, sizeof(struct ldheader));
280: canint(head.l_machine);
281: if (head.l_machine!=M_8086)
282: goto bad;
283: for (i=0; i<NXSEG; i++) {
284: cansize(head.l_ssize[i]);
285: }
286: canint(head.l_flag);
287: canvaddr(head.l_entry);
288:
289: /*
290: * If a shared and separated image
291: * has stuff in segments that makes it impossible
292: * to share, give an error immediately so that we don't
293: * lose the parent.
294: */
295: head.l_flag &= LF_SHR|LF_SEP|LF_KER;
296:
297: if ((head.l_flag&LF_SEP==0) || (head.l_flag &LF_KER)
298: || head.l_ssize[L_PRVI] || head.l_ssize[L_BSSI]) {
299: goto bad;
300: }
301: xhp->magic = XMAGIC( I286MAGIC,I_MAGIC );
302: xhp->entry = head.l_entry;
303:
304: xhp->segs[SISTEXT].fbase = sizeof(struct ldheader);
305: xhp->segs[SISTEXT].mbase = NBPS;
306: xhp->segs[SISTEXT].size = head.l_ssize[L_SHRI];
307:
308: xhp->segs[SIPDATA].fbase = sizeof(struct ldheader) +
309: xhp->segs[SISTEXT].size;
310: xhp->segs[SIPDATA].mbase = 0;
311: xhp->segs[SIPDATA].size = head.l_ssize[L_SHRD] +
312: head.l_ssize[L_PRVD];
313: if (head.l_flag & LF_SHR)
314: *shrds = head.l_ssize[L_SHRD];
315:
316: xhp->segs[SIBSS].fbase = 0;
317: xhp->segs[SIBSS].mbase = xhp->segs[SIPDATA].size;
318: xhp->segs[SIBSS].size = head.l_ssize[L_BSSD];
319:
320: xhp->segs[SISTACK].mbase = ISP_286; /* size 0, fbase 0 */
321: brelease(bp);
322: return ip;
323:
324: case I386MAGIC: /* ... COFF */
325: kkcopy(bp->b_vaddr, &fhead, sizeof(struct filehdr));
326: hdrsize = sizeof(ahead)+sizeof(fhead);
327: if(fhead.f_opthdr!=sizeof (ahead) || !(fhead.f_flags&F_EXEC)||
328: fhead.f_nscns*sizeof(scnhdr) > BSIZE)
329: goto bad;
330:
331: kkcopy(bp->b_vaddr+sizeof(fhead), &ahead, sizeof(ahead));
332: if ((/*ahead.magic!=O_MAGIC && ahead.magic!=N_MAGIC && */
333: ahead.magic!=Z_MAGIC))
334: goto bad;
335:
336: xhp->magic = XMAGIC( I386MAGIC,ahead.magic );
337: xhp->entry = ahead.entry;
338:
339: for (i=0; i<fhead.f_nscns; i++) {
340: kkcopy(bp->b_vaddr + hdrsize + sizeof(scnhdr)*i,
341: &scnhdr, sizeof(scnhdr));
342: switch ((int)(scnhdr.s_flags)) {
343: case STYP_INFO:
344: continue;
345: case STYP_BSS:
346: nscn = SIBSS;
347: break;
348: case STYP_TEXT:
349: nscn = SISTEXT; goto common;
350: case STYP_DATA:
351: nscn = SIPDATA;
352: common:
353: diff = scnhdr.s_scnptr & (NBPC-1);
354: scnhdr.s_vaddr -= diff;
355: scnhdr.s_scnptr -= diff;
356: scnhdr.s_size += diff;
357: break;
358: default:
359: goto bad;
360: }
361:
362: if (xhp->segs[nscn].size!=0
363: || (unsigned)scnhdr.s_vaddr >= ISP_386)
364: goto bad;
365:
366: xhp->segs[nscn].mbase = scnhdr.s_vaddr;
367: xhp->segs[nscn].fbase = scnhdr.s_scnptr;
368: xhp->segs[nscn].size = scnhdr.s_size;
369: }
370:
371: if (!xhp->segs[SISTEXT].size || !xhp->segs[SIPDATA].size)
372: goto bad;
373:
374: xhp->entry = ahead.entry;
375: if (xhp->entry >= xhp->segs[SISTEXT].size)
376: goto bad;
377:
378: xhp->segs[SISTACK].mbase = ISP_386; /* size 0, fbase 0 */
379: xhp->magic = XMAGIC( I386MAGIC,ahead.magic );
380: brelease(bp);
381: return ip;
382: default:
383: bad:
384: brelease(bp);
385: u.u_error = ENOEXEC;
386: idetach(ip);
387: return NULL;
388: }
389: }
390:
391: /*
392: * Given a segment `sp', read `ss' bytes from the inode `ip' starting
393: * at seek address `sa' into offset `so' in the segment.
394: *
395: * Argument "first" is nonzero only when loading data for l.out -
396: * need this because *shared* l.out's need PRVD to be aligned on the next
397: * 16 byte boundary after the end of SHRD. So we need to leave a hole
398: * between SHRD and PRVD in this case.
399: */
400: static SEG *
401: exsread(sp, ip, xsp, first)
402: register SEG *sp;
403: INODE *ip;
404: struct xecseg *xsp;
405: int first;
406: {
407: register int ss, sa, so, did;
408: int overshoot;
409:
410: sa = xsp->fbase;
411: so = 0;
412:
413: for (ss = first ? first : xsp->size;; ss -= did) {
414: if (!ss) { /* we finished a hunk */
415: /* is there more to read */
416: if (!first || (!(ss = xsp->size - first)))
417: break;
418: so = (so + 15) & ~15; /* round up */
419: first = 0; /* don't go again */
420: }
421: u.u_io.io_seg = IOPHY;
422: u.u_io.io_seek = sa;
423: u.u_io.io.pbase = MAPIO(sp->s_vmem, so);
424: u.u_io.io_flag = 0;
425: /*
426: * "did" is how many bytes to read in with this request.
427: */
428: if (ss >= 4096)
429: did = u.u_io.io_ioc = 4096;
430: else
431: did = u.u_io.io_ioc = ss;
432: /*
433: * Don't allow incoming data to straddle a 4k segment.
434: */
435: overshoot = did + (so & 4095) - 4096;
436: if (overshoot > 0)
437: did -= overshoot;
438: sp->s_lrefc++;
439: iread(ip, &u.u_io);
440: sp->s_lrefc--;
441: if (nondsig()) {
442: u.u_error = EINTR;
443: break;
444: }
445: sa += did;
446: so += did;
447: }
448: if (u.u_error == 0)
449: return (sp);
450: return (NULL);
451: }
452:
453: struct adata { /* Storage for arg and env data */
454: int np; /* Number of pointers in vector */
455: int nc; /* Number of characters in strings */
456: };
457:
458: /*
459: * Given a pointer to a list of arguments and a pointer to a list of
460: * environments, return a stack with the arguments and environments on it.
461: */
462: SEG *
463: exstack(xhp, argp, envp, wdin)
464: register struct xechdr *xhp;
465: vaddr_t argp, envp;
466: {
467: register SEG *sp; /* Stack segment pointer */
468: struct sdata { /* To keep segment pointers */
469: vaddr_t vp; /* Argv[i], envp[i] pointer */
470: vaddr_t cp; /* Argv[i][j], envp[i][j] pointer */
471: } stk;
472: struct adata arg, env;
473: int chrsz, vecsz, stksz, wdmask, wdout, stkoff, stktop;
474: int stkenvp;
475: register int i;
476:
477: /* Validate and evaluate size of args and envs */
478: if (!excount(argp, &arg, wdin) || !excount(envp, &env, wdin))
479: return NULL;
480:
481: /* Calculate stack size and allocate it */
482: chrsz = roundu(arg.nc + env.nc, sizeof(int));
483: vecsz = (arg.np+1 + env.np+1) * sizeof(long);
484: stksz = roundu(vecsz+chrsz+ISTSIZE, NBPC);
485: if (stksz > MADSIZE || !(sp = salloc(stksz, SFDOWN))) {
486: u.u_error = E2BIG;
487: return NULL;
488: }
489:
490: /* Set up target stack */
491: stktop = xhp->segs[SISTACK].mbase;
492: stk.cp = stktop - chrsz;
493: stk.vp = stktop - chrsz - vecsz;
494: stkoff = MAPIO(sp->s_vmem, stksz - stktop);
495: u.u_argc = arg.np;
496: u.u_argp = stk.vp;
497: wdmask = -1;
498: if (wdin==sizeof(short))
499: wdmask = (unsigned short)wdmask;
500:
501: switch (stktop) {
502:
503: case ISP_386:
504: wdout = sizeof(long);
505: xhp->initsp = stk.vp - sizeof(long);
506: dmaout(sizeof(long), xhp->initsp+stkoff, &arg.np);
507: break;
508:
509: case ISP_286:
510: wdout = sizeof(short);
511: xhp->initsp = stk.vp - 3*sizeof(short);
512: stkenvp = stk.vp + (arg.np+1) * sizeof(short);
513: dmaout(sizeof(short), xhp->initsp+stkoff, &arg.np);
514: dmaout(sizeof(short), xhp->initsp+sizeof(short)+stkoff,
515: &stk.vp);
516: dmaout(sizeof(short), xhp->initsp+2*sizeof(short)+stkoff,
517: &stkenvp);
518: break;
519:
520: default:
521: panic("exstack");
522:
523: }
524:
525: /* Arguments */
526: for (i = 0; i<arg.np; i++, argp += wdin, stk.vp += wdout) {
527: dmaout(wdout, stk.vp+stkoff, &stk.cp);
528: stk.cp += exarg(stk.cp+stkoff, getupd(argp) & wdmask);
529: }
530:
531: /* skip null word after arguments */
532: stk.vp += wdout;
533:
534: /* Environments */
535: for (i = 0; i<env.np; i++, envp += wdin, stk.vp += wdout) {
536: dmaout(wdout, stk.vp+stkoff, &stk.cp);
537: stk.cp += exarg(stk.cp+stkoff, getupd(envp) & wdmask);
538: }
539:
540: return sp;
541: }
542:
543: exarg(out, in)
544: vaddr_t in, out;
545: {
546: char c;
547: vaddr_t init_in;
548:
549: init_in = in;
550: do {
551: c = getubd(in++);
552: dmaout(sizeof(char), out++, &c);
553: } while (c);
554: return in - init_in;
555: }
556:
557:
558: /*
559: * Given a pointer to a list of arguments, a pointer to an argument count
560: * and a pointer to a byte count, count the #characters/#strigns
561: * in the arguments
562: */
563: excount(usrvp, adp, wdin)
564: register vaddr_t usrvp;
565: struct adata *adp;
566: {
567: register vaddr_t usrcp;
568: register int c;
569: register unsigned nb;
570: register unsigned na;
571: int wdmask;
572:
573: wdmask = -1;
574: if (wdin==sizeof(short))
575: wdmask = (unsigned short)wdmask;
576: na = nb = 0;
577: if (usrvp != NULL) {
578: for (;;) {
579: usrcp = getupd(usrvp) & wdmask;
580: usrvp += wdin;
581: if (u.u_error)
582: return (0);
583: if (usrcp == NULL)
584: break;
585: na++;
586: for (;;) {
587: c = getubd(usrcp++);
588: if (u.u_error)
589: return (0);
590: nb++;
591: if (c == '\0')
592: break;
593: }
594: }
595: }
596: adp->np = na;
597: adp->nc = nb;
598: return (1);
599: }
600:
601: /*
602: * Round up a size to a paragraph
603: * (mod 16) boundry.
604: * This is really mod 512 to make swapping work
605: */
606: off_t
607: exround(s)
608: off_t s;
609: {
610: return ((s+15)&~0x0F);
611: }
612:
613: pload( np )
614: char * np;
615: {
616: return -1;
617:
618: }
619: /*
620: * Set up the first process, a small programme which will exec
621: * the init programme.
622: */
623: eveinit()
624: {
625: SEG *sp;
626: register PROC *pp;
627: SELF = pp = eprocp;
628: /* static struct xechdr xecinit[NUSEG+1] = { {0},{0},{0},{ISP_386}}; */
629:
630: /*
631: * Allocate, record, initialize code segment, make it executable.
632: */
633: if ((sp = salloc(roundu(icodes, NBPC), 0)) == NULL)
634: panic("eveinit(code)");
635: pp->p_segp[SIPDATA] = sp;
636:
637: /*
638: * Start process.
639: */
640: u.u_argp = 0;
641: if (sproto(0) == 0)
642: panic("eveinit()");
643: segload();
644: kucopy(icodep, 0, icodes);
645: }
646:
647: /*
648: * Given a major number, undo the previous function.
649: */
650: puload(m)
651: int m;
652: {
653: register CON *cp;
654: register DRV *dp;
655:
656: dp = &drvl[m];
657: lock(dp->d_gate);
658: if (m>=drvn || (cp=dp->d_conp)==NULL) {
659: u.u_error = ENXIO;
660: goto ret;
661: }
662: (*cp->c_uload)();
663: if ( ! u.u_error)
664: dp->d_conp = NULL;
665: ret:
666: unlock(dp->d_gate);
667: return (0);
668: }
669:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.