rationalized handling of child processes, cleaned up mail1 some more
[unix-history] / usr / src / usr.bin / ranlib / ranlib.c
CommitLineData
d0aeaf5a
DF
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
34aa0635 7#ifndef lint
d0aeaf5a
DF
8char 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
d93c729e 14static char sccsid[] = "@(#)ranlib.c 5.4 (Berkeley) %G%";
d0aeaf5a
DF
15#endif not lint
16
1372f8b5
BJ
17/*
18 * ranlib - create table of contents for archive; string table version
19 */
20#include <sys/types.h>
2785c759 21#include <ar.h>
1372f8b5 22#include <ranlib.h>
2785c759 23#include <a.out.h>
1372f8b5
BJ
24#include <stdio.h>
25
26struct ar_hdr archdr;
27#define OARMAG 0177545
28long arsize;
29struct exec exp;
30FILE *fi, *fo;
31long off, oldoff;
32long atol(), ftell();
e62e46e3 33#define TABSZ 3000
1372f8b5 34int tnum;
e62e46e3 35#define STRTABSZ 30000
1372f8b5
BJ
36int tssiz;
37char *strtab;
38int ssiz;
39int new;
d93c729e 40char tempnm[] = RANLIBMAG;
1372f8b5 41char firstname[17];
e62e46e3
KM
42void stash();
43char *malloc(), *calloc();
44
45/*
46 * table segment definitions
47 */
48char *segalloc();
49void segclean();
50struct tabsegment {
51 struct tabsegment *pnext;
52 unsigned nelem;
53 struct ranlib tab[TABSZ];
54} tabbase, *ptabseg;
55struct strsegment {
56 struct strsegment *pnext;
57 unsigned nelem;
58 char stab[STRTABSZ];
59} strbase, *pstrseg;
1372f8b5
BJ
60
61main(argc, argv)
62char **argv;
63{
64 char cmdbuf[BUFSIZ];
2a7750c9 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)];
30c310a4 68 register int just_touch = 0;
e62e46e3
KM
69 register struct tabsegment *ptab;
70 register struct strsegment *pstr;
30c310a4
KM
71
72 /* check for the "-t" flag" */
73 if (argc > 1 && strcmp(argv[1], "-t") == 0) {
74 just_touch++;
75 argc--;
76 argv++;
77 }
1372f8b5
BJ
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;
2a7750c9 87 fread((char *)magbuf, 1, SARMAG, fi);
88 if (strncmp((char *)magbuf, ARMAG, SARMAG)) {
89 if (magbuf[0] == OARMAG)
1372f8b5
BJ
90 fprintf(stderr, "old format ");
91 else
92 fprintf(stderr, "not an ");
93 fprintf(stderr, "archive: %s\n", *argv);
94 continue;
95 }
62ed4d47
KM
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);
c75e8e88 112 fixdate(*argv);
62ed4d47
KM
113 continue;
114 }
1372f8b5 115 fseek(fi, 0L, 0);
e62e46e3
KM
116 new = tssiz = tnum = 0;
117 segclean();
1372f8b5
BJ
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;
dcacd57d
RC
130 if (!strncmp(tempnm, archdr.ar_name, sizeof(archdr.ar_name)))
131 continue;
1372f8b5
BJ
132 if (exp.a_syms == 0) {
133 fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name);
fd894872 134 continue;
1372f8b5
BJ
135 }
136 o = N_STROFF(exp) - sizeof (struct exec);
137 if (ftell(fi)+o+sizeof(ssiz) >= off) {
dcacd57d
RC
138 fprintf(stderr, "ranlib: warning: %s(%s): old format .o file\n", *argv, archdr.ar_name);
139 continue;
1372f8b5
BJ
140 }
141 fseek(fi, o, 1);
142 fread((char *)&ssiz, 1, sizeof (ssiz), fi);
2a7750c9 143 if (ssiz < sizeof ssiz){
144 /* sanity check */
dcacd57d
RC
145 fprintf(stderr, "ranlib: warning: %s(%s): mangled string table\n", *argv, archdr.ar_name);
146 continue;
2a7750c9 147 }
1372f8b5
BJ
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 }
e62e46e3 175 free(strtab);
1372f8b5
BJ
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);
e62e46e3
KM
187 ptab = &tabbase;
188 do {
189 fwrite((char *)ptab->tab, ptab->nelem,
190 sizeof(struct ranlib), fo);
191 } while (ptab = ptab->pnext);
1372f8b5 192 fwrite(&tssiz, 1, sizeof (tssiz), fo);
e62e46e3
KM
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);
1372f8b5
BJ
200 fclose(fo);
201 if(new)
2785c759 202 sprintf(cmdbuf, "ar rlb %s %s %s\n", firstname, *argv, tempnm);
1372f8b5 203 else
2785c759 204 sprintf(cmdbuf, "ar rl %s %s\n", *argv, tempnm);
1372f8b5
BJ
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
214nextel(af)
215FILE *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
e62e46e3 235void
1372f8b5
BJ
236stash(s)
237 struct nlist *s;
238{
1372f8b5 239 register char *cp;
e62e46e3
KM
240 register char *strtab;
241 register strsiz;
242 register struct ranlib *tab;
243 register tabsiz;
1372f8b5 244
e62e46e3
KM
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;
1372f8b5 251 }
e62e46e3
KM
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;
267redo:
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;
1372f8b5 277 }
e62e46e3
KM
278
279 tssiz += strsiz - pstrseg->nelem; /* length of the string */
280 pstrseg->nelem = strsiz;
1372f8b5 281 tnum++;
e62e46e3
KM
282 ptabseg->nelem++;
283}
284
285/* allocate a zero filled segment of size bytes */
286char *
287segalloc(size)
288unsigned 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 */
301void
302segclean()
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;
1372f8b5
BJ
336}
337
338fixsize()
339{
340 int i;
341 off_t offdelta;
e62e46e3 342 register struct tabsegment *ptab;
1372f8b5
BJ
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 }
e62e46e3
KM
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);
1372f8b5
BJ
362 return(new);
363}
364
365/* patch time */
366fixdate(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}