1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: char copyright[] = 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: #endif not lint 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)ranlib.c 5.3 (Berkeley) 1/22/86"; 15: #endif not lint 16: 17: /* 18: * ranlib - create table of contents for archive; string table version 19: */ 20: #include <sys/types.h> 21: #include <ar.h> 22: #include <ranlib.h> 23: #include <a.out.h> 24: #include <stdio.h> 25: 26: struct ar_hdr archdr; 27: #define OARMAG 0177545 28: long arsize; 29: struct exec exp; 30: FILE *fi, *fo; 31: long off, oldoff; 32: long atol(), ftell(); 33: #define TABSZ 3000 34: int tnum; 35: #define STRTABSZ 30000 36: int tssiz; 37: char *strtab; 38: int ssiz; 39: int new; 40: char tempnm[] = "__.SYMDEF"; 41: char firstname[17]; 42: void stash(); 43: char *malloc(), *calloc(); 44: 45: /* 46: * table segment definitions 47: */ 48: char *segalloc(); 49: void segclean(); 50: struct tabsegment { 51: struct tabsegment *pnext; 52: unsigned nelem; 53: struct ranlib tab[TABSZ]; 54: } tabbase, *ptabseg; 55: struct strsegment { 56: struct strsegment *pnext; 57: unsigned nelem; 58: char stab[STRTABSZ]; 59: } strbase, *pstrseg; 60: 61: main(argc, argv) 62: char **argv; 63: { 64: char cmdbuf[BUFSIZ]; 65: /* magbuf must be an int array so it is aligned on an int-ish 66: boundary, so that we may access its first word as an int! */ 67: int magbuf[(SARMAG+sizeof(int))/sizeof(int)]; 68: register int just_touch = 0; 69: register struct tabsegment *ptab; 70: register struct strsegment *pstr; 71: 72: /* check for the "-t" flag" */ 73: if (argc > 1 && strcmp(argv[1], "-t") == 0) { 74: just_touch++; 75: argc--; 76: argv++; 77: } 78: 79: --argc; 80: while(argc--) { 81: fi = fopen(*++argv,"r"); 82: if (fi == NULL) { 83: fprintf(stderr, "ranlib: cannot open %s\n", *argv); 84: continue; 85: } 86: off = SARMAG; 87: fread((char *)magbuf, 1, SARMAG, fi); 88: if (strncmp((char *)magbuf, ARMAG, SARMAG)) { 89: if (magbuf[0] == OARMAG) 90: fprintf(stderr, "old format "); 91: else 92: fprintf(stderr, "not an "); 93: fprintf(stderr, "archive: %s\n", *argv); 94: continue; 95: } 96: if (just_touch) { 97: register int len; 98: 99: fseek(fi, (long) SARMAG, 0); 100: if (fread(cmdbuf, sizeof archdr.ar_name, 1, fi) != 1) { 101: fprintf(stderr, "malformed archive: %s\n", 102: *argv); 103: continue; 104: } 105: len = strlen(tempnm); 106: if (bcmp(cmdbuf, tempnm, len) != 0 || 107: cmdbuf[len] != ' ') { 108: fprintf(stderr, "no symbol table: %s\n", *argv); 109: continue; 110: } 111: fclose(fi); 112: fixdate(*argv); 113: continue; 114: } 115: fseek(fi, 0L, 0); 116: new = tssiz = tnum = 0; 117: segclean(); 118: if (nextel(fi) == 0) { 119: fclose(fi); 120: continue; 121: } 122: do { 123: long o; 124: register n; 125: struct nlist sym; 126: 127: fread((char *)&exp, 1, sizeof(struct exec), fi); 128: if (N_BADMAG(exp)) 129: continue; 130: if (!strncmp(tempnm, archdr.ar_name, sizeof(archdr.ar_name))) 131: continue; 132: if (exp.a_syms == 0) { 133: fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name); 134: continue; 135: } 136: o = N_STROFF(exp) - sizeof (struct exec); 137: if (ftell(fi)+o+sizeof(ssiz) >= off) { 138: fprintf(stderr, "ranlib: warning: %s(%s): old format .o file\n", *argv, archdr.ar_name); 139: continue; 140: } 141: fseek(fi, o, 1); 142: fread((char *)&ssiz, 1, sizeof (ssiz), fi); 143: if (ssiz < sizeof ssiz){ 144: /* sanity check */ 145: fprintf(stderr, "ranlib: warning: %s(%s): mangled string table\n", *argv, archdr.ar_name); 146: continue; 147: } 148: strtab = (char *)calloc(1, ssiz); 149: if (strtab == 0) { 150: fprintf(stderr, "ranlib: ran out of memory\n"); 151: exit(1); 152: } 153: fread(strtab+sizeof(ssiz), ssiz - sizeof(ssiz), 1, fi); 154: fseek(fi, -(exp.a_syms+ssiz), 1); 155: n = exp.a_syms / sizeof(struct nlist); 156: while (--n >= 0) { 157: fread((char *)&sym, 1, sizeof(sym), fi); 158: if (sym.n_un.n_strx == 0) 159: continue; 160: sym.n_un.n_name = strtab + sym.n_un.n_strx; 161: if ((sym.n_type&N_EXT)==0) 162: continue; 163: switch (sym.n_type&N_TYPE) { 164: 165: case N_UNDF: 166: if (sym.n_value!=0) 167: stash(&sym); 168: continue; 169: 170: default: 171: stash(&sym); 172: continue; 173: } 174: } 175: free(strtab); 176: } while(nextel(fi)); 177: new = fixsize(); 178: fclose(fi); 179: fo = fopen(tempnm, "w"); 180: if(fo == NULL) { 181: fprintf(stderr, "can't create temporary\n"); 182: exit(1); 183: } 184: tnum *= sizeof (struct ranlib); 185: fwrite(&tnum, 1, sizeof (tnum), fo); 186: tnum /= sizeof (struct ranlib); 187: ptab = &tabbase; 188: do { 189: fwrite((char *)ptab->tab, ptab->nelem, 190: sizeof(struct ranlib), fo); 191: } while (ptab = ptab->pnext); 192: fwrite(&tssiz, 1, sizeof (tssiz), fo); 193: pstr = &strbase; 194: do { 195: fwrite(pstr->stab, pstr->nelem, 1, fo); 196: tssiz -= pstr->nelem; 197: } while (pstr = pstr->pnext); 198: /* pad with nulls */ 199: while (tssiz--) putc('\0', fo); 200: fclose(fo); 201: if(new) 202: sprintf(cmdbuf, "ar rlb %s %s %s\n", firstname, *argv, tempnm); 203: else 204: sprintf(cmdbuf, "ar rl %s %s\n", *argv, tempnm); 205: if(system(cmdbuf)) 206: fprintf(stderr, "ranlib: ``%s'' failed\n", cmdbuf); 207: else 208: fixdate(*argv); 209: unlink(tempnm); 210: } 211: exit(0); 212: } 213: 214: nextel(af) 215: FILE *af; 216: { 217: register r; 218: register char *cp; 219: 220: oldoff = off; 221: fseek(af, off, 0); 222: r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af); 223: if (r != sizeof(struct ar_hdr)) 224: return(0); 225: for (cp=archdr.ar_name; cp < & archdr.ar_name[sizeof(archdr.ar_name)]; cp++) 226: if (*cp == ' ') 227: *cp = '\0'; 228: arsize = atol(archdr.ar_size); 229: if (arsize & 1) 230: arsize++; 231: off = ftell(af) + arsize; 232: return(1); 233: } 234: 235: void 236: stash(s) 237: struct nlist *s; 238: { 239: register char *cp; 240: register char *strtab; 241: register strsiz; 242: register struct ranlib *tab; 243: register tabsiz; 244: 245: if (ptabseg->nelem >= TABSZ) { 246: /* allocate a new symbol table segment */ 247: ptabseg = ptabseg->pnext = 248: (struct tabsegment *) segalloc(sizeof(struct tabsegment)); 249: ptabseg->pnext = NULL; 250: ptabseg->nelem = 0; 251: } 252: tabsiz = ptabseg->nelem; 253: tab = ptabseg->tab; 254: 255: if (pstrseg->nelem >= STRTABSZ) { 256: /* allocate a new string table segment */ 257: pstrseg = pstrseg->pnext = 258: (struct strsegment *) segalloc(sizeof(struct strsegment)); 259: pstrseg->pnext = NULL; 260: pstrseg->nelem = 0; 261: } 262: strsiz = pstrseg->nelem; 263: strtab = pstrseg->stab; 264: 265: tab[tabsiz].ran_un.ran_strx = tssiz; 266: tab[tabsiz].ran_off = oldoff; 267: redo: 268: for (cp = s->n_un.n_name; strtab[strsiz++] = *cp++;) 269: if (strsiz >= STRTABSZ) { 270: /* allocate a new string table segment */ 271: pstrseg = pstrseg->pnext = 272: (struct strsegment *) segalloc(sizeof(struct strsegment)); 273: pstrseg->pnext = NULL; 274: strsiz = pstrseg->nelem = 0; 275: strtab = pstrseg->stab; 276: goto redo; 277: } 278: 279: tssiz += strsiz - pstrseg->nelem; /* length of the string */ 280: pstrseg->nelem = strsiz; 281: tnum++; 282: ptabseg->nelem++; 283: } 284: 285: /* allocate a zero filled segment of size bytes */ 286: char * 287: segalloc(size) 288: unsigned size; 289: { 290: char *pseg = NULL; 291: 292: pseg = malloc(size); 293: if (pseg == NULL) { 294: fprintf(stderr, "ranlib: ran out of memeory\n"); 295: exit(1); 296: } 297: return(pseg); 298: } 299: 300: /* free segments */ 301: void 302: segclean() 303: { 304: register struct tabsegment *ptab; 305: register struct strsegment *pstr; 306: 307: /* 308: * symbol table 309: * 310: * The first entry is static. 311: */ 312: ptabseg = &tabbase; 313: ptab = ptabseg->pnext; 314: while (ptabseg = ptab) { 315: ptab = ptabseg->pnext; 316: free((char *)ptabseg); 317: } 318: ptabseg = &tabbase; 319: ptabseg->pnext = NULL; 320: ptabseg->nelem = 0; 321: 322: /* 323: * string table 324: * 325: * The first entry is static. 326: */ 327: pstrseg = &strbase; 328: pstr = pstrseg->pnext; 329: while (pstrseg = pstr) { 330: pstr = pstrseg->pnext; 331: free((char *)pstrseg); 332: } 333: pstrseg = &strbase; 334: pstrseg->pnext = NULL; 335: pstrseg->nelem = 0; 336: } 337: 338: fixsize() 339: { 340: int i; 341: off_t offdelta; 342: register struct tabsegment *ptab; 343: 344: if (tssiz&1) 345: tssiz++; 346: offdelta = sizeof(archdr) + sizeof (tnum) + tnum * sizeof(struct ranlib) + 347: sizeof (tssiz) + tssiz; 348: off = SARMAG; 349: nextel(fi); 350: if(strncmp(archdr.ar_name, tempnm, sizeof (archdr.ar_name)) == 0) { 351: new = 0; 352: offdelta -= sizeof(archdr) + arsize; 353: } else { 354: new = 1; 355: strncpy(firstname, archdr.ar_name, sizeof(archdr.ar_name)); 356: } 357: ptab = &tabbase; 358: do { 359: for (i = 0; i < ptab->nelem; i++) 360: ptab->tab[i].ran_off += offdelta; 361: } while (ptab = ptab->pnext); 362: return(new); 363: } 364: 365: /* patch time */ 366: fixdate(s) 367: char *s; 368: { 369: long time(); 370: char buf[24]; 371: int fd; 372: 373: fd = open(s, 1); 374: if(fd < 0) { 375: fprintf(stderr, "ranlib: can't reopen %s\n", s); 376: return; 377: } 378: sprintf(buf, "%-*ld", sizeof(archdr.ar_date), time((long *)NULL)+5); 379: lseek(fd, (long)SARMAG + ((char *)archdr.ar_date-(char *)&archdr), 0); 380: write(fd, buf, sizeof(archdr.ar_date)); 381: close(fd); 382: }