date.c revision 1.20
1219820Sjeff/*	$NetBSD: date.c,v 1.20 1998/01/20 22:06:02 mycroft Exp $	*/
2219820Sjeff
3219820Sjeff/*
4219820Sjeff * Copyright (c) 1985, 1987, 1988, 1993
5219820Sjeff *	The Regents of the University of California.  All rights reserved.
6219820Sjeff *
7219820Sjeff * Redistribution and use in source and binary forms, with or without
8219820Sjeff * modification, are permitted provided that the following conditions
9219820Sjeff * are met:
10219820Sjeff * 1. Redistributions of source code must retain the above copyright
11219820Sjeff *    notice, this list of conditions and the following disclaimer.
12219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright
13219820Sjeff *    notice, this list of conditions and the following disclaimer in the
14219820Sjeff *    documentation and/or other materials provided with the distribution.
15219820Sjeff * 3. All advertising materials mentioning features or use of this software
16219820Sjeff *    must display the following acknowledgement:
17219820Sjeff *	This product includes software developed by the University of
18219820Sjeff *	California, Berkeley and its contributors.
19219820Sjeff * 4. Neither the name of the University nor the names of its contributors
20219820Sjeff *    may be used to endorse or promote products derived from this software
21219820Sjeff *    without specific prior written permission.
22219820Sjeff *
23219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24219820Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25219820Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26219820Sjeff * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27219820Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28219820Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29219820Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30219820Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31219820Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32219820Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33219820Sjeff * SUCH DAMAGE.
34219820Sjeff */
35219820Sjeff
36219820Sjeff#include <sys/cdefs.h>
37219820Sjeff#ifndef lint
38219820Sjeff__COPYRIGHT(
39219820Sjeff"@(#) Copyright (c) 1985, 1987, 1988, 1993\n\
40219820Sjeff	The Regents of the University of California.  All rights reserved.\n");
41219820Sjeff#endif /* not lint */
42219820Sjeff
43219820Sjeff#ifndef lint
44219820Sjeff#if 0
45219820Sjeffstatic char sccsid[] = "@(#)date.c	8.2 (Berkeley) 4/28/95";
46219820Sjeff#else
47219820Sjeff__RCSID("$NetBSD: date.c,v 1.20 1998/01/20 22:06:02 mycroft Exp $");
48219820Sjeff#endif
49219820Sjeff#endif /* not lint */
50219820Sjeff
51219820Sjeff#include <sys/param.h>
52219820Sjeff#include <sys/time.h>
53219820Sjeff
54219820Sjeff#include <ctype.h>
55219820Sjeff#include <err.h>
56219820Sjeff#include <fcntl.h>
57219820Sjeff#include <stdio.h>
58219820Sjeff#include <stdlib.h>
59219820Sjeff#include <string.h>
60219820Sjeff#include <locale.h>
61219820Sjeff#include <syslog.h>
62219820Sjeff#include <tzfile.h>
63219820Sjeff#include <unistd.h>
64219820Sjeff#include <util.h>
65219820Sjeff
66219820Sjeff#include "extern.h"
67219820Sjeff
68219820Sjefftime_t tval;
69219820Sjeffint retval, nflag;
70219820Sjeff
71219820Sjeffint main __P((int, char *[]));
72219820Sjeffstatic void setthetime __P((char *));
73219820Sjeffstatic void badformat __P((void));
74219820Sjeffstatic void usage __P((void));
75219820Sjeff
76219820Sjeffint
77219820Sjeffmain(argc, argv)
78219820Sjeff	int argc;
79219820Sjeff	char *argv[];
80219820Sjeff{
81219820Sjeff	extern int optind;
82219820Sjeff	extern char *optarg;
83219820Sjeff	int ch, rflag;
84219820Sjeff	char *format, buf[1024];
85219820Sjeff
86219820Sjeff	(void)setlocale(LC_ALL, "");
87219820Sjeff
88219820Sjeff	rflag = 0;
89219820Sjeff	while ((ch = getopt(argc, argv, "nr:u")) != -1)
90219820Sjeff		switch((char)ch) {
91219820Sjeff		case 'n':		/* don't set network */
92219820Sjeff			nflag = 1;
93219820Sjeff			break;
94219820Sjeff		case 'r':		/* user specified seconds */
95219820Sjeff			rflag = 1;
96219820Sjeff			tval = atol(optarg);
97219820Sjeff			break;
98219820Sjeff		case 'u':		/* do everything in GMT */
99219820Sjeff			(void)setenv("TZ", "GMT0", 1);
100219820Sjeff			break;
101219820Sjeff		default:
102219820Sjeff			usage();
103219820Sjeff		}
104219820Sjeff	argc -= optind;
105219820Sjeff	argv += optind;
106219820Sjeff
107219820Sjeff	if (!rflag && time(&tval) == -1)
108219820Sjeff		err(1, "time");
109219820Sjeff
110219820Sjeff	format = "%a %b %e %H:%M:%S %Z %Y";
111219820Sjeff
112219820Sjeff	/* allow the operands in any order */
113219820Sjeff	if (*argv && **argv == '+') {
114219820Sjeff		format = *argv + 1;
115219820Sjeff		++argv;
116219820Sjeff	}
117219820Sjeff
118219820Sjeff	if (*argv) {
119219820Sjeff		setthetime(*argv);
120219820Sjeff		++argv;
121219820Sjeff	}
122219820Sjeff
123219820Sjeff	if (*argv && **argv == '+')
124219820Sjeff		format = *argv + 1;
125219820Sjeff
126219820Sjeff	(void)strftime(buf, sizeof(buf), format, localtime(&tval));
127219820Sjeff	(void)printf("%s\n", buf);
128219820Sjeff	exit(retval);
129219820Sjeff	/* NOTREACHED */
130219820Sjeff}
131219820Sjeff
132219820Sjeff#define	ATOI2(ar)	((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
133219820Sjeffvoid
134219820Sjeffsetthetime(p)
135219820Sjeff	char *p;
136219820Sjeff{
137219820Sjeff	struct tm *lt;
138219820Sjeff	struct timeval tv;
139219820Sjeff	char *dot, *t;
140219820Sjeff	int yearset;
141219820Sjeff
142219820Sjeff	for (t = p, dot = NULL; *t; ++t) {
143219820Sjeff		if (isdigit(*t))
144219820Sjeff			continue;
145219820Sjeff		if (*t == '.' && dot == NULL) {
146219820Sjeff			dot = t;
147219820Sjeff			continue;
148219820Sjeff		}
149219820Sjeff		badformat();
150219820Sjeff	}
151219820Sjeff
152219820Sjeff	lt = localtime(&tval);
153219820Sjeff
154219820Sjeff	if (dot != NULL) {			/* .ss */
155219820Sjeff		*dot++ = '\0';
156219820Sjeff		if (strlen(dot) != 2)
157219820Sjeff			badformat();
158219820Sjeff		lt->tm_sec = ATOI2(dot);
159219820Sjeff	} else
160219820Sjeff		lt->tm_sec = 0;
161219820Sjeff
162219820Sjeff	yearset = 0;
163219820Sjeff	switch (strlen(p)) {
164219820Sjeff	case 12:
165219820Sjeff		lt->tm_year = ATOI2(p);
166219820Sjeff		lt->tm_year *= 100;
167219820Sjeff		yearset = 1;
168219820Sjeff		/* FALLTHROUGH */
169219820Sjeff	case 10:				/* yy */
170219820Sjeff		if (yearset) {
171219820Sjeff			yearset = ATOI2(p);
172219820Sjeff			lt->tm_year += yearset;
173219820Sjeff		} else {
174219820Sjeff			yearset = ATOI2(p);
175219820Sjeff			if (yearset < 69)		/* hack for 2000 ;-} */
176219820Sjeff				lt->tm_year = yearset + 2000;
177219820Sjeff			else
178219820Sjeff				lt->tm_year = yearset + 1900;
179219820Sjeff		}
180219820Sjeff		lt->tm_year -= TM_YEAR_BASE;
181219820Sjeff		/* FALLTHROUGH */
182219820Sjeff	case 8:					/* mm */
183219820Sjeff		lt->tm_mon = ATOI2(p);
184219820Sjeff		--lt->tm_mon;			/* time struct is 0 - 11 */
185219820Sjeff		/* FALLTHROUGH */
186219820Sjeff	case 6:					/* dd */
187219820Sjeff		lt->tm_mday = ATOI2(p);
188219820Sjeff		/* FALLTHROUGH */
189219820Sjeff	case 4:					/* hh */
190219820Sjeff		lt->tm_hour = ATOI2(p);
191219820Sjeff		/* FALLTHROUGH */
192219820Sjeff	case 2:					/* mm */
193219820Sjeff		lt->tm_min = ATOI2(p);
194219820Sjeff		break;
195219820Sjeff	default:
196219820Sjeff		badformat();
197219820Sjeff	}
198219820Sjeff
199219820Sjeff	/* convert broken-down time to GMT clock time */
200219820Sjeff	if ((tval = mktime(lt)) == -1)
201219820Sjeff		badformat();
202219820Sjeff
203219820Sjeff	/* set the time */
204219820Sjeff	if (nflag || netsettime(tval)) {
205219820Sjeff		logwtmp("|", "date", "");
206219820Sjeff		tv.tv_sec = tval;
207219820Sjeff		tv.tv_usec = 0;
208219820Sjeff		if (settimeofday(&tv, NULL)) {
209219820Sjeff			perror("date: settimeofday");
210219820Sjeff			exit(1);
211219820Sjeff		}
212219820Sjeff		logwtmp("{", "date", "");
213219820Sjeff	}
214219820Sjeff
215219820Sjeff	if ((p = getlogin()) == NULL)
216219820Sjeff		p = "???";
217219820Sjeff	syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
218219820Sjeff}
219219820Sjeff
220219820Sjeffstatic void
221219820Sjeffbadformat()
222219820Sjeff{
223219820Sjeff	warnx("illegal time format");
224219820Sjeff	usage();
225219820Sjeff}
226219820Sjeff
227219820Sjeffstatic void
228219820Sjeffusage()
229219820Sjeff{
230219820Sjeff	(void)fprintf(stderr,
231219820Sjeff	    "usage: date [-nu] [-r seconds] [+format]\n");
232219820Sjeff	(void)fprintf(stderr, "       date [[[[[cc]yy]mm]dd]hh]mm[.ss]\n");
233219820Sjeff	exit(1);
234219820Sjeff}
235219820Sjeff