xref: /original-bsd/bin/date/date.c (revision 331bfa8d)
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.2 (Berkeley) 02/25/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;
39 	char *format, buf[1024];
40 
41 	tz.tz_dsttime = tz.tz_minuteswest = 0;
42 	while ((ch = getopt(argc, argv, "d:nut:")) != EOF)
43 		switch((char)ch) {
44 		case 'd':		/* daylight savings time */
45 			tz.tz_dsttime = atoi(optarg) ? 1 : 0;
46 			break;
47 		case 'n':		/* don't set network */
48 			nflag = 1;
49 			break;
50 		case 'u':		/* do everything in GMT */
51 			(void)setenv("TZ", "GMT", 1);
52 			break;
53 		case 't':		/* minutes west of GMT */
54 					/* error check; don't allow "PST" */
55 			if (isdigit(*optarg)) {
56 				tz.tz_minuteswest = atoi(optarg);
57 				break;
58 			}
59 			/* FALLTHROUGH */
60 		default:
61 			usage();
62 		}
63 	argc -= optind;
64 	argv += optind;
65 
66 	/*
67 	 * If -d or -t, set the timezone or daylight savings time; this
68 	 * doesn't belong here, there kernel should not know about either.
69 	 */
70 	if ((tz.tz_minuteswest || tz.tz_dsttime) &&
71 	    settimeofday((struct timeval *)NULL, &tz)) {
72 		perror("date: settimeofday");
73 		exit(1);
74 	}
75 
76 	if (time(&tval) == (time_t)-1) {
77 		perror("date: time");
78 		exit(1);
79 	}
80 
81 	format = "%a %b %e %H:%M:%S %Z %Y\n";
82 
83 	/* allow the operands in any order */
84 	if (*argv && **argv == '+') {
85 		format = *argv + 1;
86 		++argv;
87 	}
88 
89 	if (*argv) {
90 		setthetime(*argv);
91 		++argv;
92 	}
93 
94 	if (*argv && **argv == '+')
95 		format = *argv + 1;
96 
97 	(void)strftime(buf, sizeof(buf), format, localtime(&tval));
98 	(void)printf("%s", buf);
99 	exit(retval);
100 }
101 
102 #define	ATOI2(ar)	((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
103 setthetime(p)
104 	register char *p;
105 {
106 	register struct tm *lt;
107 	struct timeval tv;
108 	int dot;
109 	char *t;
110 
111 	for (t = p, dot = 0; *t; ++t)
112 		if (!isdigit(*t) && (*t != '.' || dot++))
113 			badformat();
114 
115 	lt = localtime(&tval);
116 
117 	if (t = index(p, '.')) {		/* .ss */
118 		*t++ = '\0';
119 		if (lt->tm_sec > 61)
120 			badformat();
121 	} else
122 		lt->tm_sec = 0;
123 
124 	for (t = p; *t; ++t)
125 		if (!isdigit(*t))
126 			badformat();
127 
128 	switch (strlen(p)) {
129 	case 10:				/* yy */
130 		lt->tm_year = ATOI2(p);
131 		if (lt->tm_year < 69)		/* hack for 2000 ;-} */
132 			lt->tm_year += 100;
133 		/* FALLTHROUGH */
134 	case 8:					/* mm */
135 		lt->tm_mon = ATOI2(p);
136 		if (lt->tm_mon > 12)
137 			badformat();
138 		--lt->tm_mon;			/* time struct is 0 - 11 */
139 		/* FALLTHROUGH */
140 	case 6:					/* dd */
141 		lt->tm_mday = ATOI2(p);
142 		if (lt->tm_mday > 31)
143 			badformat();
144 		/* FALLTHROUGH */
145 	case 4:					/* hh */
146 		lt->tm_hour = ATOI2(p);
147 		if (lt->tm_hour > 23)
148 			badformat();
149 		/* FALLTHROUGH */
150 	case 2:					/* mm */
151 		lt->tm_min = ATOI2(p);
152 		if (lt->tm_min > 59)
153 			badformat();
154 		break;
155 	default:
156 		badformat();
157 	}
158 
159 	/* convert broken-down time to GMT clock time */
160 	if ((tval = mktime(lt)) == -1)
161 		badformat();
162 
163 	if (!(p = getlogin()))			/* single-user or no tty */
164 		p = "root";
165 	syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
166 
167 	/* set the time */
168 	if (nflag || netsettime(tval)) {
169 		logwtmp("|", "date", "");
170 		tv.tv_sec = tval;
171 		tv.tv_usec = 0;
172 		if (settimeofday(&tv, (struct timezone *)NULL)) {
173 			perror("date: settimeofday");
174 			exit(1);
175 		}
176 		logwtmp("{", "date", "");
177 	}
178 }
179 
180 badformat()
181 {
182 	(void)fprintf(stderr, "date: illegal time format.\n");
183 	usage();
184 }
185 
186 usage()
187 {
188 	(void)fprintf(stderr,
189 "usage: date [-nu] [-d dst] [-t west] [+format] [yy[mm[dd[hh]]]]mm[.ss]]\n");
190 	exit(1);
191 }
192