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