date.c revision 1.9
1/* $NetBSD: date.c,v 1.9 1995/03/21 09:03:50 cgd Exp $ */ 2 3/* 4 * Copyright (c) 1985, 1987, 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#ifndef lint 37static char copyright[] = 38"@(#) Copyright (c) 1985, 1987, 1988, 1993\n\ 39 The Regents of the University of California. All rights reserved.\n"; 40#endif /* not lint */ 41 42#ifndef lint 43static char sccsid[] = "@(#)date.c 8.1 (Berkeley) 5/31/93"; 44#endif /* not lint */ 45 46#include <sys/param.h> 47#include <sys/time.h> 48 49#include <ctype.h> 50#include <err.h> 51#include <fcntl.h> 52#include <stdio.h> 53#include <stdlib.h> 54#include <string.h> 55#include <locale.h> 56#include <syslog.h> 57#include <unistd.h> 58 59#include "extern.h" 60 61time_t tval; 62int retval, nflag; 63 64static void setthetime __P((char *)); 65static void badformat __P((void)); 66static void usage __P((void)); 67 68int logwtmp __P((char *, char *, char *)); 69 70int 71main(argc, argv) 72 int argc; 73 char **argv; 74{ 75 extern int optind; 76 extern char *optarg; 77 struct timezone tz; 78 int ch, rflag; 79 char *format, buf[1024]; 80 81 setlocale(LC_ALL, ""); 82 83 tz.tz_dsttime = tz.tz_minuteswest = 0; 84 rflag = 0; 85 while ((ch = getopt(argc, argv, "d:nr:ut:")) != -1) 86 switch((char)ch) { 87 case 'd': /* daylight savings time */ 88 tz.tz_dsttime = atoi(optarg) ? 1 : 0; 89 break; 90 case 'n': /* don't set network */ 91 nflag = 1; 92 break; 93 case 'r': /* user specified seconds */ 94 rflag = 1; 95 tval = atol(optarg); 96 break; 97 case 'u': /* do everything in GMT */ 98 (void)setenv("TZ", "GMT0", 1); 99 break; 100 case 't': /* minutes west of GMT */ 101 /* error check; don't allow "PST" */ 102 if (isdigit(*optarg)) { 103 tz.tz_minuteswest = atoi(optarg); 104 break; 105 } 106 /* FALLTHROUGH */ 107 default: 108 usage(); 109 } 110 argc -= optind; 111 argv += optind; 112 113 /* 114 * If -d or -t, set the timezone or daylight savings time; this 115 * doesn't belong here, there kernel should not know about either. 116 */ 117 if ((tz.tz_minuteswest || tz.tz_dsttime) && 118 settimeofday(NULL, &tz)) 119 err(1, "settimeofday"); 120 121 if (!rflag && time(&tval) == -1) 122 err(1, "time"); 123 124 format = "%a %b %e %H:%M:%S %Z %Y"; 125 126 /* allow the operands in any order */ 127 if (*argv && **argv == '+') { 128 format = *argv + 1; 129 ++argv; 130 } 131 132 if (*argv) { 133 setthetime(*argv); 134 ++argv; 135 } 136 137 if (*argv && **argv == '+') 138 format = *argv + 1; 139 140 (void)strftime(buf, sizeof(buf), format, localtime(&tval)); 141 (void)printf("%s\n", buf); 142 exit(retval); 143} 144 145#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2; 146void 147setthetime(p) 148 register char *p; 149{ 150 register struct tm *lt; 151 struct timeval tv; 152 char *dot, *t; 153 154 for (t = p, dot = NULL; *t; ++t) { 155 if (isdigit(*t)) 156 continue; 157 if (*t == '.' && dot == NULL) { 158 dot = t; 159 continue; 160 } 161 badformat(); 162 } 163 164 lt = localtime(&tval); 165 166 if (dot != NULL) { /* .ss */ 167 *dot++ = '\0'; 168 if (strlen(dot) != 2) 169 badformat(); 170 lt->tm_sec = ATOI2(dot); 171 if (lt->tm_sec > 61) 172 badformat(); 173 } else 174 lt->tm_sec = 0; 175 176 switch (strlen(p)) { 177 case 10: /* yy */ 178 lt->tm_year = ATOI2(p); 179 if (lt->tm_year < 69) /* hack for 2000 ;-} */ 180 lt->tm_year += 100; 181 /* FALLTHROUGH */ 182 case 8: /* mm */ 183 lt->tm_mon = ATOI2(p); 184 if (lt->tm_mon > 12) 185 badformat(); 186 --lt->tm_mon; /* time struct is 0 - 11 */ 187 /* FALLTHROUGH */ 188 case 6: /* dd */ 189 lt->tm_mday = ATOI2(p); 190 if (lt->tm_mday > 31) 191 badformat(); 192 /* FALLTHROUGH */ 193 case 4: /* hh */ 194 lt->tm_hour = ATOI2(p); 195 if (lt->tm_hour > 23) 196 badformat(); 197 /* FALLTHROUGH */ 198 case 2: /* mm */ 199 lt->tm_min = ATOI2(p); 200 if (lt->tm_min > 59) 201 badformat(); 202 break; 203 default: 204 badformat(); 205 } 206 207 /* convert broken-down time to GMT clock time */ 208 if ((tval = mktime(lt)) == -1) 209 badformat(); 210 211 /* set the time */ 212 if (nflag || netsettime(tval)) { 213 logwtmp("|", "date", ""); 214 tv.tv_sec = tval; 215 tv.tv_usec = 0; 216 if (settimeofday(&tv, NULL)) { 217 perror("date: settimeofday"); 218 exit(1); 219 } 220 logwtmp("{", "date", ""); 221 } 222 223 if ((p = getlogin()) == NULL) 224 p = "???"; 225 syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p); 226} 227 228static void 229badformat() 230{ 231 warnx("illegal time format"); 232 usage(); 233} 234 235static void 236usage() 237{ 238 (void)fprintf(stderr, 239 "usage: date [-nu] [-d dst] [-r seconds] [-t west] [+format]\n"); 240 (void)fprintf(stderr, " [yy[mm[dd[hh]]]]mm[.ss]]\n"); 241 exit(1); 242} 243