|
|
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.