|
|
1.1 ! root 1: #ifndef lint ! 2: static char *rcsid = ! 3: "$Header: ffasl.c,v 1.10 83/12/09 16:45:04 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(), *sprintf(), *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: unlink(sprintf(filename,"tmp:sym%d.stb",pid)); ! 202: /* ! 203: * Rename the new symbol table so it is now the old symbol table ! 204: */ ! 205: link(sprintf(symfil,"tmp:sym%d.new",pid),filename); ! 206: unlink(symfil); ! 207: sprintf(myname,"tmp:sym%d.stb",pid); ! 208: stabf = myname; ! 209: /* ! 210: * Return Lgetaddress(entry,function_name,discipline) ! 211: */ ! 212: { ! 213: struct argent *oldlbot, *oldnp; ! 214: lispval result; ! 215: ! 216: oldlbot = lbot; ! 217: oldnp = np; ! 218: lbot = np; ! 219: np++->val = matom(mlbot[1].val); ! 220: np++->val = mlbot[2].val; ! 221: np++->val = matom(mlbot[3].val); ! 222: result = Lgetaddress(); ! 223: lbot = oldlbot; ! 224: np = oldnp; ! 225: return(result); ! 226: } ! 227: } ! 228: #endif ! 229: } ! 230: #ifdef os_vms ! 231: #define M 4 ! 232: #else ! 233: #define M 1 ! 234: #endif ! 235: #define oktox(n) \ ! 236: (0==stat(n,&stbuf)&&(stbuf.st_mode&S_IFMT)==S_IFREG&&0==access(n,M)) ! 237: char * ! 238: gstab() ! 239: { ! 240: register char *cp, *cp2; char *getenv(); ! 241: struct stat stbuf; ! 242: extern char **Xargv; ! 243: ! 244: if(stabf==0) { ! 245: cp = getenv("PATH"); ! 246: if(cp==0) ! 247: cp=":/usr/ucb:/bin:/usr/bin"; ! 248: if(*cp==':'||*Xargv[0]=='/') { ! 249: cp++; ! 250: if(oktox(Xargv[0])) { ! 251: strcpy(myname,Xargv[0]); ! 252: return(stabf = myname); ! 253: } ! 254: #ifdef os_vms ! 255: /* ! 256: * Try Xargv[0] with ".stb" concatenated ! 257: */ ! 258: strcpy(myname,Xargv[0]); ! 259: strcat(myname,".stb"); ! 260: if (oktox(myname)) return(stabf = myname); ! 261: /* ! 262: * Try Xargv[0] with ".exe" concatenated ! 263: */ ! 264: strcpy(myname,Xargv[0]); ! 265: strcat(myname,".exe"); ! 266: if (oktox(myname)) return(stabf = myname); ! 267: #endif ! 268: } ! 269: for(;*cp;) { ! 270: ! 271: /* copy over current directory ! 272: and then append argv[0] */ ! 273: ! 274: for(cp2=myname;(*cp)!=0 && (*cp)!=':';) ! 275: *cp2++ = *cp++; ! 276: *cp2++ = '/'; ! 277: strcpy(cp2,Xargv[0]); ! 278: if(*cp) cp++; ! 279: #ifndef os_vms ! 280: if(!oktox(myname)) continue; ! 281: #else ! 282: /* ! 283: * Also try ".stb" and ".exe" in VMS ! 284: */ ! 285: if(!oktox(myname)) { ! 286: char *end_of_name; ! 287: end_of_name = cp2 + strlen(cp2); ! 288: strcat(cp2,".stb"); ! 289: if(!oktox(myname)) { ! 290: /* ! 291: * Try ".exe" ! 292: */ ! 293: *end_of_name = 0; /* Kill ".stb" */ ! 294: strcat(cp2,".exe"); ! 295: if (!oktox(myname)) continue; ! 296: } ! 297: } ! 298: #endif ! 299: return(stabf = myname); ! 300: } ! 301: /* one last try for dual systems */ ! 302: strcpy(myname,Xargv[0]); ! 303: if(oktox(myname)) return(stabf = myname); ! 304: error("Could not find which file is being executed.",FALSE); ! 305: /* NOTREACHED */ ! 306: } else return (stabf); ! 307: } ! 308: static char mybuff[40]; ! 309: char * ! 310: mytemp() ! 311: { ! 312: /*if(mypid==0) mypid = (getpid() & 0xffff); ! 313: fails if you do a dumplisp after doing a ! 314: cfasl */ ! 315: sprintf(mybuff,"/tmp/Li%d.%d",(getpid() & 0xffff),seed++); ! 316: return(mybuff); ! 317: } ! 318: ungstab() ! 319: { ! 320: seed--; ! 321: sprintf(mybuff,"/tmp/Li%d.%d",(getpid() & 0xffff),seed-1); ! 322: if(seed==0) { ! 323: stabf = 0; ! 324: fvirgin = 1; ! 325: } ! 326: } ! 327: lispval ! 328: verify(in,error) ! 329: register lispval in; ! 330: char *error; ! 331: { ! 332: for(EVER) { ! 333: switch(TYPE(in)) { ! 334: case STRNG: ! 335: return(in); ! 336: case ATOM: ! 337: return((lispval)in->a.pname); ! 338: } ! 339: in = errorh1(Vermisc,error,nil,TRUE,0,in); ! 340: } ! 341: } ! 342: ! 343: ! 344: /* extern int fvirgin; */ ! 345: /* declared in ffasl.c tells if this is original ! 346: * lisp symbol table. ! 347: * if fvirgin is 1 then we must copy the symbol ! 348: * table, else we can overwrite it, since ! 349: * it is a temporary file which only ! 350: * one user could be using(was not created ! 351: * as an original lisp or by a (dumplisp) ! 352: * or a (savelisp)). ! 353: */ ! 354: ! 355: /* copy a block of data from one file to another of size size */ ! 356: copyblock(f1,f2,size) ! 357: FILE *f1, *f2; ! 358: long size; ! 359: { ! 360: char block[BUFSIZ]; ! 361: ! 362: while ( size > BUFSIZ ) { ! 363: size -= BUFSIZ; ! 364: fread(block,BUFSIZ,1,f1); ! 365: fwrite(block,BUFSIZ,1,f2); ! 366: } ! 367: if (size > 0 ) { ! 368: fread(block,(int)size,1,f1); ! 369: fwrite(block,(int)size,1,f2); ! 370: } ! 371: } ! 372: ! 373: /* removeaddress -- ! 374: * ! 375: * (removeaddress '|_entry1| '|_entry2| ...) ! 376: * ! 377: * removes the given entry points from the run time symbol table, ! 378: * so that later cfasl'd files can have these label names. ! 379: * ! 380: */ ! 381: ! 382: lispval ! 383: Lrmadd(){ ! 384: register struct argent *mlbot = lbot; ! 385: register struct nlist *q; ! 386: register int i; ! 387: int numberofargs, strsize; ! 388: char *gstab(); ! 389: char ostabf[128]; ! 390: char *nstabf,*mytemp(); ! 391: char *strtbl,*alloca(); ! 392: int i2, n, m, nargleft, savem; ! 393: FILE *f, *fa; ! 394: FILE *fnew; ! 395: off_t savesymadd,symadd; /* symbol address */ ! 396: struct exec buf; ! 397: struct nlist nlbuf[BUFSIZ/sizeof (struct nlist)]; ! 398: int maxlen; ! 399: int change; ! 400: Keepxs(); ! 401: ! 402: numberofargs = (np - lbot); ! 403: nargleft = numberofargs; ! 404: maxlen = 0; ! 405: for ( i=0; i<numberofargs; i++,mlbot ++) { ! 406: mlbot->val = verify(mlbot->val,"Incorrect entry specification."); ! 407: n = strlen((char *)mlbot->val); ! 408: if (n > maxlen) ! 409: maxlen = n; ! 410: } ! 411: /* ! 412: * Must not disturb object file if it an original file which ! 413: * other users can execute(signified by the variable fvirgin). ! 414: * so the entire symbol table is copied to a new file. ! 415: */ ! 416: if (fvirgin) { ! 417: strncpy(ostabf,gstab(),128); ! 418: nstabf = mytemp(); ! 419: /* ! 420: * copy over symbol table into a temporary file first ! 421: * ! 422: */ ! 423: f = fopen(ostabf, "r"); ! 424: fnew = fopen(nstabf, "w"); ! 425: if (( f == NULL ) || (fnew == NULL)) {Freexs(); return( nil );} ! 426: /* read exec header on file */ ! 427: #ifndef os_vms ! 428: fread((char *)&buf, sizeof buf, 1, f); ! 429: #else os_vms ! 430: /* ! 431: * Under VMS/EUNICE we have to try the 1st 512 byte ! 432: * block and the 2nd 512 byte block (there may be ! 433: * a VMS header in the 1st 512 bytes). ! 434: */ ! 435: get_aout_header(fileno(f),&buf); ! 436: #endif os_vms ! 437: ! 438: /* Is this a legitimate a.out file? */ ! 439: if (N_BADMAG(buf)) { ! 440: unlink(nstabf); ! 441: ungstab(); ! 442: fclose(f); ! 443: fclose(fnew); ! 444: errorh1(Vermisc,"Removeaddress: Bad file",nil,FALSE,0,inewstr(ostabf)); ! 445: {Freexs(); return(nil);} ! 446: } ! 447: /* set pointer on read file to symbol table */ ! 448: /* must be done before the structure buf is reassigned ! 449: * so that it will be accurate for the read file ! 450: */ ! 451: fseek(f,(long)N_SYMOFF(buf),0); ! 452: /* reset up exec header structure for new file */ ! 453: buf.a_magic = OMAGIC; ! 454: buf.a_text = 0; ! 455: buf.a_data = 0; ! 456: buf.a_bss = 0; ! 457: buf.a_entry = 0; ! 458: buf.a_trsize = 0; ! 459: buf.a_drsize = 0; ! 460: fwrite((char *)&buf, ! 461: sizeof buf,1,fnew); /* write out exec header */ ! 462: copyblock(f,fnew,(long)buf.a_syms); /* copy symbol table */ ! 463: #if ! (os_unisoft | os_unix_ts) ! 464: fread((char *)&strsize, ! 465: sizeof (int),1,f); /* find size of string table */ ! 466: fwrite((char *)&strsize, ! 467: sizeof (int),1,fnew); /* find size of string table */ ! 468: strsize -= 4; ! 469: strtbl = alloca(strsize); ! 470: fread(strtbl,strsize,1,f); /* read and save string table*/ ! 471: fwrite(strtbl,strsize,1,fnew); /* copy out string table */ ! 472: #endif ! 473: fclose(f);fclose(fnew); ! 474: } else { ! 475: nstabf = gstab(); ! 476: } ! 477: ! 478: /* ! 479: * now unset the external bits it the entry points specified. ! 480: */ ! 481: f = fopen(nstabf, "r"); ! 482: fa = fopen(nstabf, "a"); ! 483: if (( f == NULL ) || (fa == NULL)) { ! 484: unlink(nstabf); ! 485: ungstab(); ! 486: if (f != NULL ) fclose(f); ! 487: if (fa != NULL ) fclose(fa); ! 488: return ( nil ); ! 489: } ! 490: ! 491: /* read exec header on file */ ! 492: #ifndef os_vms ! 493: fread((char *)&buf, sizeof buf, 1, f); ! 494: #else os_vms ! 495: /* ! 496: * Under VMS/EUNICE we have to try the 1st 512 byte ! 497: * block and the 2nd 512 byte block (there may be ! 498: * a VMS header in the 1st 512 bytes). ! 499: */ ! 500: get_aout_header(fileno(f),&buf); ! 501: #endif os_vms ! 502: ! 503: /* Is this a legitimate a.out file? */ ! 504: if (N_BADMAG(buf)) { ! 505: if (fvirgin) { ! 506: unlink(nstabf); ! 507: ungstab(); ! 508: } ! 509: fclose(f); ! 510: fclose(fa); ! 511: errorh1(Vermisc,"Removeaddress: Bad file",nil,FALSE,0,inewstr(ostabf)); ! 512: {Freexs(); return(nil);} ! 513: } else { ! 514: symadd = N_SYMOFF(buf); ! 515: #if ! (os_unisoft | os_unix_ts) ! 516: /* ! 517: * read in string table if not done during copying ! 518: */ ! 519: if (fvirgin==0){ ! 520: fseek(f,(long)N_STROFF(buf),0); ! 521: fread((char *)&strsize,sizeof (int),1,f); ! 522: strsize -= 4; ! 523: strtbl = alloca(strsize); ! 524: fread(strtbl,strsize,1,f); ! 525: } ! 526: #endif ! 527: n = buf.a_syms; ! 528: fseek(f, (long)symadd, 0); ! 529: while (n) { ! 530: m = sizeof (nlbuf); ! 531: if (n < m) ! 532: m = n; ! 533: ! 534: /* read next block of symbols from a.out file */ ! 535: fread((char *)nlbuf, m, 1, f); ! 536: savem = m; ! 537: savesymadd = symadd; ! 538: symadd += m; ! 539: n -= m; ! 540: change = 0; ! 541: ! 542: /* compare block of symbols against list of entry point ! 543: * names given, if a match occurs, clear the N_EXT bit ! 544: * for that given symbol and signal a change. ! 545: */ ! 546: for (q = nlbuf; (m -= sizeof(struct nlist)) >= 0; q++) { ! 547: ! 548: /* make sure it is external */ ! 549: if ( ! 550: (q->n_type & N_EXT)==0 ! 551: #if ! (os_unix_ts | os_unisoft) ! 552: || q->n_un.n_strx == 0 || q->n_type & N_STAB ! 553: #endif ! 554: ) continue; ! 555: for (mlbot=lbot,i2 = 0;i2<numberofargs;i2++,mlbot++) { ! 556: #if ! (os_unix_ts | os_unisoft) ! 557: if(strcmp((char *)mlbot->val, ! 558: strtbl+q->n_un.n_strx-4)!=0) ! 559: continue; ! 560: #else ! 561: if(strncmp((char *)mlbot->val, ! 562: q->n_name,8)!=0) ! 563: continue; ! 564: #endif ! 565: change = 1; ! 566: q->n_type &= ~N_EXT; ! 567: break; ! 568: } ! 569: } ! 570: if ( change ) { ! 571: fseek(fa,(long)savesymadd,0); ! 572: fwrite((char *)nlbuf, savem, 1, fa); ! 573: if (--nargleft == 0) ! 574: goto alldone; ! 575: } ! 576: } ! 577: } ! 578: alldone: ! 579: fclose(f); ! 580: fclose(fa); ! 581: if(fvirgin) ! 582: fvirgin = 0; ! 583: stabf = nstabf; ! 584: {Freexs(); return(tatom);} ! 585: } ! 586: char * ! 587: Ilibdir() ! 588: { ! 589: register lispval handy; ! 590: tryagain: ! 591: handy = Vlibdir->a.clb; ! 592: switch(TYPE(handy)) { ! 593: case ATOM: ! 594: handy = (lispval) handy->a.pname; ! 595: case STRNG: ! 596: break; ! 597: default: ! 598: (void) error( ! 599: "cfasl or load: lisp-library-directory not bound to string or atom", ! 600: TRUE); ! 601: goto tryagain; ! 602: } ! 603: return((char *) handy); ! 604: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.