home *** CD-ROM | disk | FTP | other *** search
- /*
- * SCCS: @(#)libmtch.c 1.2 11/2/84 14:18:55
- * Read library files.
- *
- ***********************************************************************
- * This software is copyright of
- *
- * John M Collins
- * 47 Cedarwood Drive
- * St Albans
- * Herts, AL4 0DN
- * England +44 727 57267
- *
- * and is released into the public domain on the following conditions:
- *
- * 1. No free maintenance will be guaranteed.
- * 2. Nothing may be based on this software without
- * acknowledgement, including incorporation of this
- * notice.
- *
- * Notwithstanding the above, the author welcomes correspondence and bug
- * fixes.
- ***********************************************************************
- */
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <a.out.h>
- #include <ar.h>
- #include <setjmp.h>
- #include "unc.h"
-
- long lseek();
- void bfopen(), bfclose(), nomem();
- void rrell2(), markmatch();
- char *strchr(), *strrchr(), *strncpy(), *strcat(), *strcpy(), *malloc();
- int matchup();
- long findstart();
-
- char verbose; /* Tell the world what we are doing */
- char *tfnam;
- char *cfile;
- ef_fids mainfile;
- struct commit dreltab;
- int donedrel, donebrel;
- long trelpos, drelpos, brelpos;
- static struct libit currlib = {-1, 0, -1, ""};
-
- void lclash(str)
- char *str;
- {
- (void) fprintf(stderr, "Library scan failure - %s\n", str);
- (void) fprintf(stderr, "Searching %s\n", cfile);
- if (currlib.lf_name[0])
- (void) fprintf(stderr, "Member is %s\n", currlib.lf_name);
- exit(255);
- }
-
- /*
- * Find next member.
- */
-
- long nextmemb(lfd)
- register struct libit *lfd;
- {
- struct ar_hdr arbuf;
-
- if (lfd->lf_next < 0)
- return -1;
-
- (void) lseek(lfd->lf_fd, lfd->lf_next, 0);
- if (read(lfd->lf_fd, (char *)&arbuf, sizeof(arbuf)) != sizeof(arbuf)) {
- lfd->lf_next = -1;
- return -1;
- }
- (void) strncpy(lfd->lf_name, arbuf.ar_name, sizeof(lfd->lf_name));
- lfd->lf_offset = lfd->lf_next + sizeof(arbuf);
- lfd->lf_next = (lfd->lf_offset + arbuf.ar_size + 1) & ~1;
- return lfd->lf_offset;
- }
-
- /*
- * Decode a file name thus -
- *
- * -lxxx decode as /lib/libxxx.a /usr/lib/libxxx.a etc
- * -Lxxx forget "lib" ".a" bit thus -Lcrt0.o
- * or read LDPATH environment var to give list of directories as sh
- * (default /lib:/usr/lib).
- *
- * Alternatively treat as normal pathname.
- *
- * File names may be followed by (membername) if the file is an archive,
- * thus
- *
- * -lc(printf.o)
- *
- * in which case the specified module is fetched.
- */
-
- struct libit *getfnam(str)
- char *str;
- {
- char *bp, *ep = NULL, *pathb, *pathe, *fullpath = NULL;
- static char *pathn;
- extern char *getenv();
- long magic;
- struct ar_hdr arhdr;
- int fd;
-
- if ((bp = strrchr(str, '(')) != NULL &&
- (ep = strrchr(str, ')')) != NULL)
- *ep = *bp = '\0';
-
- if (str[0] == '-' && (str[1] == 'l' || str[1] == 'L')) {
- if (pathn == NULL) {
- if ((pathn = getenv("LDPATH")) == NULL)
- pathn = "/lib:/usr/lib";
- }
- fullpath = malloc((unsigned)(strlen(pathn) + strlen(str) + 1));
- if (fullpath == NULL)
- nomem();
- pathb = pathn;
- do {
- pathe = strchr(pathb, ':');
- if (*pathb == ':')
- fullpath[0] = '\0';
- else {
- if (pathe != NULL)
- *pathe = '\0';
- (void) strcpy(fullpath, pathb);
- (void) strcat(fullpath, "/");
- if (pathe != NULL)
- *pathe = ':';
- }
- if (str[1] == 'l')
- (void) strcat(fullpath, "lib");
- (void) strcat(fullpath, &str[2]);
- if (str[1] == 'l')
- (void) strcat(fullpath, ".a");
- if ((fd = open(fullpath, O_RDONLY)) >= 0)
- goto found;
- pathb = pathe + 1;
- } while (pathe != NULL);
-
- (void) fprintf(stderr, "Unable to locate lib%s.a in %s\n",
- &str[2], pathn);
- exit(101);
- }
- else if ((fd = open(str, O_RDONLY)) < 0) {
- (void) fprintf(stderr, "Cannot open %s\n", str);
- exit(102);
- }
-
- found:
-
- if ((read(fd, (char *) &magic, sizeof(magic)) != sizeof(magic) ||
- magic != ARMAG)) {
- if (ep != NULL) {
- (void) fprintf(stderr, "%s is not library file\n",
- fullpath != NULL? fullpath: str);
- exit(103);
- }
- if (fullpath != NULL)
- free(fullpath);
- currlib.lf_fd = fd;
- currlib.lf_offset = 0;
- currlib.lf_next = -1;
- currlib.lf_name[0] = '\0';
- return &currlib;
- }
-
- /*
- * It appears to be a library file - see if we want a specific
- * one.
- */
-
- if (ep != NULL) {
- currlib.lf_offset = sizeof(magic) + sizeof(struct ar_hdr);
- for (;;) {
- if (read(fd, &arhdr, sizeof(arhdr)) != sizeof(arhdr)) {
- (void) fprintf(stderr, "Cannot find member %s in %s\n",
- bp+1, fullpath?fullpath: str);
- exit(103);
- }
- if (strncmp(bp+1, arhdr.ar_name, sizeof(arhdr.ar_name)) == 0)
- break;
- currlib.lf_offset += arhdr.ar_size + sizeof(arhdr) + 1;
- currlib.lf_offset &= ~ 1;
- (void) lseek(fd, (long)(currlib.lf_offset - sizeof(arhdr)), 0);
- }
- if (fullpath != NULL)
- free(fullpath);
- currlib.lf_fd = fd;
- currlib.lf_next = -1;
- currlib.lf_name[0] = '\0';
- *bp = '(';
- *ep = ')';
- return &currlib;
- }
-
- /*
- * Otherwise point to 1st member in library.
- */
-
- if (read(fd, &arhdr, sizeof(arhdr)) != sizeof(arhdr)) {
- (void) fprintf(stderr, "Library %s empty\n", fullpath? fullpath: str);
- exit(104);
- }
- if (fullpath != NULL)
- free(fullpath);
- currlib.lf_offset = sizeof(magic) + sizeof(arhdr);
- currlib.lf_next = currlib.lf_offset + arhdr.ar_size + 1;
- currlib.lf_next &= ~1;
- currlib.lf_fd = fd;
- (void) strncpy(currlib.lf_name, arhdr.ar_name, sizeof(currlib.lf_name));
- return &currlib;
- }
-
- /*
- * Process library files.
- */
-
- #define MINTEXT 6
-
- void lscan(nfiles, fnames)
- int nfiles;
- char **fnames;
- {
- ef_fids libfile;
- register ef_fid ll = &libfile;
- register struct libit *clf;
- extern symbol dolsymb();
- int firstfile;
-
- for (; nfiles > 0; fnames++, nfiles--) {
- clf = getfnam(*fnames);
- cfile = *fnames;
- firstfile = 1;
- do {
- bfopen(tfnam, ll);
-
- /*
- * If file is garbled, silently forget it and go
- * on to the next one.
- */
-
- if (!rtext(clf->lf_fd, clf->lf_offset, ll))
- goto closeit;
-
- if (ll->ef_tsize < MINTEXT)
- goto closeit;
-
- if (!rdata(clf->lf_fd, clf->lf_offset, ll))
- goto closeit;
-
- if (rrell1(clf->lf_fd, clf->lf_offset, ll) < 0)
- goto closeit;
-
- /*
- * If first file in library, find it from
- * beginning of main file.
- */
-
- if (firstfile) {
- if ((trelpos = findstart(&mainfile, ll)) < 0)
- goto closeit;
- firstfile = 0;
- }
- else if (!matchup(&mainfile, ll, trelpos))
- goto closeit;
-
- /*
- * Found a match.
- */
-
- if (!rsymb(clf->lf_fd, clf->lf_offset, dolsymb, ll)) {
- (void) fprintf(stderr, "Corrupt file %s\n",
- *fnames);
- exit(150);
- }
-
- donedrel = 0;
- donebrel = 0;
- rrell2(clf->lf_fd, clf->lf_offset, ll);
- if (verbose) {
- (void) fprintf(stderr, "Found: ");
- if (clf->lf_name[0])
- (void) fprintf(stderr, "%.14s in ",
- clf->lf_name);
- (void) fprintf(stderr, "%s\n", *fnames);
- }
- if (libfile.ef_stvec != NULL) {
- free(libfile.ef_stvec);
- libfile.ef_stvec = NULL;
- libfile.ef_stcnt = 0;
- }
- dreltab.c_int = 0;
-
- /*
- * Start looking next time round
- * where last one left off.
- */
-
- markmatch(&mainfile, ll, trelpos);
- trelpos += libfile.ef_tsize;
- closeit:
- bfclose(ll);
- } while (nextmemb(clf) >= 0);
- }
- }
-