112673Ssam #ifndef lint 2*19963Smckusick static char sccsid[] = "@(#)ranlib.c 4.9 05/06/85"; 312673Ssam #endif 4625Sbill /* 5625Sbill * ranlib - create table of contents for archive; string table version 6625Sbill */ 7625Sbill #include <sys/types.h> 8899Sbill #include <ar.h> 9625Sbill #include <ranlib.h> 10899Sbill #include <a.out.h> 11625Sbill #include <stdio.h> 12625Sbill 13625Sbill struct ar_hdr archdr; 14625Sbill #define OARMAG 0177545 15625Sbill long arsize; 16625Sbill struct exec exp; 17625Sbill FILE *fi, *fo; 18625Sbill long off, oldoff; 19625Sbill long atol(), ftell(); 2011152Sshantz #define TABSZ 6000 21625Sbill struct ranlib tab[TABSZ]; 22625Sbill int tnum; 231753Sbill #define STRTABSZ 75000 24625Sbill char tstrtab[STRTABSZ]; 25625Sbill int tssiz; 26625Sbill char *strtab; 27625Sbill int ssiz; 28625Sbill int new; 29625Sbill char tempnm[] = "__.SYMDEF"; 30625Sbill char firstname[17]; 31625Sbill 32625Sbill main(argc, argv) 33625Sbill char **argv; 34625Sbill { 35625Sbill char cmdbuf[BUFSIZ]; 369343Srt /* magbuf must be an int array so it is aligned on an int-ish 379343Srt boundary, so that we may access its first word as an int! */ 389343Srt int magbuf[(SARMAG+sizeof(int))/sizeof(int)]; 3919932Smckusick register int just_touch = 0; 40625Sbill 4119932Smckusick /* check for the "-t" flag" */ 4219932Smckusick if (argc > 1 && strcmp(argv[1], "-t") == 0) { 4319932Smckusick just_touch++; 4419932Smckusick argc--; 4519932Smckusick argv++; 4619932Smckusick } 4719932Smckusick 48625Sbill --argc; 49625Sbill while(argc--) { 50625Sbill fi = fopen(*++argv,"r"); 51625Sbill if (fi == NULL) { 52625Sbill fprintf(stderr, "ranlib: cannot open %s\n", *argv); 53625Sbill continue; 54625Sbill } 55625Sbill off = SARMAG; 569343Srt fread((char *)magbuf, 1, SARMAG, fi); 579343Srt if (strncmp((char *)magbuf, ARMAG, SARMAG)) { 589343Srt if (magbuf[0] == OARMAG) 59625Sbill fprintf(stderr, "old format "); 60625Sbill else 61625Sbill fprintf(stderr, "not an "); 62625Sbill fprintf(stderr, "archive: %s\n", *argv); 63625Sbill continue; 64625Sbill } 65*19963Smckusick if (just_touch) { 66*19963Smckusick register int len; 67*19963Smckusick 68*19963Smckusick fseek(fi, (long) SARMAG, 0); 69*19963Smckusick if (fread(cmdbuf, sizeof archdr.ar_name, 1, fi) != 1) { 70*19963Smckusick fprintf(stderr, "malformed archive: %s\n", 71*19963Smckusick *argv); 72*19963Smckusick continue; 73*19963Smckusick } 74*19963Smckusick len = strlen(tempnm); 75*19963Smckusick if (bcmp(cmdbuf, tempnm, len) != 0 || 76*19963Smckusick cmdbuf[len] != ' ') { 77*19963Smckusick fprintf(stderr, "no symbol table: %s\n", *argv); 78*19963Smckusick continue; 79*19963Smckusick } 80*19963Smckusick fclose(fi); 81*19963Smckusick fixdate(*++argv); 82*19963Smckusick continue; 83*19963Smckusick } 84625Sbill fseek(fi, 0L, 0); 85625Sbill new = tnum = 0; 86625Sbill if (nextel(fi) == 0) { 87625Sbill fclose(fi); 88625Sbill continue; 89625Sbill } 90625Sbill do { 91625Sbill long o; 92625Sbill register n; 93625Sbill struct nlist sym; 94625Sbill 95625Sbill fread((char *)&exp, 1, sizeof(struct exec), fi); 96625Sbill if (N_BADMAG(exp)) 97625Sbill continue; 9817423Sralph if (!strncmp(tempnm, archdr.ar_name, sizeof(archdr.ar_name))) 9917423Sralph continue; 100625Sbill if (exp.a_syms == 0) { 101625Sbill fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name); 1023607Ssklower continue; 103625Sbill } 104625Sbill o = N_STROFF(exp) - sizeof (struct exec); 105625Sbill if (ftell(fi)+o+sizeof(ssiz) >= off) { 10617423Sralph fprintf(stderr, "ranlib: warning: %s(%s): old format .o file\n", *argv, archdr.ar_name); 10717423Sralph continue; 108625Sbill } 109625Sbill fseek(fi, o, 1); 110625Sbill fread((char *)&ssiz, 1, sizeof (ssiz), fi); 1119343Srt if (ssiz < sizeof ssiz){ 1129343Srt /* sanity check */ 11317423Sralph fprintf(stderr, "ranlib: warning: %s(%s): mangled string table\n", *argv, archdr.ar_name); 11417423Sralph continue; 1159343Srt } 116625Sbill strtab = (char *)calloc(1, ssiz); 117625Sbill if (strtab == 0) { 118625Sbill fprintf(stderr, "ranlib: ran out of memory\n"); 119625Sbill exit(1); 120625Sbill } 121625Sbill fread(strtab+sizeof(ssiz), ssiz - sizeof(ssiz), 1, fi); 122625Sbill fseek(fi, -(exp.a_syms+ssiz), 1); 123625Sbill n = exp.a_syms / sizeof(struct nlist); 124625Sbill while (--n >= 0) { 125625Sbill fread((char *)&sym, 1, sizeof(sym), fi); 126625Sbill if (sym.n_un.n_strx == 0) 127625Sbill continue; 128625Sbill sym.n_un.n_name = strtab + sym.n_un.n_strx; 129625Sbill if ((sym.n_type&N_EXT)==0) 130625Sbill continue; 131625Sbill switch (sym.n_type&N_TYPE) { 132625Sbill 133625Sbill case N_UNDF: 134625Sbill if (sym.n_value!=0) 135625Sbill stash(&sym); 136625Sbill continue; 137625Sbill 138625Sbill default: 139625Sbill stash(&sym); 140625Sbill continue; 141625Sbill } 142625Sbill } 143625Sbill } while(nextel(fi)); 144625Sbill new = fixsize(); 145625Sbill fclose(fi); 146625Sbill fo = fopen(tempnm, "w"); 147625Sbill if(fo == NULL) { 148625Sbill fprintf(stderr, "can't create temporary\n"); 149625Sbill exit(1); 150625Sbill } 151625Sbill tnum *= sizeof (struct ranlib); 152625Sbill fwrite(&tnum, 1, sizeof (tnum), fo); 153625Sbill tnum /= sizeof (struct ranlib); 154625Sbill fwrite((char *)tab, tnum, sizeof(struct ranlib), fo); 155625Sbill fwrite(&tssiz, 1, sizeof (tssiz), fo); 156625Sbill fwrite(tstrtab, tssiz, 1, fo); 157625Sbill fclose(fo); 158625Sbill if(new) 159899Sbill sprintf(cmdbuf, "ar rlb %s %s %s\n", firstname, *argv, tempnm); 160625Sbill else 161899Sbill sprintf(cmdbuf, "ar rl %s %s\n", *argv, tempnm); 162625Sbill if(system(cmdbuf)) 163625Sbill fprintf(stderr, "ranlib: ``%s'' failed\n", cmdbuf); 164625Sbill else 165625Sbill fixdate(*argv); 166625Sbill unlink(tempnm); 167625Sbill } 168625Sbill exit(0); 169625Sbill } 170625Sbill 171625Sbill nextel(af) 172625Sbill FILE *af; 173625Sbill { 174625Sbill register r; 175625Sbill register char *cp; 176625Sbill 177625Sbill oldoff = off; 178625Sbill fseek(af, off, 0); 179625Sbill r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af); 180625Sbill if (r != sizeof(struct ar_hdr)) 181625Sbill return(0); 182625Sbill for (cp=archdr.ar_name; cp < & archdr.ar_name[sizeof(archdr.ar_name)]; cp++) 183625Sbill if (*cp == ' ') 184625Sbill *cp = '\0'; 185625Sbill arsize = atol(archdr.ar_size); 186625Sbill if (arsize & 1) 187625Sbill arsize++; 188625Sbill off = ftell(af) + arsize; 189625Sbill return(1); 190625Sbill } 191625Sbill 192625Sbill stash(s) 193625Sbill struct nlist *s; 194625Sbill { 195625Sbill int i; 196625Sbill register char *cp; 197625Sbill 198625Sbill if(tnum >= TABSZ) { 199625Sbill fprintf(stderr, "ranlib: symbol table overflow\n"); 200625Sbill exit(1); 201625Sbill } 202625Sbill tab[tnum].ran_un.ran_strx = tssiz; 203625Sbill tab[tnum].ran_off = oldoff; 204625Sbill for (cp = s->n_un.n_name; tstrtab[tssiz++] = *cp++;) 205625Sbill if (tssiz > STRTABSZ) { 206625Sbill fprintf(stderr, "ranlib: string table overflow\n"); 207625Sbill exit(1); 208625Sbill } 209625Sbill tnum++; 210625Sbill } 211625Sbill 212625Sbill fixsize() 213625Sbill { 214625Sbill int i; 215625Sbill off_t offdelta; 216625Sbill 217625Sbill if (tssiz&1) 218625Sbill tssiz++; 219625Sbill offdelta = sizeof(archdr) + sizeof (tnum) + tnum * sizeof(struct ranlib) + 220625Sbill sizeof (tssiz) + tssiz; 221625Sbill off = SARMAG; 222625Sbill nextel(fi); 223625Sbill if(strncmp(archdr.ar_name, tempnm, sizeof (archdr.ar_name)) == 0) { 224625Sbill new = 0; 225625Sbill offdelta -= sizeof(archdr) + arsize; 226625Sbill } else { 227625Sbill new = 1; 228625Sbill strncpy(firstname, archdr.ar_name, sizeof(archdr.ar_name)); 229625Sbill } 230625Sbill for(i=0; i<tnum; i++) 231625Sbill tab[i].ran_off += offdelta; 232625Sbill return(new); 233625Sbill } 234625Sbill 235625Sbill /* patch time */ 236625Sbill fixdate(s) 237625Sbill char *s; 238625Sbill { 239625Sbill long time(); 240625Sbill char buf[24]; 241625Sbill int fd; 242625Sbill 243625Sbill fd = open(s, 1); 244625Sbill if(fd < 0) { 245625Sbill fprintf(stderr, "ranlib: can't reopen %s\n", s); 246625Sbill return; 247625Sbill } 248625Sbill sprintf(buf, "%-*ld", sizeof(archdr.ar_date), time((long *)NULL)+5); 249625Sbill lseek(fd, (long)SARMAG + ((char *)archdr.ar_date-(char *)&archdr), 0); 250625Sbill write(fd, buf, sizeof(archdr.ar_date)); 251625Sbill close(fd); 252625Sbill } 253