summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Mills <gary_mills@fastmail.fm>2018-02-10 09:22:21 -0600
committerGordon Ross <gwr@nexenta.com>2018-03-14 16:00:47 -0400
commit026e699f086745296cda4664068f50ace71e32e2 (patch)
tree635c8c3902441dfac562388f9c4bc0428ca8808f
parentac29b594b43c0e9b5cc7656b662ca9f359b36a46 (diff)
downloadillumos-joyent-026e699f086745296cda4664068f50ace71e32e2.tar.gz
8980 BIOS clock is sometimes one hour fast
Reviewed by: Toomas Soome <tsoome@me.com> Reviewed by: C Fraire <cfraire@me.com> Approved by: Gordon Ross <gwr@nexenta.com>
-rw-r--r--usr/src/cmd/rtc/rtc.c166
-rw-r--r--usr/src/man/man1m/rtc.1m210
2 files changed, 246 insertions, 130 deletions
diff --git a/usr/src/cmd/rtc/rtc.c b/usr/src/cmd/rtc/rtc.c
index 1ef72c18d5..4e32bb3f16 100644
--- a/usr/src/cmd/rtc/rtc.c
+++ b/usr/src/cmd/rtc/rtc.c
@@ -20,12 +20,11 @@
* CDDL HEADER END
*/
/*
+ * Copyright 2018 Gary Mills
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -36,13 +35,21 @@
#include <string.h>
#include <sys/stat.h>
+/* RTC modes */
+#define M_UNSET 0 /* Mode never set */
+#define M_VAR 1 /* Tracks local time including DST */
+#define M_UTC 2 /* Clock runs in UTC */
+#define M_STD 3 /* Clock runs in local standard time */
+
static char *progname;
static char *zonefile = "/etc/rtc_config";
static FILE *zonefptr;
static char zone_info[256];
static char zone_lag[256];
static char tz[256] = "TZ=";
+static char *utc_zone = "UTC";
int debug = 0;
+int rtc_mode = M_UNSET;
int lag;
int errors_ok = 0; /* allow "rtc no-args" to be quiet when not configured */
static time_t clock_val;
@@ -71,8 +78,8 @@ open_zonefile()
if ((zonefptr = fopen(zonefile, "r")) == NULL) {
if (errors_ok == 0)
(void) fprintf(stderr,
- "%s: cannot open %s: errno = %d\n",
- progname, zonefile, errno);
+ "%s: cannot open %s: errno = %d\n",
+ progname, zonefile, errno);
return (1);
}
@@ -156,21 +163,13 @@ display_zone_string(void)
(void) printf("GMT\n");
}
-long
-set_zone(char *zone_string)
+int
+get_local(char *z)
{
struct tm *tm;
- long current_lag;
-
- (void) umask(0022);
- if ((zonefptr = fopen(zonefile, "w")) == NULL) {
- (void) fprintf(stderr, "%s: cannot open %s: errno = %d\n",
- progname, zonefile, errno);
- return (0);
- }
tz[3] = 0;
- (void) strncat(tz, zone_string, 253);
+ (void) strncat(tz, z, 253);
if (debug)
(void) fprintf(stderr, "Time Zone string is '%s'\n", tz);
@@ -181,15 +180,44 @@ set_zone(char *zone_string)
(void) time(&clock_val);
tm = localtime(&clock_val);
- current_lag = tm->tm_isdst ? altzone : timezone;
+ return (tm->tm_isdst);
+}
+
+long
+set_zone(char *zone_string)
+{
+ int isdst;
+ long current_lag;
+
+ (void) umask(0022);
+ if ((zonefptr = fopen(zonefile, "w")) == NULL) {
+ (void) fprintf(stderr, "%s: cannot open %s: errno = %d\n",
+ progname, zonefile, errno);
+ return (0);
+ }
+
+ switch (rtc_mode) {
+ case M_VAR:
+ isdst = get_local(zone_string);
+ current_lag = isdst ? altzone : timezone;
+ break;
+ case M_STD:
+ isdst = get_local(zone_string);
+ current_lag = timezone;
+ break;
+ default: /* Includes M_UTC */
+ isdst = 0;
+ current_lag = 0;
+ zone_string = utc_zone;
+ break;
+ }
if (debug)
- (void) printf("%s DST. Lag is %ld.\n", tm->tm_isdst ? "Is" :
- "Is NOT", tm->tm_isdst ? altzone : timezone);
+ (void) printf("%s DST. Lag is %ld.\n", isdst ? "Is" :
+ "Is NOT", current_lag);
(void) fprintf(zonefptr, zone_comment, zonefile);
(void) fprintf(zonefptr, "zone_info=%s\n", zone_string);
- (void) fprintf(zonefptr, "zone_lag=%ld\n",
- tm->tm_isdst ? altzone : timezone);
+ (void) fprintf(zonefptr, "zone_lag=%ld\n", current_lag);
(void) fclose(zonefptr);
zonefptr = NULL;
return (current_lag);
@@ -198,36 +226,37 @@ set_zone(char *zone_string)
void
correct_rtc_and_lag()
{
- struct tm *tm;
+ int isdst;
long kernels_lag;
long current_lag;
if (open_zonefile())
return;
- tz[3] = 0;
- (void) strncat(tz, zone_info, 253);
- if (debug)
- (void) fprintf(stderr, "Time Zone string is '%s'\n", tz);
-
- (void) putenv(tz);
- if (debug)
- (void) system("env | grep TZ");
-
- (void) time(&clock_val);
- tm = localtime(&clock_val);
- current_lag = tm->tm_isdst ? altzone : timezone;
+ switch (rtc_mode) {
+ case M_VAR:
+ isdst = get_local(zone_info);
+ current_lag = isdst ? altzone : timezone;
+ break;
+ case M_STD:
+ (void) get_local(zone_info);
+ current_lag = timezone;
+ break;
+ default: /* Includes M_UTC */
+ current_lag = 0;
+ break;
+ }
if (current_lag != lag) { /* if file is wrong */
if (debug)
- (void) fprintf(stderr, "correcting file");
+ (void) fprintf(stderr, "correcting file\n");
(void) set_zone(zone_info); /* then rewrite file */
}
(void) sysi86(GGMTL, &kernels_lag);
if (current_lag != kernels_lag) {
if (debug)
- (void) fprintf(stderr, "correcting kernel's lag");
+ (void) fprintf(stderr, "correcting kernel's lag\n");
(void) sysi86(SGMTL, current_lag); /* correct the lag */
(void) sysi86(WTODC); /* set the rtc to */
/* new local time */
@@ -257,7 +286,7 @@ void
usage()
{
static char Usage[] = "Usage:\n\
-rtc [-c] [-z time_zone] [-?]\n";
+rtc [-w] [-s|-u|-v] [-c] [-z time_zone] [-?]\n";
(void) fprintf(stderr, Usage);
}
@@ -267,42 +296,95 @@ verbose_usage()
{
static char Usage1[] = "\
Options:\n\
+ -w\t\tDoes nothing.\n\
+ -s\t\tRTC runs in local standard time.\n\
+ -u\t\tRTC runs in UTC time.\n\
+ -v\t\tRTC tracks local time (with cron command).\n\
-c\t\tCheck and correct for daylight savings time rollover.\n\
-z [zone]\tRecord the zone info in the config file.\n";
(void) fprintf(stderr, Usage1);
}
+void
+set_default()
+{
+ switch (rtc_mode) {
+ default: /* Includes M_UNSET */
+ rtc_mode = M_VAR;
+ break;
+ case M_VAR:
+ /*FALLTHROUGH*/
+ case M_UTC:
+ /*FALLTHROUGH*/
+ case M_STD:
+ break;
+ }
+}
+
+void
+check_mode(int letter, int mode)
+{
+ if (rtc_mode == M_UNSET || rtc_mode == mode) {
+ rtc_mode = mode;
+ return;
+ }
+ (void) fprintf(stderr, "%s: option -%c conflicts with other options\n",
+ progname, letter);
+ exit(1);
+}
+
+
int
main(int argc, char *argv[])
{
int c;
+ int cflg = 0;
+ char *zone_name = NULL;
progname = argv[0];
if (argc == 1) {
errors_ok = 1;
display_zone_string();
+ exit(0);
}
- while ((c = getopt(argc, argv, "cz:d")) != EOF) {
+ while ((c = getopt(argc, argv, "suvwcz:d")) != EOF) {
switch (c) {
case 'c':
- correct_rtc_and_lag();
+ cflg++;
continue;
case 'z':
- initialize_zone(optarg);
+ zone_name = optarg;
continue;
case 'd':
debug = 1;
continue;
+ case 's': /* standard: RTC runs local standard time */
+ check_mode(c, M_STD);
+ continue;
+ case 'u': /* utc: RTC runs UTC time */
+ check_mode(c, M_UTC);
+ continue;
+ case 'v': /* varies: RTC tracks local time */
+ check_mode(c, M_VAR);
+ continue;
+ case 'w': /* Does nothing */
+ continue;
case '?':
verbose_usage();
- return (0);
+ exit(0);
default:
usage();
- return (1);
+ exit(1);
}
}
- return (0);
+ set_default();
+ if (zone_name != NULL)
+ initialize_zone(zone_name);
+ if (cflg > 0)
+ correct_rtc_and_lag();
+ exit(0);
+ /*LINTED*/
}
diff --git a/usr/src/man/man1m/rtc.1m b/usr/src/man/man1m/rtc.1m
index fd258fde45..3ac51b4c88 100644
--- a/usr/src/man/man1m/rtc.1m
+++ b/usr/src/man/man1m/rtc.1m
@@ -1,90 +1,124 @@
-'\" te
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2018 Gary Mills
.\" Copyright (c) 2003, Sun Microsystems, Inc. All Rights Reserved.
-.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
-.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
-.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH RTC 1M "Oct 3, 2003"
-.SH NAME
-rtc \- provide all real-time clock and GMT-lag management
-.SH SYNOPSIS
-.LP
-.nf
-\fB/usr/sbin/rtc\fR [\fB-c\fR] [\fB-z\fR \fIzone-name\fR]
-.fi
-
-.SH DESCRIPTION
-.sp
-.LP
-On x86 systems, the \fBrtc\fR command reconciles the difference in the way that
-time is established between UNIX and MS-DOS systems. UNIX systems utilize
-Greenwich Mean Time (\fBGMT\fR), while \fBMS-DOS\fR systems utilize local time.
-.sp
-.LP
-Without arguments, \fBrtc\fR displays the currently configured time zone
-string. The currently configured time zone string is based on what was last
-recorded by \fBrtc\fR\fB-z\fR \fIzone-name\fR.
-.sp
-.LP
-The \fBrtc\fR command is not normally run from a shell prompt; it is generally
-invoked by the system. Commands such as \fBdate\fR(1) and \fBrdate\fR(1M),
-which are used to set the time on a system, invoke \fB/usr/sbin/rtc\fR \fB-c\fR
-to ensure that daylight savings time (\fBDST\fR) is corrected for properly.
-.SH OPTIONS
-.sp
-.ne 2
-.na
-\fB\fB-c\fR\fR
-.ad
-.RS 16n
-This option checks for \fBDST\fR and makes corrections if necessary. It is
-normally run once a day by a \fBcron\fR job.
-.sp
-If there is no \fBRTC\fR time zone or \fB/etc/rtc_config\fR file, this option
-will do nothing.
-.RE
-
-.sp
-.ne 2
-.na
-\fB\fB\fR\fB-z\fR\fB \fR\fIzone-name\fR\fR
-.ad
-.RS 16n
+.\"
+.Dd January 31, 2018
+.Dt RTC 1M
+.Os
+.Sh NAME
+.Nm rtc
+.Nd provide all real-time clock and UTC-lag management
+.Sh SYNOPSIS
+.Nm
+.Op Fl csuvw
+.Op Fl z Ar zone-name
+.Sh DESCRIPTION
+The Real Time Clock (RTC) is the hardware device on x86 computers that maintains
+the date and time.
+The RTC is battery-powered, so that it keeps running when the computer is shut
+down.
+It can be set from the BIOS and also from the operating system running on the
+computer.
+The RTC has no setting for the time zone or for Daylight Saving Time (DST).
+It relies on the operating system for these facilities and for automatic changes
+between standard time and DST.
+.Pp
+On x86 systems, the
+.Nm
+command reconciles the difference in the way that time is established between
+UNIX and Windows systems.
+The internal clock on UNIX systems utilizes Universal Coordinated Time (UTC)
+while Windows systems usually expect the RTC to run in local time, including DST
+changes.
+.Pp
+Without arguments,
+.Nm
+displays the currently configured time zone string for the RTC.
+The currently configured time zone string is based on what was last recorded by
+.Nm Fl z Ar zone-name .
+.Pp
+The
+.Nm
+command is not normally run from a shell prompt; it is generally invoked by the
+system.
+Commands such as
+.Xr date 1
+and
+.Xr rdate 1M ,
+which are used to set the time on a system, invoke
+.Nm Fl c
+to ensure that daylight savings time (DST) is corrected for properly.
+.Sh OPTIONS
+.Bl -tag -width Ds
+.It Fl c
+This option checks for DST and makes corrections to the RTC if necessary.
+It is normally run once a day by a
+.Xr cron 1M
+job.
+.Pp
+If there is no RTC time zone or
+.Pa /etc/rtc_config
+file, this option will do nothing.
+.It Fl s
+This option specifies that the RTC runs in local standard time all year round.
+It is incompatible with Windows, but is convenient if only one operating system
+is to be run on the computer.
+The
+.Xr cron 1M
+command is not necessary, and should not be run.
+.It Fl u
+This option specifies that the RTC runs in UTC time.
+As a side effect, it sets the time zone in
+.Pa /etc/rtc_config
+to UTC.
+Windows can operate in UTC time, but requires a registry change to do so.
+The
+.Xr cron 1M
+command is not necessary.
+.It Fl v
+This option specifies that the RTC tracks local time, including DST changes.
+This is the default.
+It accomodates Windows with no changes.
+The
+.Xr cron 1M
+command is necessary to change the RTC when DST is in effect.
+.It Fl w
+This option does nothing.
+It is present for compatibility with Solaris 11.
+.It Fl z Ar zone-name
This option, which is normally run by the system at software installation time,
-is used to specify the time zone in which the \fBRTC\fR is to be maintained. It
-updates the configuration file \fB/etc/rtc_config\fR with the name of the
-specified zone and the current \fBGMT\fR lag for that zone. If there is an
-existing \fBrtc_config\fR file, this command will update it. If not, this
-command will create it.
-.RE
-
-.SH FILES
-.sp
-.ne 2
-.na
-\fB\fB/etc/rtc_config\fR\fR
-.ad
-.RS 19n
-The data file used to record the time zone and \fBGMT\fR lag. This file is
-completely managed by \fB/usr/sbin/rtc\fR, and it is read by the kernel.
-.RE
-
-.SH ATTRIBUTES
-.sp
-.LP
-See \fBattributes\fR(5) for descriptions of the following attributes:
-.sp
-
-.sp
-.TS
-box;
-c | c
-l | l .
-ATTRIBUTE TYPE ATTRIBUTE VALUE
-_
-Architecture x86
-.TE
-
-.SH SEE ALSO
-.sp
-.LP
-\fBdate\fR(1), \fBrdate\fR(1M), \fBattributes\fR(5)
+is used to specify the time zone in which the RTC is to be maintained.
+It updates the configuration file
+.Pa /etc/rtc_config
+with the name of the specified zone and the current UTC lag for that zone.
+If there is an existing
+.Pa /etc/rtc_config
+file, this command will update it.
+If not, this command will create it.
+.El
+.Sh FILES
+.Bl -tag -width "/etc/rtc_config"
+.It Pa /etc/rtc_config
+The data file used to record the time zone and UTC lag.
+This file is completely managed by
+.Nm .
+At boot time, the kernel reads the UTC lag from this file, and uses it to set
+the system time.
+.El
+.Sh ARCHITECTURE
+.Sy x86
+.Sh SEE ALSO
+.Xr date 1 ,
+.Xr cron 1M ,
+.Xr rdate 1M ,
+.Xr attributes 5