Return to BSD News archive
Path: sserve!newshost.anu.edu.au!munnari.oz.au!hp9000.csc.cuhk.hk!saimiri.primate.wisc.edu!zaphod.mps.ohio-state.edu!wupost!emory!europa.eng.gtefsd.com!gatech!usenet.ins.cwru.edu!agate!doc.ic.ac.uk!marble.uknet.ac.uk!mcsun!news.funet.fi!fuug!kiae!relcom!newsserv From: "Andrew A. Chernov, Black Mage" <ache@astral.msk.su> Newsgroups: comp.os.386bsd.bugs Subject: Fix 'date' for update kernel zone offset using zoneinfo rules Date: Wed, 31 Mar 93 00:44:56 +0400 Distribution: world Organization: Ha-olahm Yetzirah Message-ID: <DN85Bkhu60@astral.msk.su> Sender: news-service@newcom.kiae.su Reply-To: ache@astral.msk.su Lines: 125 Problem description: 1. MSDOS and SETUP use BIOS clock value as local (wall) clock. 2. 386bsd use BIOS clock value in the same way only if kernel zone offset and current zoneinfo zone offset (/etc/localtime) are equal. 3. Kernel compiled with constant zone offset and don't know anything about right time to change to DST and back. 4. When DST change occurs, kernel zone offset and zoneinfo zone offset are different, so 386bsd show incorrect time (usually, one hour apart or back). You can modify this time by hand, but in such situation you obtain incorrect time in MSDOS or SETUP. Solution: I add '-Z' key to "date", which update kernel current zone offset and corresponding time using current zoneinfo rules. You can simple add date -Z -n before starting anything in your /etc/rc and obtain automagically timezone changes and correct MSDOS and SETUP clock too. Problem description: There is '-t' option in "date" to provide forced kernel timezone offset, but this option works only with positive values (west of GMT), because getopt() treat all negative (-180 f.e.) arguments as separate option and produce error. Solution: I add '-T' option to "date" to change kernel timezone offset east of GMT with positive argument converted to negative. *** date.c.was Fri Apr 5 05:19:45 1991 --- /usr/src/bin/date/date.c Tue Mar 30 22:37:58 1993 *************** *** 63,75 **** struct timezone tz; int ch, rflag; char *format, buf[1024]; ! tz.tz_dsttime = tz.tz_minuteswest = 0; rflag = 0; ! while ((ch = getopt(argc, argv, "d:nr:ut:")) != EOF) switch((char)ch) { case 'd': /* daylight savings time */ tz.tz_dsttime = atoi(optarg) ? 1 : 0; break; case 'n': /* don't set network */ nflag = 1; --- 63,78 ---- struct timezone tz; int ch, rflag; char *format, buf[1024]; + int force_dst, force_off; ! force_dst = force_off = 0; ! (void)gettimeofday((struct timeval *)NULL, &tz); rflag = 0; ! while ((ch = getopt(argc, argv, "d:nr:ut:T:Z")) != EOF) switch((char)ch) { case 'd': /* daylight savings time */ tz.tz_dsttime = atoi(optarg) ? 1 : 0; + force_dst = 1; break; case 'n': /* don't set network */ nflag = 1; *************** *** 81,90 **** --- 84,116 ---- case 'u': /* do everything in GMT */ (void)setenv("TZ", "GMT0", 1); break; + case 'Z': { /* update kernel offset */ + /* using zoneinfo rules */ + struct tm *tm; + struct timeval tv; + + (void)gettimeofday(&tv, (struct timezone *)NULL); + tm = localtime(&tv.tv_sec); + tv.tv_sec += -tm->tm_gmtoff - tz.tz_minuteswest*60; + if (!force_off) + tz.tz_minuteswest = -tm->tm_gmtoff/60; + if (!force_dst && tm->tm_isdst) + tz.tz_dsttime = 1; + if (settimeofday(&tv, &tz)) { + perror("date: settimeofday"); + exit(1); + } + force_dst = force_off = 0; + } + break; case 't': /* minutes west of GMT */ + case 'T': /* minutes east of GMT, pay for getopt */ /* error check; don't allow "PST" */ if (isdigit(*optarg)) { tz.tz_minuteswest = atoi(optarg); + if (ch == 'T') + tz.tz_minuteswest = -tz.tz_minuteswest; + force_off = 1; break; } /* FALLTHROUGH */ *************** *** 98,104 **** * If -d or -t, set the timezone or daylight savings time; this * doesn't belong here, there kernel should not know about either. */ ! if ((tz.tz_minuteswest || tz.tz_dsttime) && settimeofday((struct timeval *)NULL, &tz)) { perror("date: settimeofday"); exit(1); --- 124,130 ---- * If -d or -t, set the timezone or daylight savings time; this * doesn't belong here, there kernel should not know about either. */ ! if ((force_off || force_dst) && settimeofday((struct timeval *)NULL, &tz)) { perror("date: settimeofday"); exit(1); -- In-This-Life: Andrew A. Chernov | "Hay mas dicha, mas contento Internet: ache@astral.msk.su | "Que adorar una hermosura FIDOnet: 2:5020/23.34 | "Brujuleada entre los lejos RELCOM Development Team, Moscow, Russia | "De lo imposible?!" (Calderon)