|
|
1.1 root 1: #ifndef lint
2: static char *rcsid =
3: "$Header: ffasl.c,v 1.11 87/12/14 18:48:06 sklower Exp $";
4: #endif
5:
6: /* -[Mon Mar 21 19:37:21 1983 by jkf]-
7: * ffasl.c $Locker: $
8: * dynamically load C code
9: *
10: * (c) copyright 1982, Regents of the University of California
11: */
12:
13:
14: #include "global.h"
15: #include <sys/types.h>
16: #include <sys/stat.h>
17: #include <aout.h>
18: #define round(x,s) ((((x)-1) & ~((s)-1)) + (s))
19:
20: char *stabf = 0, *strcpy(), *Ilibdir();
21: extern int fvirgin;
22: static seed=0, mypid = 0;
23: static char myname[100];
24: lispval verify();
25:
26: /* dispget - get discipline of function
27: * this is used to handle the tricky defaulting of the discipline
28: * field of such functions as cfasl and getaddress.
29: * dispget is given the value supplied by the caller,
30: * the error message to print if something goes wrong,
31: * the default to use if nil was supplied.
32: * the discipline can be an atom or string. If an atom it is supplied
33: * it must be lambda, nlambda or macro. Otherwise the atoms pname
34: * is used.
35: */
36:
37: lispval
38: dispget(given,messg,defult)
39: lispval given,defult;
40: char *messg;
41: {
42: int typ;
43:
44: while(TRUE)
45: {
46: if(given == nil)
47: return(defult);
48: if((typ=TYPE(given)) == ATOM)
49: { if(given == lambda ||
50: given == nlambda ||
51: given == macro) return(given);
52: else return((lispval) given->a.pname);
53: } else if(typ == STRNG) return(given);
54:
55: given = errorh1(Vermisc,messg,nil,TRUE,0,given);
56: }
57: }
58:
59: lispval
60: Lcfasl(){
61: register struct argent *mlbot = lbot;
62: register lispval work;
63: register int fildes, totsize;
64: int readsize;
65: lispval csegment();
66: char *sbrk(), *currend, *tfile, cbuf[6000], *mytemp(), *gstab();
67: char ostabf[128];
68: struct exec header;
69: char *largs;
70: Savestack(4);
71:
72: switch(np-lbot) {
73: case 3: protect(nil); /* no discipline given */
74: case 4: protect(nil); /* no library given */
75: }
76: chkarg(5,"cfasl");
77: mlbot[0].val = verify(mlbot[0].val,"Incorrect .o file specification");
78: mlbot[1].val = verify(mlbot[1].val,"Incorrect entry specification for cfasl");
79: mlbot[3].val = dispget(mlbot[3].val,"Incorrect discipline specification for cfasl",(lispval)Vsubrou->a.pname);
80: while(TYPE(mlbot[2].val)!= ATOM)
81: mlbot[2].val = errorh1(Vermisc,"Bad associated atom name for fasl",
82: nil,TRUE,0,mlbot[2].val);
83: work = mlbot[4].val;
84: if(work==nil)
85: largs = 0;
86: else
87: largs = (char *) verify(work,"Bad loader flags");
88:
89: /*
90: * Invoke loader.
91: */
92: strcpy(ostabf,gstab());
93: currend = sbrk(0);
94: #if (!os_vms) | EUNICE_UNIX_OBJECT_FILE_CFASL
95: /*** UNIX cfasl code ***/
96: tfile = mytemp();
97: sprintf(cbuf,
98: "%s/nld -N -x -A %s -T %x %s -e %s -o %s %s -lc",
99: Ilibdir(),
100: ostabf,
101: currend,
102: mlbot[0].val,
103: mlbot[1].val,
104: tfile,
105: largs);
106: /* if nil don't print cfasl/nld message */
107: if ( Vldprt->a.clb != nil ) {
108: printf(cbuf);
109: putchar('\n'); fflush(stdout);
110: }
111: if(system(cbuf)!=0) {
112: unlink(tfile);
113: ungstab();
114: fprintf(stderr,"Ld returns error status\n");
115: Restorestack();
116: return(nil);
117: }
118: if(fvirgin)
119: fvirgin = 0;
120: else
121: unlink(ostabf);
122: stabf = tfile;
123: if((fildes = open(tfile,0))<0) {
124: fprintf(stderr,"Couldn't open temporary file: %s\n",tfile);
125: Restorestack();
126: return(nil);
127: }
128: /*
129: * Read a.out header to find out how much room to
130: * allocate and attempt to do so.
131: */
132: if(read(fildes,(char *)&header,sizeof(header)) <= 0) {
133: close(fildes);
134: Restorestack();
135: return(nil);
136: }
137: readsize = round(header.a_text,4) + round(header.a_data,4);
138: totsize = readsize + header.a_bss;
139: totsize = round(totsize,512);
140: /*
141: * Fix up system indicators, typing info, etc.
142: */
143: currend = (char *)csegment(OTHER,totsize,FALSE);
144:
145: if(readsize!=read(fildes,currend,readsize))
146: {close(fildes);Restorestack(); return(nil);}
147: work = newfunct();
148: work->bcd.start = (lispval (*)())header.a_entry;
149: work->bcd.discipline = mlbot[3].val;
150: close(fildes);
151: Restorestack();
152: return(mlbot[2].val->a.fnbnd = work);
153: #else
154: /*** VMS cfasl code ***/
155: {
156: int pid = getpid() & 0xffff; /* Our process ID number */
157: char objfil[100]; /* Absolute object file name */
158: char symfil[100]; /* Old symbol table file */
159: char filename[100]; /* Random filename buffer */
160: int strlen(); /* String length function */
161: int cvt_unix_to_vms(); /* Convert UNIX to VMS filename */
162: lispval Lgetaddress(),matom();
163: struct stat stbuf;
164:
165: if (largs == 0) largs = " ";
166: sprintf(objfil,"tmp:cfasl%d.tmp",pid);
167: symfil[cvt_unix_to_vms(ostabf,symfil)] = 0;
168: sprintf(cbuf, /* Create link cmd. */
169: "$ link/exe=%s/nom/syst=%%X%x/sym=tmp:sym%d.new %s,%s%s",
170: objfil,
171: currend,
172: pid,
173: mlbot[0].val,
174: symfil,
175: largs);
176: printf( /* Echo link cmd. */
177: "$ link/exe=%s/nomap/system=%%X%x/symbol_table=tmp:sym%d.new %s,%s%s\n",
178: objfil,
179: currend,
180: pid,
181: mlbot[0].val,
182: symfil,
183: largs);
184: fflush(stdout);
185: vms_system(cbuf,0);
186:
187: if ((fildes = open(objfil,0)) < 0) /* Open abs file */
188: {Restorestack(); return(nil);}
189: fstat(fildes,&stbuf); /* Get its size */
190: readsize=stbuf.st_size;
191: currend = (char *)csegment(OTHER,readsize,FALSE);
192: readsize = read(fildes,currend,10000000);
193: close(fildes);
194: /*
195: * Delete the absolute object file
196: */
197: unlink(objfil);
198: /*
199: * Delete the old symbol table (if temporary)
200: */
201: sprintf(filename,"tmp:sym%d.stb",pid);
202: unlink(filename);
203: /*
204: * Rename the new symbol table so it is now the old symbol table
205: */
206: sprintf(symfil,"tmp:sym%d.new",pid);
207: link(symfil,filename);
208: unlink(symfil);
209: sprintf(myname,"tmp:sym%d.stb",pid);
210: stabf = myname;
211: /*
212: * Return Lgetaddress(entry,function_name,discipline)
213: */
214: {
215: struct argent *oldlbot, *oldnp;
216: lispval result;
217:
218: oldlbot = lbot;
219: oldnp = np;
220: lbot = np;
221: np++->val = matom(mlbot[1].val);
222: np++->val = mlbot[2].val;
223: np++->val = matom(mlbot[3].val);
224: result = Lgetaddress();
225: lbot = oldlbot;
226: np = oldnp;
227: return(result);
228: }
229: }
230: #endif
231: }
232: #ifdef os_vms
233: #define M 4
234: #else
235: #define M 1
236: #endif
237: #define oktox(n) \
238: (0==stat(n,&stbuf)&&(stbuf.st_mode&S_IFMT)==S_IFREG&&0==access(n,M))
239: char *
240: gstab()
241: {
242: register char *cp, *cp2; char *getenv();
243: struct stat stbuf;
244: extern char **Xargv;
245:
246: if(stabf==0) {
247: cp = getenv("PATH");
248: if(cp==0)
249: cp=":/usr/ucb:/bin:/usr/bin";
250: if(*cp==':'||*Xargv[0]=='/') {
251: cp++;
252: if(oktox(Xargv[0])) {
253: strcpy(myname,Xargv[0]);
254: return(stabf = myname);
255: }
256: #ifdef os_vms
257: /*
258: * Try Xargv[0] with ".stb" concatenated
259: */
260: strcpy(myname,Xargv[0]);
261: strcat(myname,".stb");
262: if (oktox(myname)) return(stabf = myname);
263: /*
264: * Try Xargv[0] with ".exe" concatenated
265: */
266: strcpy(myname,Xargv[0]);
267: strcat(myname,".exe");
268: if (oktox(myname)) return(stabf = myname);
269: #endif
270: }
271: for(;*cp;) {
272:
273: /* copy over current directory
274: and then append argv[0] */
275:
276: for(cp2=myname;(*cp)!=0 && (*cp)!=':';)
277: *cp2++ = *cp++;
278: *cp2++ = '/';
279: strcpy(cp2,Xargv[0]);
280: if(*cp) cp++;
281: #ifndef os_vms
282: if(!oktox(myname)) continue;
283: #else
284: /*
285: * Also try ".stb" and ".exe" in VMS
286: */
287: if(!oktox(myname)) {
288: char *end_of_name;
289: end_of_name = cp2 + strlen(cp2);
290: strcat(cp2,".stb");
291: if(!oktox(myname)) {
292: /*
293: * Try ".exe"
294: */
295: *end_of_name = 0; /* Kill ".stb" */
296: strcat(cp2,".exe");
297: if (!oktox(myname)) continue;
298: }
299: }
300: #endif
301: return(stabf = myname);
302: }
303: /* one last try for dual systems */
304: strcpy(myname,Xargv[0]);
305: if(oktox(myname)) return(stabf = myname);
306: error("Could not find which file is being executed.",FALSE);
307: /* NOTREACHED */
308: } else return (stabf);
309: }
310: static char mybuff[40];
311: char *
312: mytemp()
313: {
314: /*if(mypid==0) mypid = (getpid() & 0xffff);
315: fails if you do a dumplisp after doing a
316: cfasl */
317: sprintf(mybuff,"/tmp/Li%d.%d",(getpid() & 0xffff),seed++);
318: return(mybuff);
319: }
320: ungstab()
321: {
322: seed--;
323: sprintf(mybuff,"/tmp/Li%d.%d",(getpid() & 0xffff),seed-1);
324: if(seed==0) {
325: stabf = 0;
326: fvirgin = 1;
327: }
328: }
329: lispval
330: verify(in,error)
331: register lispval in;
332: char *error;
333: {
334: for(EVER) {
335: switch(TYPE(in)) {
336: case STRNG:
337: return(in);
338: case ATOM:
339: return((lispval)in->a.pname);
340: }
341: in = errorh1(Vermisc,error,nil,TRUE,0,in);
342: }
343: }
344:
345:
346: /* extern int fvirgin; */
347: /* declared in ffasl.c tells if this is original
348: * lisp symbol table.
349: * if fvirgin is 1 then we must copy the symbol
350: * table, else we can overwrite it, since
351: * it is a temporary file which only
352: * one user could be using(was not created
353: * as an original lisp or by a (dumplisp)
354: * or a (savelisp)).
355: */
356:
357: /* copy a block of data from one file to another of size size */
358: copyblock(f1,f2,size)
359: FILE *f1, *f2;
360: long size;
361: {
362: char block[BUFSIZ];
363:
364: while ( size > BUFSIZ ) {
365: size -= BUFSIZ;
366: fread(block,BUFSIZ,1,f1);
367: fwrite(block,BUFSIZ,1,f2);
368: }
369: if (size > 0 ) {
370: fread(block,(int)size,1,f1);
371: fwrite(block,(int)size,1,f2);
372: }
373: }
374:
375: /* removeaddress --
376: *
377: * (removeaddress '|_entry1| '|_entry2| ...)
378: *
379: * removes the given entry points from the run time symbol table,
380: * so that later cfasl'd files can have these label names.
381: *
382: */
383:
384: lispval
385: Lrmadd(){
386: register struct argent *mlbot = lbot;
387: register struct nlist *q;
388: register int i;
389: int numberofargs, strsize;
390: char *gstab();
391: char ostabf[128];
392: char *nstabf,*mytemp();
393: char *strtbl,*alloca();
394: int i2, n, m, nargleft, savem;
395: FILE *f, *fa;
396: FILE *fnew;
397: off_t savesymadd,symadd; /* symbol address */
398: struct exec buf;
399: struct nlist nlbuf[BUFSIZ/sizeof (struct nlist)];
400: int maxlen;
401: int change;
402: Keepxs();
403:
404: numberofargs = (np - lbot);
405: nargleft = numberofargs;
406: maxlen = 0;
407: for ( i=0; i<numberofargs; i++,mlbot ++) {
408: mlbot->val = verify(mlbot->val,"Incorrect entry specification.");
409: n = strlen((char *)mlbot->val);
410: if (n > maxlen)
411: maxlen = n;
412: }
413: /*
414: * Must not disturb object file if it an original file which
415: * other users can execute(signified by the variable fvirgin).
416: * so the entire symbol table is copied to a new file.
417: */
418: if (fvirgin) {
419: strncpy(ostabf,gstab(),128);
420: nstabf = mytemp();
421: /*
422: * copy over symbol table into a temporary file first
423: *
424: */
425: f = fopen(ostabf, "r");
426: fnew = fopen(nstabf, "w");
427: if (( f == NULL ) || (fnew == NULL)) {Freexs(); return( nil );}
428: /* read exec header on file */
429: #ifndef os_vms
430: fread((char *)&buf, sizeof buf, 1, f);
431: #else os_vms
432: /*
433: * Under VMS/EUNICE we have to try the 1st 512 byte
434: * block and the 2nd 512 byte block (there may be
435: * a VMS header in the 1st 512 bytes).
436: */
437: get_aout_header(fileno(f),&buf);
438: #endif os_vms
439:
440: /* Is this a legitimate a.out file? */
441: if (N_BADMAG(buf)) {
442: unlink(nstabf);
443: ungstab();
444: fclose(f);
445: fclose(fnew);
446: errorh1(Vermisc,"Removeaddress: Bad file",nil,FALSE,0,inewstr(ostabf));
447: {Freexs(); return(nil);}
448: }
449: /* set pointer on read file to symbol table */
450: /* must be done before the structure buf is reassigned
451: * so that it will be accurate for the read file
452: */
453: fseek(f,(long)N_SYMOFF(buf),0);
454: /* reset up exec header structure for new file */
455: buf.a_magic = OMAGIC;
456: buf.a_text = 0;
457: buf.a_data = 0;
458: buf.a_bss = 0;
459: buf.a_entry = 0;
460: buf.a_trsize = 0;
461: buf.a_drsize = 0;
462: fwrite((char *)&buf,
463: sizeof buf,1,fnew); /* write out exec header */
464: copyblock(f,fnew,(long)buf.a_syms); /* copy symbol table */
465: #if ! (os_unisoft | os_unix_ts)
466: fread((char *)&strsize,
467: sizeof (int),1,f); /* find size of string table */
468: fwrite((char *)&strsize,
469: sizeof (int),1,fnew); /* find size of string table */
470: strsize -= 4;
471: strtbl = alloca(strsize);
472: fread(strtbl,strsize,1,f); /* read and save string table*/
473: fwrite(strtbl,strsize,1,fnew); /* copy out string table */
474: #endif
475: fclose(f);fclose(fnew);
476: } else {
477: nstabf = gstab();
478: }
479:
480: /*
481: * now unset the external bits it the entry points specified.
482: */
483: f = fopen(nstabf, "r");
484: fa = fopen(nstabf, "a");
485: if (( f == NULL ) || (fa == NULL)) {
486: unlink(nstabf);
487: ungstab();
488: if (f != NULL ) fclose(f);
489: if (fa != NULL ) fclose(fa);
490: return ( nil );
491: }
492:
493: /* read exec header on file */
494: #ifndef os_vms
495: fread((char *)&buf, sizeof buf, 1, f);
496: #else os_vms
497: /*
498: * Under VMS/EUNICE we have to try the 1st 512 byte
499: * block and the 2nd 512 byte block (there may be
500: * a VMS header in the 1st 512 bytes).
501: */
502: get_aout_header(fileno(f),&buf);
503: #endif os_vms
504:
505: /* Is this a legitimate a.out file? */
506: if (N_BADMAG(buf)) {
507: if (fvirgin) {
508: unlink(nstabf);
509: ungstab();
510: }
511: fclose(f);
512: fclose(fa);
513: errorh1(Vermisc,"Removeaddress: Bad file",nil,FALSE,0,inewstr(ostabf));
514: {Freexs(); return(nil);}
515: } else {
516: symadd = N_SYMOFF(buf);
517: #if ! (os_unisoft | os_unix_ts)
518: /*
519: * read in string table if not done during copying
520: */
521: if (fvirgin==0){
522: fseek(f,(long)N_STROFF(buf),0);
523: fread((char *)&strsize,sizeof (int),1,f);
524: strsize -= 4;
525: strtbl = alloca(strsize);
526: fread(strtbl,strsize,1,f);
527: }
528: #endif
529: n = buf.a_syms;
530: fseek(f, (long)symadd, 0);
531: while (n) {
532: m = sizeof (nlbuf);
533: if (n < m)
534: m = n;
535:
536: /* read next block of symbols from a.out file */
537: fread((char *)nlbuf, m, 1, f);
538: savem = m;
539: savesymadd = symadd;
540: symadd += m;
541: n -= m;
542: change = 0;
543:
544: /* compare block of symbols against list of entry point
545: * names given, if a match occurs, clear the N_EXT bit
546: * for that given symbol and signal a change.
547: */
548: for (q = nlbuf; (m -= sizeof(struct nlist)) >= 0; q++) {
549:
550: /* make sure it is external */
551: if (
552: (q->n_type & N_EXT)==0
553: #if ! (os_unix_ts | os_unisoft)
554: || q->n_un.n_strx == 0 || q->n_type & N_STAB
555: #endif
556: ) continue;
557: for (mlbot=lbot,i2 = 0;i2<numberofargs;i2++,mlbot++) {
558: #if ! (os_unix_ts | os_unisoft)
559: if(strcmp((char *)mlbot->val,
560: strtbl+q->n_un.n_strx-4)!=0)
561: continue;
562: #else
563: if(strncmp((char *)mlbot->val,
564: q->n_name,8)!=0)
565: continue;
566: #endif
567: change = 1;
568: q->n_type &= ~N_EXT;
569: break;
570: }
571: }
572: if ( change ) {
573: fseek(fa,(long)savesymadd,0);
574: fwrite((char *)nlbuf, savem, 1, fa);
575: if (--nargleft == 0)
576: goto alldone;
577: }
578: }
579: }
580: alldone:
581: fclose(f);
582: fclose(fa);
583: if(fvirgin)
584: fvirgin = 0;
585: stabf = nstabf;
586: {Freexs(); return(tatom);}
587: }
588: char *
589: Ilibdir()
590: {
591: register lispval handy;
592: tryagain:
593: handy = Vlibdir->a.clb;
594: switch(TYPE(handy)) {
595: case ATOM:
596: handy = (lispval) handy->a.pname;
597: case STRNG:
598: break;
599: default:
600: (void) error(
601: "cfasl or load: lisp-library-directory not bound to string or atom",
602: TRUE);
603: goto tryagain;
604: }
605: return((char *) handy);
606: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.