|
|
1.1 root 1: /*
2: * ATclock.c
3: * 5/16/90
4: * ATclock - read or set the IBM AT real-time clock
5: * Usage: /etc/ATclock [YY[MM[DD[HH[MM[.SS]]]]]]
6: * cc -s -i -O -o ATclock ATclock.c ATclockas.s
7: *
8: */
9:
10: #include <stdio.h>
11: #include <fcntl.h>
12:
13: #define USAGE "Usage: /etc/ATclock [YY[MM[DD[HH[MM[.SS]]]]]]\n"
14:
15: /* Offsets within clock memory. */
16: #define DIAG 14 /* Diagnostic port: bit(7) -> powerloss */
17: /* bit(2) -> bad time */
18: #define BADCLK 0x84
19: #define STAT 10 /* Status port: bit(7) -> updating */
20: #define UPDATE 0x80
21: #define YEAR 9
22: #define MON 8
23: #define DAY 7
24: #define HOUR 4
25: #define MIN 2
26: #define SEC 0
27:
28: #define DEV_CMOS "/dev/cmos"
29: #define DEV_CLOCK "/dev/clock"
30:
31: #define CLKLEN 10
32:
33: /* Forward. */
34: int bcd();
35: void clock();
36: void clockcheck();
37: void fatal();
38: void sanity();
39: void set();
40: void usage();
41:
42: int zget();
43: void zput();
44:
45: /* Globals. */
46: unsigned char clkbuf[CLKLEN]; /* Clock image buffer (ten BCD digits). */
47:
48: int fd_cmos;
49: int fd_clock;
50:
51: /*
52: * zget()
53: *
54: * read a byte from a specified offset in CMOS
55: *
56: */
57: int
58: zget(offset)
59: int offset;
60: {
61: int ret;
62:
63: lseek(fd_cmos, (long)offset, 0);
64: if(read(fd_cmos, &ret, 1) != 1) {
65: fprintf(stderr, "Can't read CMOS byte %d\n", offset);
66: exit (1);
67: }
68: return ret & 0xff;
69: }
70:
71: main(argc, argv) int argc; char *argv[];
72: {
73: if((fd_cmos = open(DEV_CMOS, O_RDONLY)) == -1) {
74: fprintf(stderr, "ATclock: can't read %s.\n",
75: DEV_CMOS);
76: exit(1);
77: }
78:
79: if((fd_clock = open(DEV_CLOCK, O_RDONLY)) == -1) {
80: fprintf(stderr, "ATclock: can't read %s.\n",
81: DEV_CLOCK);
82: exit(1);
83: }
84:
85: if (argc > 2)
86: usage();
87:
88: if (zget(DIAG) & BADCLK)
89: fatal("bad clock"); /* check for valid clock */
90:
91: if (read(fd_clock, clkbuf, CLKLEN) != CLKLEN) {
92: fprintf(stderr, "Can't read %d bytes from %s.\n",
93: CLKLEN, DEV_CLOCK);
94: exit(1);
95: }
96:
97: if (argc == 2) {
98: close(fd_clock);
99: if((fd_clock = open(DEV_CLOCK, O_RDWR)) == -1) {
100: fprintf(stderr, "ATclock: can't write %s.\n",
101: DEV_CLOCK);
102: exit(1);
103: }
104: set(argv[1]); /* initialize clkbuf[] */
105: lseek(fd_clock, 0L, 0);
106: if (write(fd_clock, clkbuf, CLKLEN) != CLKLEN) {
107: fprintf(stderr, "Can't write %d bytes to %s.\n",
108: CLKLEN, DEV_CLOCK);
109: exit(1);
110: }
111: } else
112: clockcheck(); /* check clock */
113:
114: /* Print formatted date. */
115: printf("%d%d%d%d%d%d%d%d%d%d.%d%d\n",
116: clkbuf[YEAR] >> 4, clkbuf[YEAR] & 15,
117: clkbuf[MON] >> 4, clkbuf[MON] & 15,
118: clkbuf[DAY] >> 4, clkbuf[DAY] & 15,
119: clkbuf[HOUR] >> 4, clkbuf[HOUR] & 15,
120: clkbuf[MIN] >> 4, clkbuf[MIN] & 15,
121: clkbuf[SEC] >> 4, clkbuf[SEC] & 15
122: );
123:
124: close(fd_cmos);
125: close(fd_clock);
126: exit (0);
127: }
128:
129: /*
130: * Change a numeric character string into two bcd digits.
131: */
132: int
133: bcd(s) register char *s;
134: {
135: if (('0' <= s[0]) && (s[0] <= '9') && ('0' <= s[1]) && (s[1] <= '9'))
136: return (s[0] << 4) | (s[1] & 15);
137: fatal("argument contains nondigit");
138: }
139:
140: /*
141: * Check the clkbuf[] for sanity.
142: */
143: void
144: clockcheck()
145: {
146: sanity(YEAR, 0, 99, "year");
147: sanity(MON, 1, 12, "month");
148: sanity(DAY, 1, 31, "day");
149: sanity(HOUR, 0, 23, "hour");
150: sanity(MIN, 0, 59, "minute");
151: sanity(SEC, 0, 59, "second");
152: }
153:
154: /*
155: * Cry and die.
156: */
157: void
158: fatal(args) char *args;
159: {
160: fprintf(stderr, "/etc/ATclock: %r\n", &args);
161: exit(1);
162: }
163:
164: /*
165: * Sanity check: make sure BCD clkbuf[i] is in the given range.
166: */
167: void
168: sanity(i, min, max, msg) register int i; int min, max; char *msg;
169: {
170: register int n;
171:
172: n = 10 * (clkbuf[i] >> 4) + (clkbuf[i] & 15);
173: if (n < min || n > max)
174: fatal("%s %d not in range %d to %d", msg, n, min, max);
175: }
176:
177: /*
178: * Set clkbuf[] according to the argument string.
179: */
180: void
181: set(s) register char *s;
182: {
183: register char *a;
184:
185: a = s + strlen(s);
186: if ((&a[-3] >= s) && (a[-3] == '.')) {
187: clkbuf[SEC] = bcd(a -= 2);
188: a--;
189: } else
190: clkbuf[SEC] = 0;
191: if (&a[-2] >= s)
192: clkbuf[MIN] = bcd(a -= 2);
193: if (&a[-2] >= s)
194: clkbuf[HOUR] = bcd(a -= 2);
195: if (&a[-2] >= s)
196: clkbuf[DAY] = bcd(a -= 2);
197: if (&a[-2] >= s)
198: clkbuf[MON] = bcd(a -= 2);
199: if (&a[-2] >= s)
200: clkbuf[YEAR] = bcd(a -= 2);
201: if (a != s)
202: usage();
203: clockcheck();
204: }
205:
206: /*
207: * Print a usage message and exit.
208: */
209: void
210: usage()
211: {
212: fprintf(stderr, USAGE);
213: exit(1);
214: }
215:
216: /* end of ATclock.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.