1: # include <fcntl.h>
2: # include <sccs.h>
3:
4: SCCSID(@(#)timefix.c 8.2 1/18/85)
5:
6: /*
7: ** TIMEFIX -- patch binary program to correct for timezone changes.
8: **
9: ** Timefix is compiled with the ctime(III) variables:
10: ** daylight,
11: ** timezone,
12: ** tzname[]
13: **
14: ** Each file specified is examined to see if it contains
15: ** all of these variables. If it does then the current values
16: ** of those variables for that file are given. If the "-u" flag
17: ** is specified then the values are not overwritten.
18: **
19: ** The other flags can be used to override the values of the
20: ** variables; specifically:
21: ** -sxxx --> timezone (xxx converted from ascii to binary)
22: ** -dx --> daylight (x converted from ascii to binary)
23: ** -tXXXYYY -> tzname[0] = "XXX" and tzname[1] = "YYY"
24: */
25:
26: struct
27: {
28: int magic;
29: int tsize;
30: int dsize;
31: int bss;
32: int ssize;
33: int start_ad;
34: int unused;
35: int reloc_flag;
36: };
37:
38: struct sym
39: {
40: char symname[8];
41: int type;
42: int value;
43: };
44:
45:
46: /* these values are defined in the unix ctime() routine */
47: extern int daylight;
48: extern int timezone;
49: extern char *tzname[];
50:
51: int Noupdate;
52:
53: main(argc, argv)
54: int argc;
55: char *argv[];
56: {
57:
58: if (argc < 2)
59: {
60: printf("usage: timefix filename ...\n");
61: exit (1);
62: }
63:
64: argc--;
65: argv++;
66:
67: if (checkflags(&argc, argv))
68: exit (1);
69:
70: pr_values("your installation", timezone, tzname[0], tzname[1], daylight);
71:
72: while (argc--)
73: newtime(*argv++);
74: }
75: /*
76: ** NEWTIME
77: */
78:
79: newtime(filename)
80: char *filename;
81: {
82: struct sym timez, name_st, name_dy, dayflag;
83: struct header head;
84: register int i, fdes;
85: int adr, secs;
86: char std[4], dyl[4];
87:
88: if ((fdes = openheader(&head, filename)) < 0)
89: return (-1);
90:
91: bmove("_timezon", timez.symname, 8);
92: bmove("_tzname\0", name_st.symname, 8);
93: bmove("_dayligh", dayflag.symname, 8);
94:
95: /* pick up addresses from symbol table */
96: i = findsymbol(&head, fdes, &timez);
97: i |= findsymbol(&head, fdes, &name_st);
98: i |= findsymbol(&head, fdes, &dayflag);
99:
100: if (i)
101: {
102: printf("File %s does not need to be corrected\n", filename);
103: close(fdes);
104: return (-2);
105: }
106:
107: /* form entries for pointer to "PST" and "PDT" */
108: i = getvalue(&head, fdes, &name_st, &adr, 2);
109: name_st.value += 2;
110: i |= getvalue(&head, fdes, &name_st, &name_dy.value, 2);
111: name_dy.type = name_st.type;
112: name_st.value = adr;
113:
114: if (i)
115: {
116: printf("can't find pointers to timezone names in %s\n", filename);
117: close(fdes);
118: return (-3);
119: }
120:
121: /* now print out current values */
122: i = getvalue(&head, fdes, &timez, &secs, 2);
123: i |= getvalue(&head, fdes, &name_st, std, 4);
124: i |= getvalue(&head, fdes, &name_dy, dyl, 4);
125: i |= getvalue(&head, fdes, &dayflag, &adr, 2);
126:
127: if (i)
128: {
129: printf("one or more symbols cannot be read from %s\n", filename);
130: close(fdes);
131: return (-4);
132: }
133:
134: pr_values(filename, secs, std, dyl, adr);
135:
136: if (!Noupdate)
137: {
138: if (putvalue(&head, fdes, &timez, &timezone, 2)
139: || putvalue(&head, fdes, &name_st, tzname[0], 4)
140: || putvalue(&head, fdes, &name_dy, tzname[1], 4)
141: || putvalue(&head, fdes, &dayflag, &daylight, 2))
142: {
143: printf("cannot update %s with new values\n", filename);
144: close(fdes);
145: return (-2);
146: }
147: else
148: printf("File %s updated.\n", filename);
149: }
150:
151:
152: close(fdes);
153:
154: return (0);
155: }
156: /*
157: ** Open the indicated file and read & verify header
158: */
159:
160: (hd, filename)
161: struct header *hd;
162: char *filename;
163: {
164: register int fd, i;
165:
166: if ((fd = open(filename, O_RDWR)) < 0)
167: {
168: printf("can't open file %s\n", filename);
169: return (-1);
170: }
171:
172: if ((i = read(fd, hd, sizeof (*hd))) != sizeof (*hd))
173: {
174: printf("can't read in header\n");
175: close(fd);
176: return (-2);
177: }
178:
179: switch (hd->magic)
180: {
181:
182: case 0407:
183: case 0410:
184: case 0411:
185: if (hd->ssize)
186: break;
187: printf("File %s does not have a symbol table.\n", filename);
188: return (-4);
189:
190: default:
191: printf("%s not an object file\n", filename);
192: return (-3);
193: }
194:
195: return (fd);
196: }
197: /*
198: ** Seek to beginning of symbol table
199: */
200:
201: startsymbol(hd, fdx)
202: struct header *hd;
203: int fdx;
204: {
205: register int i, fd;
206: register struct header *h;
207: long offset;
208: long itol();
209:
210: h = hd;
211: fd = fdx;
212:
213: /* seek past header */
214: i = lseek(fd, 16L, 0);
215:
216: /* seek to start of symbol table */
217: offset = itol(h->tsize);
218: offset = offset + itol(h->dsize);
219: if (h->reloc_flag == 0)
220: offset += offset;
221:
222: i |= lseek(fd, offset, 1);
223:
224: if (i < 0)
225: {
226: printf("can't seek to symbol table\n");
227: return (-1);
228: }
229:
230: return (0);
231: }
232: /*
233: ** Locate symbol in symbol table and return sucess-failure
234: */
235:
236: findsymbol(hd, fd, s)
237: struct header *hd;
238: int fd;
239: struct sym *s;
240: {
241: register int i, j;
242: struct sym next;
243:
244: if (startsymbol(hd, fd))
245: return (-1);
246:
247: for (i = hd->ssize; i--; )
248: {
249: j = read(fd, &next, sizeof (next));
250:
251: if (j != sizeof (next))
252: {
253: if (j)
254: printf("symbol table error %d,%d,%d\n", hd->ssize, i, j);
255: return (-1);
256: }
257:
258: if (bequal(next.symname, s->symname, sizeof (next.symname)))
259: {
260: s->type = next.type;
261: s->value = next.value;
262: return (0);
263: }
264: }
265:
266: return (1);
267: }
268: /*
269: ** GETVALUE
270: */
271:
272: getvalue(hd, fd, s, cp, len)
273: struct header *hd;
274: int fd;
275: struct sym *s;
276: char *cp;
277: int len;
278: {
279: register int i;
280: long getaddr(), addr;
281:
282: addr = getaddr(hd, s);
283: if (addr == -1)
284: return (-1);
285:
286: if (lseek(fd, addr, 0) < 0)
287: return (-1);
288:
289: if ((i = read(fd, cp, len)) != len)
290: return (-1);
291:
292: return (0);
293: }
294: /*
295: ** PUTVALUE
296: */
297:
298:
299: putvalue(hd, fd, s, loc, len)
300: struct header *hd;
301: int fd;
302: struct sym *s;
303: char *loc;
304: int len;
305: {
306: long adr, getaddr();
307:
308: adr = getaddr(hd, s);
309: if (adr == -1)
310: return (-1);
311:
312: if (lseek(fd, adr, 0) < 0)
313: return (-1);
314:
315: if (write(fd, loc, len) != len)
316: return (-2);
317:
318: return (0);
319: }
320: /*
321: ** PR_VALUES
322: */
323:
324: pr_values(str, secs, std, dyl, flag)
325: char *str;
326: int secs;
327: char *std;
328: char *dyl;
329: int flag;
330: {
331: printf("\nCurrent values for %s are:\n\t# seconds past greenwich: %d\n", str, secs);
332: printf("\ttimezones: %.4s and %.4s\n\tdaylight saving flag: %d\n", std, dyl, flag);
333: }
334: /*
335: ** CHECKFLAGS
336: */
337:
338: checkflags(argc, argv)
339: int *argc;
340: char *argv[];
341: {
342: register char *cp, **nargv;
343: register int cnt;
344: int ret;
345:
346: ret = 0;
347: cnt = *argc;
348: nargv = argv;
349: while (cnt--)
350: {
351: cp = *argv++;
352: if (*cp == '-')
353: {
354: (*argc)--;
355: cp++;
356: switch (*cp++)
357: {
358:
359: case 's':
360: timezone = atoi(cp);
361: break;
362:
363: case 't':
364: bmove(cp, tzname[0], 3);
365: bmove(cp+3, tzname[1], 3);
366: break;
367:
368: case 'd':
369: daylight = atoi(cp);
370: break;
371:
372: case 'u':
373: Noupdate++;
374: break;
375:
376: default:
377: printf("bad flag %s\n", cp - 2);
378: ret = -1;
379: }
380: }
381: else
382: *nargv++ = cp;
383: }
384:
385: return (ret);
386: }
387:
388:
389: bmove(src, dst, len)
390: char *src;
391: char *dst;
392: int len;
393: {
394: register int i;
395: register char *s, *d;
396:
397: s = src;
398: d = dst;
399: i = len;
400:
401: while (i--)
402: *d++ = *s++;
403: }
404:
405:
406: bequal(s1, s2, len)
407: char *s1;
408: char *s2;
409: int len;
410: {
411: register int i;
412: register char *s, *d;
413:
414: s = s1;
415: d = s2;
416: i = len;
417:
418: while (i--)
419: if (*s++ != *d++)
420: return (0);
421:
422: return (1);
423: }
424: /*
425: ** GETADDR
426: */
427:
428: long
429: getaddr(hd, s)
430: struct header *hd;
431: struct sym *s;
432: {
433: long addr;
434: int i;
435: long l;
436: long itol();
437:
438: addr = s->value + 16; /* offset past header */
439:
440: switch (s->type)
441: {
442:
443: /* extern text segment */
444: case 042:
445: return (addr);
446:
447: /* data segment extern */
448: case 043:
449: switch (hd->magic)
450: {
451:
452: case 0407:
453: return (addr);
454:
455: case 0410:
456: /* subtract space between text and data */
457: l = itol(hd->tsize) + 017777;
458: l &= ~017777;
459:
460: return (addr - (l - itol(hd->tsize)));
461:
462: case 0411:
463: return (addr + itol(hd->tsize));
464:
465: }
466: default:
467: printf("Invalid symbol type %o\n", s->type);
468: return (-1);
469: }
470: }
471:
472:
473: long itol(value)
474: int value;
475: {
476: long ret;
477: int *ip;
478:
479: ret = value;
480: ip = &ret;
481: *ip = 0;
482:
483: return (ret);
484: }