--- old/usr/src/cmd/rtc/rtc.c	Sat Feb 10 09:35:49 2018
+++ new/usr/src/cmd/rtc/rtc.c	Sat Feb 10 09:35:49 2018
@@ -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,6 +35,12 @@
 #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;
@@ -42,7 +47,9 @@
 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 @@
 	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 @@
 		(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 @@
 	(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,7 +226,7 @@
 void
 correct_rtc_and_lag()
 {
-	struct tm *tm;
+	int isdst;
 	long kernels_lag;
 	long current_lag;
 
@@ -205,22 +233,23 @@
 	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);
+	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;
+	}
 
-	(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;
-
 	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 */
 	}
 
@@ -227,7 +256,7 @@
 	(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 @@
 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,6 +296,10 @@
 {
 	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";
 
@@ -273,10 +306,41 @@
 	(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];
 
@@ -283,26 +347,44 @@
 	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*/
 }
