xref: /original-bsd/bin/date/date.c (revision 8bb6539f)
1 /*
2  * Copyright (c) 1985, 1987, 1988 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1985, 1987, 1988 The Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)date.c	5.8 (Berkeley) 03/20/92";
16 #endif /* not lint */
17 
18 #include <sys/param.h>
19 #include <sys/time.h>
20 #include <sys/file.h>
21 #include <syslog.h>
22 #include <unistd.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 
28 time_t tval;
29 int retval, nflag;
30 
31 main(argc, argv)
32 	int argc;
33 	char **argv;
34 {
35 	extern int optind;
36 	extern char *optarg;
37 	struct timezone tz;
38 	int ch, rflag;
39 	char *format, buf[1024];
40 
41 	tz.tz_dsttime = tz.tz_minuteswest = 0;
42 	rflag = 0;
43 	while ((ch = getopt(argc, argv, "d:nr:ut:")) != EOF)
44 		switch((char)ch) {
45 		case 'd':		/* daylight savings time */
46 			tz.tz_dsttime = atoi(optarg) ? 1 : 0;
47 			break;
48 		case 'n':		/* don't set network */
49 			nflag = 1;
50 			break;
51 		case 'r':		/* user specified seconds */
52 			rflag = 1;
53 			tval = atol(optarg);
54 			break;
55 		case 'u':		/* do everything in GMT */
56 			(void)setenv("TZ", "GMT0", 1);
57 			break;
58 		case 't':		/* minutes west of GMT */
59 					/* error check; don't allow "PST" */
60 			if (isdigit(*optarg)) {
61 				tz.tz_minuteswest = atoi(optarg);
62 				break;
63 			}
64 			/* FALLTHROUGH */
65 		default:
66 			usage();
67 		}
68 	argc -= optind;
69 	argv += optind;
70 
71 	/*
72 	 * If -d or -t, set the timezone or daylight savings time; this
73 	 * doesn't belong here, there kernel should not know about either.
74 	 */
75 	if ((tz.tz_minuteswest || tz.tz_dsttime) &&
76 	    settimeofday(NULL, &tz)) {
77 		perror("date: settimeofday");
78 		exit(1);
79 	}
80 
81 	if (!rflag && time(&tval) == -1) {
82 		perror("date: time");
83 		exit(1);
84 	}
85 
86 	format = "%a %b %e %H:%M:%S %Z %Y\n";
87 
88 	/* allow the operands in any order */
89 	if (*argv && **argv == '+') {
90 		format = *argv + 1;
91 		++argv;
92 	}
93 
94 	if (*argv) {
95 		setthetime(*argv);
96 		++argv;
97 	}
98 
99 	if (*argv && **argv == '+')
100 		format = *argv + 1;
101 
102 	(void)strftime(buf, sizeof(buf), format, localtime(&tval));
103 	(void)printf("%s", buf);
104 	exit(retval);
105 }
106 
107 #define	ATOI2(ar)	((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
108 setthetime(p)
109 	register char *p;
110 {
111 	register struct tm *lt;
112 	struct timeval tv;
113 	char *dot, *t;
114 
115 	for (t = p, dot = NULL; *t; ++t) {
116 		if (isdigit(*t))
117 			continue;
118 		if (*t == '.' && dot == NULL) {
119 			dot = t;
120 			continue;
121 		}
122 		badformat();
123 	}
124 
125 	lt = localtime(&tval);
126 
127 	if (dot != NULL) {			/* .ss */
128 		*dot++ = '\0';
129 		if (strlen(dot) != 2)
130 			badformat();
131 		lt->tm_sec = ATOI2(dot);
132 		if (lt->tm_sec > 61)
133 			badformat();
134 	} else
135 		lt->tm_sec = 0;
136 
137 	switch (strlen(p)) {
138 	case 10:				/* yy */
139 		lt->tm_year = ATOI2(p);
140 		if (lt->tm_year < 69)		/* hack for 2000 ;-} */
141 			lt->tm_year += 100;
142 		/* FALLTHROUGH */
143 	case 8:					/* mm */
144 		lt->tm_mon = ATOI2(p);
145 		if (lt->tm_mon > 12)
146 			badformat();
147 		--lt->tm_mon;			/* time struct is 0 - 11 */
148 		/* FALLTHROUGH */
149 	case 6:					/* dd */
150 		lt->tm_mday = ATOI2(p);
151 		if (lt->tm_mday > 31)
152 			badformat();
153 		/* FALLTHROUGH */
154 	case 4:					/* hh */
155 		lt->tm_hour = ATOI2(p);
156 		if (lt->tm_hour > 23)
157 			badformat();
158 		/* FALLTHROUGH */
159 	case 2:					/* mm */
160 		lt->tm_min = ATOI2(p);
161 		if (lt->tm_min > 59)
162 			badformat();
163 		break;
164 	default:
165 		badformat();
166 	}
167 
168 	/* convert broken-down time to GMT clock time */
169 	if ((tval = mktime(lt)) == -1)
170 		badformat();
171 
172 	/* set the time */
173 	if (nflag || netsettime(tval)) {
174 		logwtmp("|", "date", "");
175 		tv.tv_sec = tval;
176 		tv.tv_usec = 0;
177 		if (settimeofday(&tv, NULL)) {
178 			perror("date: settimeofday");
179 			exit(1);
180 		}
181 		logwtmp("{", "date", "");
182 	}
183 
184 	if ((p = getlogin()) == NULL)
185 		p = "???";
186 	syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
187 }
188 
189 badformat()
190 {
191 	(void)fprintf(stderr, "date: illegal time format.\n");
192 	usage();
193 }
194 
195 usage()
196 {
197 	(void)fprintf(stderr,
198 	    "usage: date [-nu] [-d dst] [-r seconds] [-t west] [+format]\n");
199 	(void)fprintf(stderr, "            [yy[mm[dd[hh]]]]mm[.ss]]\n");
200 	exit(1);
201 }
202