xref: /original-bsd/bin/date/date.c (revision e59fb703)
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.6 (Berkeley) 10/17/91";
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 	int dot;
114 	char *t;
115 
116 	for (t = p, dot = 0; *t; ++t)
117 		if (!isdigit(*t) && (*t != '.' || dot++))
118 			badformat();
119 
120 	lt = localtime(&tval);
121 
122 	if (t = index(p, '.')) {		/* .ss */
123 		*t++ = '\0';
124 		if (lt->tm_sec > 61)
125 			badformat();
126 	} else
127 		lt->tm_sec = 0;
128 
129 	for (t = p; *t; ++t)
130 		if (!isdigit(*t))
131 			badformat();
132 
133 	switch (strlen(p)) {
134 	case 10:				/* yy */
135 		lt->tm_year = ATOI2(p);
136 		if (lt->tm_year < 69)		/* hack for 2000 ;-} */
137 			lt->tm_year += 100;
138 		/* FALLTHROUGH */
139 	case 8:					/* mm */
140 		lt->tm_mon = ATOI2(p);
141 		if (lt->tm_mon > 12)
142 			badformat();
143 		--lt->tm_mon;			/* time struct is 0 - 11 */
144 		/* FALLTHROUGH */
145 	case 6:					/* dd */
146 		lt->tm_mday = ATOI2(p);
147 		if (lt->tm_mday > 31)
148 			badformat();
149 		/* FALLTHROUGH */
150 	case 4:					/* hh */
151 		lt->tm_hour = ATOI2(p);
152 		if (lt->tm_hour > 23)
153 			badformat();
154 		/* FALLTHROUGH */
155 	case 2:					/* mm */
156 		lt->tm_min = ATOI2(p);
157 		if (lt->tm_min > 59)
158 			badformat();
159 		break;
160 	default:
161 		badformat();
162 	}
163 
164 	/* convert broken-down time to GMT clock time */
165 	if ((tval = mktime(lt)) == -1)
166 		badformat();
167 
168 	/* set the time */
169 	if (nflag || netsettime(tval)) {
170 		logwtmp("|", "date", "");
171 		tv.tv_sec = tval;
172 		tv.tv_usec = 0;
173 		if (settimeofday(&tv, NULL)) {
174 			perror("date: settimeofday");
175 			exit(1);
176 		}
177 		logwtmp("{", "date", "");
178 	}
179 
180 	if ((p = getlogin()) == NULL)
181 		p = "???";
182 	syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
183 }
184 
185 badformat()
186 {
187 	(void)fprintf(stderr, "date: illegal time format.\n");
188 	usage();
189 }
190 
191 usage()
192 {
193 	(void)fprintf(stderr,
194 	    "usage: date [-nu] [-d dst] [-r seconds] [-t west] [+format]\n");
195 	(void)fprintf(stderr, "            [yy[mm[dd[hh]]]]mm[.ss]]\n");
196 	exit(1);
197 }
198