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