|
|
1.1 root 1: /*
2: * date.c
3: * Print and set the date.
4: */
5:
6: #include <stdio.h>
7: #include <ctype.h>
8: #include <sys/types.h>
9: #include <time.h>
10: #include <sys/timeb.h>
11:
12: #if COHERENT
13: #include <utmp.h>
14: #include <sys/stat.h>
15: #endif
16:
17: void error();
18: void usage();
19:
20: #define TFCFLAG 0 /* Truly French GMT is UTC */
21: int gmtflag; /* Do things in Greenwich Mean Time */
22: int sflag; /* Suppress DST conversion when setting */
23: struct tm *gtime();
24: struct timeb tb;
25: time_t timep[2];
26: #define MIN (60L)
27: #define HOUR (60L*60L)
28: #define DAY (60L*60L*24L)
29: #define APR 3
30: #define OCT 9
31:
32: #if COHERENT
33: struct utmp utmps[2];
34: char utmpf[] = "/usr/adm/wtmp";
35: struct stat sbuf;
36: char btimf[] = "/etc/boottime";
37: #endif
38:
39: /*
40: * Table of days per month.
41: * This will be adjusted for leap years.
42: */
43: char dpm[] = {
44: 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
45: };
46:
47: main(argc, argv)
48: char *argv[];
49: {
50: register char *s;
51: register struct tm *tmp;
52: long ltime;
53: char *tzone;
54:
55: if (argc>1 && *argv[1]=='-') {
56: if (argv[1][1]=='u' && argv[1][2]=='\0')
57: gmtflag = 1;
58: else if (argv[1][1]=='s' && argv[1][2]=='\0')
59: sflag = 1;
60: else
61: usage();
62: argc--;
63: argv++;
64: }
65: if (argc > 2)
66: usage();
67: if (argc > 1)
68: sdate(argv[1]);
69: ftime(&tb);
70: ltime = tb.time;
71: s = asctime(tmp = gtime(<ime));
72: s[24] = '\0';
73: if (!gmtflag)
74: tzone = tzname[tmp->tm_isdst];
75: else
76: tzone = TFCFLAG ? "UTC" : "GMT";
77: printf("%s %s\n", s, tzone);
78: exit(0);
79: }
80:
81: /*
82: * Set the date/time based on
83: * string 's'.
84: */
85: sdate(s)
86: char *s;
87: {
88: register char *sp;
89: register int year;
90: register int month;
91: int status;
92: #if COHERENT
93: int ufd;
94: #endif
95: long ltime;
96: struct tm *tmp;
97:
98: ftime(&tb);
99: ltime = tb.time;
100: #if COHERENT
101: utmps[0].ut_time = ltime;
102: #endif
103: tmp = gtime(<ime);
104: for (sp = s; *sp != '\0'; sp++)
105: ;
106: if ((sp -= 2) < s)
107: usage();
108: if (sp>s && sp[-1]=='.') {
109: tmp->tm_sec = convert(sp, 60, s);
110: sp--;
111: } else {
112: sp += 2;
113: tmp->tm_sec = 0;
114: }
115: tmp->tm_min = convert(sp-=2, 60, s);
116: tmp->tm_hour = convert(sp-=2, 24, s);
117: if ((sp-=2) >= s) {
118: tmp->tm_mday = convert(sp, 31+1, s);
119: if ((sp-=2) >= s) {
120: tmp->tm_mon = convert(sp, 12+1, s) - 1;
121: if ((sp-=2) >= s)
122: tmp->tm_year = convert(sp, 100, s);
123: }
124: }
125: if (tmp->tm_mday > dpm[tmp->tm_mon])
126: usage();
127: /*
128: * Convert using the year, month, day, hour, minute,
129: * and second values in the 'tm' structure.
130: * When all is completed, take care of timezone.
131: */
132: ltime = tmp->tm_sec + MIN*tmp->tm_min + HOUR*tmp->tm_hour;
133: ltime += (tmp->tm_mday-1) * DAY;
134: year = 1900 + tmp->tm_year;
135: /*
136: * Adjust length of February in leap years.
137: */
138: if (!isleap(year))
139: dpm[1] = 28;
140: month = tmp->tm_mon;
141: while (--month >= 0)
142: ltime += dpm[month] * DAY;
143: while (--year >= 1970)
144: ltime += (long)DAY * (isleap(year) ? 366 : 365);
145: if (!gmtflag) {
146: ltime += timezone;
147: tmp = localtime(<ime);
148: if (!sflag && tmp->tm_isdst)
149: ltime -= HOUR;
150: }
151: status = stime(<ime);
152: if (status < 0) {
153: #if COHERENT
154: error("no permission");
155: #else
156: error("bad date");
157: #endif
158: return;
159: }
160:
161: #if COHERENT
162: /* Correct the modtime of /etc/boottime */
163: stat(btimf, &sbuf);
164: timep[0] = ltime - utmps[0].ut_time + sbuf.st_mtime;
165: timep[1] = timep[0];
166: utime(btimf, timep);
167:
168: /* Note the change of time in /usr/adm/wtmp */
169: utmps[1].ut_time = ltime;
170: utmps[0].ut_line[0] = '|';
171: utmps[1].ut_line[0] = '}';
172: if ((ufd = open(utmpf, 1)) >= 0) {
173: lseek(ufd, 0L, 2);
174: write(ufd, utmps, sizeof (utmps));
175: close(ufd);
176: }
177: #endif
178: }
179:
180: /*
181: * Return 1 on leap years.
182: */
183: isleap(yr)
184: register yr;
185: {
186: if (yr%4000 == 0)
187: return (0);
188: if (yr%400==0 || (yr%100!=0 && yr%4==0))
189: return (1);
190: return (0);
191: }
192:
193: /*
194: * Convert a piece of the time.
195: * The pointer cp should never fall before
196: * beg and the two digits parsed should be
197: * less than max.
198: */
199: convert(cp, max, beg)
200: register char *cp;
201: char *beg;
202: {
203: register val;
204:
205: if (cp<beg || !isdigit(cp[0]) || !isdigit(cp[1]))
206: usage();
207: val = (cp[0]-'0')*10 + cp[1]-'0';
208: if (val >= max)
209: usage();
210: return (val);
211: }
212:
213: /*
214: * Return either local time or Greenwich
215: * Mean 'tm' in a 'tm' structure.
216: */
217: struct tm *
218: gtime(tp)
219: register time_t *tp;
220: {
221: return (gmtflag ? gmtime(tp) : localtime(tp));
222: }
223:
224: void
225: usage()
226: {
227: fprintf(stderr, "Usage: date [-u] [yymmddhhmm[.ss]]\n");
228: exit(1);
229: }
230:
231: void
232: error(x)
233: {
234: fprintf(stderr, "date: %r\n", &x);
235: exit(1);
236: }
237:
238: /* end of date.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.