1e8f3668aSmckusick /*
2e4fa375eSbostic * Copyright (c) 1985, 1987, 1988, 1993
3e4fa375eSbostic * The Regents of the University of California. All rights reserved.
4c2c8d999Sbostic *
561d627fdSbostic * %sccs.include.redist.c%
6e8f3668aSmckusick */
7e8f3668aSmckusick
8ad4dcd8fSsam #ifndef lint
9e4fa375eSbostic static char copyright[] =
10e4fa375eSbostic "@(#) Copyright (c) 1985, 1987, 1988, 1993\n\
11e4fa375eSbostic The Regents of the University of California. All rights reserved.\n";
12c2c8d999Sbostic #endif /* not lint */
13e8f3668aSmckusick
14e8f3668aSmckusick #ifndef lint
15*93001edbSbostic static char sccsid[] = "@(#)date.c 8.2 (Berkeley) 04/28/95";
16c2c8d999Sbostic #endif /* not lint */
17ad4dcd8fSsam
1836fa1a6bSkarels #include <sys/param.h>
1929f671e3Swnj #include <sys/time.h>
2095e6f391Sbostic
2195e6f391Sbostic #include <ctype.h>
2295e6f391Sbostic #include <err.h>
2395e6f391Sbostic #include <fcntl.h>
24fe3493caSbostic #include <stdio.h>
2574c46193Sbostic #include <stdlib.h>
261afa398dSbostic #include <string.h>
2795e6f391Sbostic #include <syslog.h>
2895e6f391Sbostic #include <unistd.h>
2995e6f391Sbostic
3095e6f391Sbostic #include "extern.h"
318df64c17Sgusella
3274c46193Sbostic time_t tval;
3374c46193Sbostic int retval, nflag;
3463fd2155Sbill
3595e6f391Sbostic static void setthetime __P((char *));
3695e6f391Sbostic static void badformat __P((void));
3795e6f391Sbostic static void usage __P((void));
3895e6f391Sbostic
3995e6f391Sbostic int logwtmp __P((char *, char *, char *));
4095e6f391Sbostic
4195e6f391Sbostic int
main(argc,argv)4263fd2155Sbill main(argc, argv)
43ad4dcd8fSsam int argc;
44fe3493caSbostic char **argv;
4563fd2155Sbill {
46fe3493caSbostic extern int optind;
47fe3493caSbostic extern char *optarg;
48fe3493caSbostic struct timezone tz;
490850ca54Sbostic int ch, rflag;
5074c46193Sbostic char *format, buf[1024];
5163fd2155Sbill
5233de07beSbostic tz.tz_dsttime = tz.tz_minuteswest = 0;
530850ca54Sbostic rflag = 0;
54*93001edbSbostic while ((ch = getopt(argc, argv, "d:nr:ut:")) != -1)
55fe3493caSbostic switch((char)ch) {
56c2c8d999Sbostic case 'd': /* daylight savings time */
57fe3493caSbostic tz.tz_dsttime = atoi(optarg) ? 1 : 0;
58fe3493caSbostic break;
59c2c8d999Sbostic case 'n': /* don't set network */
60fe3493caSbostic nflag = 1;
611a1d0a1fSkarels break;
620850ca54Sbostic case 'r': /* user specified seconds */
630850ca54Sbostic rflag = 1;
64b4781d87Sbostic tval = atol(optarg);
65b4781d87Sbostic break;
6674c46193Sbostic case 'u': /* do everything in GMT */
676c8be42fSbostic (void)setenv("TZ", "GMT0", 1);
681a1d0a1fSkarels break;
69c2c8d999Sbostic case 't': /* minutes west of GMT */
7074c46193Sbostic /* error check; don't allow "PST" */
7133de07beSbostic if (isdigit(*optarg)) {
7233de07beSbostic tz.tz_minuteswest = atoi(optarg);
7333de07beSbostic break;
7433de07beSbostic }
7533de07beSbostic /* FALLTHROUGH */
761a1d0a1fSkarels default:
7733de07beSbostic usage();
781a1d0a1fSkarels }
79fe3493caSbostic argc -= optind;
80fe3493caSbostic argv += optind;
81fe3493caSbostic
8274c46193Sbostic /*
8374c46193Sbostic * If -d or -t, set the timezone or daylight savings time; this
8474c46193Sbostic * doesn't belong here, there kernel should not know about either.
8574c46193Sbostic */
86fe3493caSbostic if ((tz.tz_minuteswest || tz.tz_dsttime) &&
8795e6f391Sbostic settimeofday(NULL, &tz))
8895e6f391Sbostic err(1, "settimeofday");
89fe3493caSbostic
9095e6f391Sbostic if (!rflag && time(&tval) == -1)
9195e6f391Sbostic err(1, "time");
92fe3493caSbostic
93*93001edbSbostic format = "%a %b %e %H:%M:%S %Z %Y";
94fe3493caSbostic
9574c46193Sbostic /* allow the operands in any order */
9674c46193Sbostic if (*argv && **argv == '+') {
9774c46193Sbostic format = *argv + 1;
9874c46193Sbostic ++argv;
99fe3493caSbostic }
100fe3493caSbostic
10174c46193Sbostic if (*argv) {
10274c46193Sbostic setthetime(*argv);
10374c46193Sbostic ++argv;
104fe3493caSbostic }
10574c46193Sbostic
10674c46193Sbostic if (*argv && **argv == '+')
10774c46193Sbostic format = *argv + 1;
10874c46193Sbostic
10974c46193Sbostic (void)strftime(buf, sizeof(buf), format, localtime(&tval));
110*93001edbSbostic (void)printf("%s\n", buf);
11174c46193Sbostic exit(retval);
11274c46193Sbostic }
11374c46193Sbostic
11474c46193Sbostic #define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
11595e6f391Sbostic void
setthetime(p)11674c46193Sbostic setthetime(p)
11774c46193Sbostic register char *p;
11874c46193Sbostic {
11974c46193Sbostic register struct tm *lt;
12074c46193Sbostic struct timeval tv;
1217391f40dSbostic char *dot, *t;
12274c46193Sbostic
1237391f40dSbostic for (t = p, dot = NULL; *t; ++t) {
1247391f40dSbostic if (isdigit(*t))
1257391f40dSbostic continue;
1267391f40dSbostic if (*t == '.' && dot == NULL) {
1277391f40dSbostic dot = t;
1287391f40dSbostic continue;
1297391f40dSbostic }
13074c46193Sbostic badformat();
1317391f40dSbostic }
13274c46193Sbostic
13374c46193Sbostic lt = localtime(&tval);
13474c46193Sbostic
1357391f40dSbostic if (dot != NULL) { /* .ss */
1367391f40dSbostic *dot++ = '\0';
1377391f40dSbostic if (strlen(dot) != 2)
138d24fe13cSralph badformat();
1397391f40dSbostic lt->tm_sec = ATOI2(dot);
14074c46193Sbostic if (lt->tm_sec > 61)
14174c46193Sbostic badformat();
14274c46193Sbostic } else
14374c46193Sbostic lt->tm_sec = 0;
14474c46193Sbostic
14574c46193Sbostic switch (strlen(p)) {
14674c46193Sbostic case 10: /* yy */
14774c46193Sbostic lt->tm_year = ATOI2(p);
14874c46193Sbostic if (lt->tm_year < 69) /* hack for 2000 ;-} */
14974c46193Sbostic lt->tm_year += 100;
15074c46193Sbostic /* FALLTHROUGH */
15174c46193Sbostic case 8: /* mm */
15274c46193Sbostic lt->tm_mon = ATOI2(p);
15374c46193Sbostic if (lt->tm_mon > 12)
15474c46193Sbostic badformat();
155c289d8baSbostic --lt->tm_mon; /* time struct is 0 - 11 */
15674c46193Sbostic /* FALLTHROUGH */
15774c46193Sbostic case 6: /* dd */
15874c46193Sbostic lt->tm_mday = ATOI2(p);
15974c46193Sbostic if (lt->tm_mday > 31)
16074c46193Sbostic badformat();
16174c46193Sbostic /* FALLTHROUGH */
16274c46193Sbostic case 4: /* hh */
16374c46193Sbostic lt->tm_hour = ATOI2(p);
16474c46193Sbostic if (lt->tm_hour > 23)
16574c46193Sbostic badformat();
16674c46193Sbostic /* FALLTHROUGH */
16774c46193Sbostic case 2: /* mm */
16874c46193Sbostic lt->tm_min = ATOI2(p);
16974c46193Sbostic if (lt->tm_min > 59)
17074c46193Sbostic badformat();
17174c46193Sbostic break;
17274c46193Sbostic default:
17374c46193Sbostic badformat();
17474c46193Sbostic }
17574c46193Sbostic
17674c46193Sbostic /* convert broken-down time to GMT clock time */
17774c46193Sbostic if ((tval = mktime(lt)) == -1)
17874c46193Sbostic badformat();
17974c46193Sbostic
18074c46193Sbostic /* set the time */
18174c46193Sbostic if (nflag || netsettime(tval)) {
182c2c8d999Sbostic logwtmp("|", "date", "");
18374c46193Sbostic tv.tv_sec = tval;
18474c46193Sbostic tv.tv_usec = 0;
1850f558095Sbostic if (settimeofday(&tv, NULL)) {
186993df27fSbostic perror("date: settimeofday");
187993df27fSbostic exit(1);
188fe3493caSbostic }
189c2c8d999Sbostic logwtmp("{", "date", "");
1908df64c17Sgusella }
1910f558095Sbostic
1920f558095Sbostic if ((p = getlogin()) == NULL)
1930f558095Sbostic p = "???";
1940f558095Sbostic syslog(LOG_AUTH | LOG_NOTICE, "date set by %s", p);
19563fd2155Sbill }
19663fd2155Sbill
19795e6f391Sbostic static void
badformat()19874c46193Sbostic badformat()
19963fd2155Sbill {
20095e6f391Sbostic warnx("illegal time format");
20174c46193Sbostic usage();
2021d873399Skarels }
20333de07beSbostic
20495e6f391Sbostic static void
usage()20533de07beSbostic usage()
20633de07beSbostic {
20774c46193Sbostic (void)fprintf(stderr,
208b4781d87Sbostic "usage: date [-nu] [-d dst] [-r seconds] [-t west] [+format]\n");
209b4781d87Sbostic (void)fprintf(stderr, " [yy[mm[dd[hh]]]]mm[.ss]]\n");
21074c46193Sbostic exit(1);
21133de07beSbostic }
212