date.c revision 15068
11556Srgrimes/* 21556Srgrimes * Copyright (c) 1985, 1987, 1988, 1993 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * Redistribution and use in source and binary forms, with or without 61556Srgrimes * modification, are permitted provided that the following conditions 71556Srgrimes * are met: 81556Srgrimes * 1. Redistributions of source code must retain the above copyright 91556Srgrimes * notice, this list of conditions and the following disclaimer. 101556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111556Srgrimes * notice, this list of conditions and the following disclaimer in the 121556Srgrimes * documentation and/or other materials provided with the distribution. 131556Srgrimes * 3. All advertising materials mentioning features or use of this software 141556Srgrimes * must display the following acknowledgement: 151556Srgrimes * This product includes software developed by the University of 161556Srgrimes * California, Berkeley and its contributors. 171556Srgrimes * 4. Neither the name of the University nor the names of its contributors 181556Srgrimes * may be used to endorse or promote products derived from this software 191556Srgrimes * without specific prior written permission. 201556Srgrimes * 211556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311556Srgrimes * SUCH DAMAGE. 323044Sdg * 3315068Sache * $Id: date.c,v 1.6 1995/10/23 20:26:53 ache Exp $ 341556Srgrimes */ 351556Srgrimes 361556Srgrimes#ifndef lint 371556Srgrimesstatic char copyright[] = 381556Srgrimes"@(#) Copyright (c) 1985, 1987, 1988, 1993\n\ 391556Srgrimes The Regents of the University of California. All rights reserved.\n"; 401556Srgrimes#endif /* not lint */ 411556Srgrimes 421556Srgrimes#ifndef lint 431556Srgrimesstatic char sccsid[] = "@(#)date.c 8.1 (Berkeley) 5/31/93"; 441556Srgrimes#endif /* not lint */ 451556Srgrimes 461556Srgrimes#include <sys/param.h> 471556Srgrimes#include <sys/time.h> 481556Srgrimes 491556Srgrimes#include <ctype.h> 501556Srgrimes#include <err.h> 511556Srgrimes#include <fcntl.h> 521556Srgrimes#include <stdio.h> 531556Srgrimes#include <stdlib.h> 541556Srgrimes#include <string.h> 551556Srgrimes#include <syslog.h> 561556Srgrimes#include <unistd.h> 5711738Sache#include <locale.h> 581556Srgrimes 591556Srgrimes#include "extern.h" 601556Srgrimes 611556Srgrimestime_t tval; 621556Srgrimesint retval, nflag; 631556Srgrimes 641556Srgrimesstatic void setthetime __P((char *)); 651556Srgrimesstatic void badformat __P((void)); 661556Srgrimesstatic void usage __P((void)); 671556Srgrimes 681556Srgrimesint logwtmp __P((char *, char *, char *)); 691556Srgrimes 701556Srgrimesint 711556Srgrimesmain(argc, argv) 721556Srgrimes int argc; 731556Srgrimes char **argv; 741556Srgrimes{ 751556Srgrimes extern int optind; 761556Srgrimes extern char *optarg; 771556Srgrimes struct timezone tz; 781556Srgrimes int ch, rflag; 791556Srgrimes char *format, buf[1024]; 805233Sbde char *endptr; 815233Sbde int set_timezone; 821556Srgrimes 8311738Sache (void) setlocale(LC_TIME, ""); 841556Srgrimes tz.tz_dsttime = tz.tz_minuteswest = 0; 851556Srgrimes rflag = 0; 865233Sbde set_timezone = 0; 871556Srgrimes while ((ch = getopt(argc, argv, "d:nr:ut:")) != EOF) 881556Srgrimes switch((char)ch) { 891556Srgrimes case 'd': /* daylight savings time */ 905233Sbde tz.tz_dsttime = strtol(optarg, &endptr, 10) ? 1 : 0; 915233Sbde if (endptr == optarg || *endptr != '\0') 925233Sbde usage(); 935233Sbde set_timezone = 1; 941556Srgrimes break; 951556Srgrimes case 'n': /* don't set network */ 961556Srgrimes nflag = 1; 971556Srgrimes break; 981556Srgrimes case 'r': /* user specified seconds */ 991556Srgrimes rflag = 1; 1001556Srgrimes tval = atol(optarg); 1011556Srgrimes break; 1021556Srgrimes case 'u': /* do everything in GMT */ 1031556Srgrimes (void)setenv("TZ", "GMT0", 1); 1041556Srgrimes break; 1051556Srgrimes case 't': /* minutes west of GMT */ 1061556Srgrimes /* error check; don't allow "PST" */ 1075233Sbde tz.tz_minuteswest = strtol(optarg, &endptr, 10); 1085233Sbde if (endptr == optarg || *endptr != '\0') 1095233Sbde usage(); 1105233Sbde set_timezone = 1; 1115233Sbde break; 1121556Srgrimes default: 1131556Srgrimes usage(); 1141556Srgrimes } 1151556Srgrimes argc -= optind; 1161556Srgrimes argv += optind; 1171556Srgrimes 1181556Srgrimes /* 1191556Srgrimes * If -d or -t, set the timezone or daylight savings time; this 1201556Srgrimes * doesn't belong here, there kernel should not know about either. 1211556Srgrimes */ 1225233Sbde if (set_timezone && settimeofday((struct timeval *)NULL, &tz)) 1235233Sbde err(1, "settimeofday (timezone)"); 1241556Srgrimes 1251556Srgrimes if (!rflag && time(&tval) == -1) 1261556Srgrimes err(1, "time"); 1271556Srgrimes 1289944Sache format = "%+"; 1291556Srgrimes 1301556Srgrimes /* allow the operands in any order */ 1311556Srgrimes if (*argv && **argv == '+') { 1321556Srgrimes format = *argv + 1; 1331556Srgrimes ++argv; 1341556Srgrimes } 1351556Srgrimes 1361556Srgrimes if (*argv) { 1371556Srgrimes setthetime(*argv); 1381556Srgrimes ++argv; 1391556Srgrimes } 1401556Srgrimes 1411556Srgrimes if (*argv && **argv == '+') 1421556Srgrimes format = *argv + 1; 1431556Srgrimes 1441556Srgrimes (void)strftime(buf, sizeof(buf), format, localtime(&tval)); 1457608Sjoerg (void)printf("%s\n", buf); 1461556Srgrimes exit(retval); 1471556Srgrimes} 1481556Srgrimes 1491556Srgrimes#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2; 1501556Srgrimesvoid 1511556Srgrimessetthetime(p) 1521556Srgrimes register char *p; 1531556Srgrimes{ 1541556Srgrimes register struct tm *lt; 1551556Srgrimes struct timeval tv; 1561556Srgrimes char *dot, *t; 1571556Srgrimes 1581556Srgrimes for (t = p, dot = NULL; *t; ++t) { 1591556Srgrimes if (isdigit(*t)) 1601556Srgrimes continue; 1611556Srgrimes if (*t == '.' && dot == NULL) { 1621556Srgrimes dot = t; 1631556Srgrimes continue; 1641556Srgrimes } 1651556Srgrimes badformat(); 1661556Srgrimes } 1671556Srgrimes 1681556Srgrimes lt = localtime(&tval); 1691556Srgrimes 1701556Srgrimes if (dot != NULL) { /* .ss */ 1711556Srgrimes *dot++ = '\0'; 1721556Srgrimes if (strlen(dot) != 2) 1731556Srgrimes badformat(); 1741556Srgrimes lt->tm_sec = ATOI2(dot); 1751556Srgrimes if (lt->tm_sec > 61) 1761556Srgrimes badformat(); 1771556Srgrimes } else 1781556Srgrimes lt->tm_sec = 0; 1791556Srgrimes 1801556Srgrimes switch (strlen(p)) { 1811556Srgrimes case 10: /* yy */ 1821556Srgrimes lt->tm_year = ATOI2(p); 1831556Srgrimes if (lt->tm_year < 69) /* hack for 2000 ;-} */ 1841556Srgrimes lt->tm_year += 100; 1851556Srgrimes /* FALLTHROUGH */ 1861556Srgrimes case 8: /* mm */ 1871556Srgrimes lt->tm_mon = ATOI2(p); 1881556Srgrimes if (lt->tm_mon > 12) 1891556Srgrimes badformat(); 1901556Srgrimes --lt->tm_mon; /* time struct is 0 - 11 */ 1911556Srgrimes /* FALLTHROUGH */ 1921556Srgrimes case 6: /* dd */ 1931556Srgrimes lt->tm_mday = ATOI2(p); 1941556Srgrimes if (lt->tm_mday > 31) 1951556Srgrimes badformat(); 1961556Srgrimes /* FALLTHROUGH */ 1971556Srgrimes case 4: /* hh */ 1981556Srgrimes lt->tm_hour = ATOI2(p); 1991556Srgrimes if (lt->tm_hour > 23) 2001556Srgrimes badformat(); 2011556Srgrimes /* FALLTHROUGH */ 2021556Srgrimes case 2: /* mm */ 2031556Srgrimes lt->tm_min = ATOI2(p); 2041556Srgrimes if (lt->tm_min > 59) 2051556Srgrimes badformat(); 2061556Srgrimes break; 2071556Srgrimes default: 2081556Srgrimes badformat(); 2091556Srgrimes } 2101556Srgrimes 2111556Srgrimes /* convert broken-down time to GMT clock time */ 2121556Srgrimes if ((tval = mktime(lt)) == -1) 21315068Sache errx(1, "nonexistent time"); 2141556Srgrimes 2151556Srgrimes /* set the time */ 2161556Srgrimes if (nflag || netsettime(tval)) { 2171556Srgrimes logwtmp("|", "date", ""); 2181556Srgrimes tv.tv_sec = tval; 2191556Srgrimes tv.tv_usec = 0; 2205233Sbde if (settimeofday(&tv, (struct timezone *)NULL)) 2215233Sbde err(1, "settimeofday (timeval)"); 2221556Srgrimes logwtmp("{", "date", ""); 2231556Srgrimes } 2241556Srgrimes 2251556Srgrimes if ((p = getlogin()) == NULL) 2261556Srgrimes p = "???"; 2271556Srgrimes syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p); 2281556Srgrimes} 2291556Srgrimes 2301556Srgrimesstatic void 2311556Srgrimesbadformat() 2321556Srgrimes{ 2331556Srgrimes warnx("illegal time format"); 2341556Srgrimes usage(); 2351556Srgrimes} 2361556Srgrimes 2371556Srgrimesstatic void 2381556Srgrimesusage() 2391556Srgrimes{ 2401556Srgrimes (void)fprintf(stderr, 2411556Srgrimes "usage: date [-nu] [-d dst] [-r seconds] [-t west] [+format]\n"); 2421556Srgrimes (void)fprintf(stderr, " [yy[mm[dd[hh]]]]mm[.ss]]\n"); 2431556Srgrimes exit(1); 2441556Srgrimes} 245