|
|
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.