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