From 9f43f8d10bec580c44289a5ef1684f504ac5b7bb Mon Sep 17 00:00:00 2001 From: Martijn Dekker Date: Thu, 21 Jan 2021 13:45:05 +0000 Subject: [PATCH] Backport changes to AST time library from ksh 93v- beta This incorporates the last changes in the tm library before AT&T laid off the AST developers. It contains mostly time zone and locale related changes/fixes. I was hoping these would fix #52 (locale-based 'printf %T' output is broken), but no such luck. This is probably good to have anyway. --- src/lib/libast/tm/tminit.c | 35 +++++++++++++++---- src/lib/libast/tm/tmxdate.c | 27 ++++++++++----- src/lib/libast/tm/tmxfmt.c | 31 +++++++++++++---- src/lib/libast/tm/tmxscan.c | 18 ++++++---- src/lib/libast/tm/tmzone.c | 68 +++++++++++++++++++++++++++++++------ src/lib/libast/tm/tvtouch.c | 16 +++++---- 6 files changed, 151 insertions(+), 44 deletions(-) diff --git a/src/lib/libast/tm/tminit.c b/src/lib/libast/tm/tminit.c index c29e271a4..c20194029 100644 --- a/src/lib/libast/tm/tminit.c +++ b/src/lib/libast/tm/tminit.c @@ -1,7 +1,7 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 1985-2011 AT&T Intellectual Property * +* Copyright (c) 1985-2012 AT&T Intellectual Property * * and is licensed under the * * Eclipse Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -14,9 +14,9 @@ * AT&T Research * * Florham Park NJ * * * -* Glenn Fowler * -* David Korn * -* Phong Vo * +* Glenn Fowler * +* David Korn * +* Phong Vo * * * ***********************************************************************/ #pragma prototyped @@ -247,6 +247,10 @@ tmlocal(void) else if (e) environ[0] = e; } +#endif +#if _dat_tzname + local.standard = strdup(tzname[0]); + local.daylight = strdup(tzname[1]); #endif tmlocale(); @@ -292,8 +296,10 @@ tmlocal(void) * POSIX */ - local.standard = strdup(tzname[0]); - local.daylight = strdup(tzname[1]); + if (!local.standard) + local.standard = strdup(tzname[0]); + if (!local.daylight) + local.daylight = strdup(tzname[1]); } else #endif @@ -375,6 +381,23 @@ tmlocal(void) } } } + if (!*local.standard && !local.west && !local.dst && (s = getenv("TZ"))) + { + if ((zp = tmzone(s, &t, NiL, NiL)) && !*t) + { + local.standard = strdup(zp->standard); + if (zp->daylight) + local.daylight = strdup(zp->daylight); + local.west = zp->west; + local.dst = zp->dst; + } + else + local.standard = strdup(s); + if (!local.standard) + local.standard = ""; + if (!local.daylight) + local.daylight = ""; + } /* * set the options diff --git a/src/lib/libast/tm/tmxdate.c b/src/lib/libast/tm/tmxdate.c index 8048f7f60..a729b81b5 100644 --- a/src/lib/libast/tm/tmxdate.c +++ b/src/lib/libast/tm/tmxdate.c @@ -14,9 +14,9 @@ * AT&T Research * * Florham Park NJ * * * -* Glenn Fowler * -* David Korn * -* Phong Vo * +* Glenn Fowler * +* David Korn * +* Phong Vo * * * ***********************************************************************/ #pragma prototyped @@ -135,7 +135,7 @@ powerize(Tm_t* tm, unsigned long p, unsigned long q, unsigned long u) q *= 10; t *= 10; } - tm->tm_nsec += (int)(t % TMX_RESOLUTION); + tm->tm_nsec += (int)((unsigned long)t % TMX_RESOLUTION); tm->tm_sec += (int)(t / TMX_RESOLUTION); } @@ -228,12 +228,14 @@ tmxdate(register const char* s, char** e, Time_t now) state &= (state & HOLD) ? ~(HOLD) : ~(EXACT|LAST|NEXT|THIS); if ((set|state) & (YEAR|MONTH|DAY)) skip['/'] = 1; - message((-1, "AHA#%d state=" FFMT " set=" FFMT, __LINE__, FLAGS(state), FLAGS(set))); + while (isspace(*s)) + s++; + message((-1, "AHA#%d state=" FFMT " set=" FFMT " '%s'", __LINE__, FLAGS(state), FLAGS(set), s)); for (;;) { if (*s == '.' || *s == '-' || *s == '+') { - if (((set|state) & (YEAR|MONTH|HOUR|MINUTE|ZONE)) == (YEAR|MONTH|HOUR|MINUTE) && (i = tmgoff(s, &t, TM_LOCALZONE)) != TM_LOCALZONE) + if (((set|state) & (MONTH|HOUR|MINUTE|ZONE)) == (MONTH|HOUR|MINUTE) && (i = tmgoff(s, &t, TM_LOCALZONE)) != TM_LOCALZONE) { zone = i; state |= ZONE; @@ -518,13 +520,15 @@ tmxdate(register const char* s, char** e, Time_t now) if (!(state & CRON)) { /* - * check for cron date + * check for cron/iso date * * min hour day-of-month month day-of-week * * if it's cron then determine the next time * that satisfies the specification * + * if it's iso then its a point in time + * * NOTE: the only spacing is ' '||'_'||';' */ @@ -765,7 +769,8 @@ tmxdate(register const char* s, char** e, Time_t now) if (dig2(t, k) < 1 || k > 31) break; flags |= DAY; - goto save_yymmdd; + if (*t != 'T' && *t != 't' || !isdigit(*++t)) + goto save_yymmdd; } n = strtol(s = t, &t, 0); if ((t - s) < 2) @@ -965,6 +970,12 @@ tmxdate(register const char* s, char** e, Time_t now) tm->tm_year = m; s = t; set |= flags; + if ((*s == '-' || *s == '+') && (i = tmgoff(s, &t, TM_LOCALZONE)) != TM_LOCALZONE) + { + zone = i; + set |= ZONE; + s = t; + } continue; } for (s = t; skip[*s]; s++); diff --git a/src/lib/libast/tm/tmxfmt.c b/src/lib/libast/tm/tmxfmt.c index 6a1585cf3..5023d4351 100644 --- a/src/lib/libast/tm/tmxfmt.c +++ b/src/lib/libast/tm/tmxfmt.c @@ -1,7 +1,7 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 1985-2011 AT&T Intellectual Property * +* Copyright (c) 1985-2012 AT&T Intellectual Property * * and is licensed under the * * Eclipse Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -14,9 +14,9 @@ * AT&T Research * * Florham Park NJ * * * -* Glenn Fowler * -* David Korn * -* Phong Vo * +* Glenn Fowler * +* David Korn * +* Phong Vo * * * ***********************************************************************/ #pragma prototyped @@ -111,6 +111,7 @@ tmxfmt(char* buf, size_t len, const char* format, Time_t t) int prec; int parts; char* arg; + char* e; char* f; const char* oformat; Tm_t* tm; @@ -471,12 +472,26 @@ tmxfmt(char* buf, size_t len, const char* format, Time_t t) p = tm_info.format[TM_RECENT]; goto push; case 'z': /* time zone nation code */ - if (!(flags & TM_UTC)) + if (arg) + { + if ((zp = tmzone(arg, &e, NiL, NiL)) && !*e) + { + tm->tm_zone = zp; + flags &= ~TM_UTC; + } + } + else if (!(flags & TM_UTC)) { if ((zp = tm->tm_zone) != tm_info.local) + { for (; zp >= tm_data.zone; zp--) + { if (p = zp->type) goto string; + if (zp->standard == zp->daylight) + break; + } + } else if (p = zp->type) goto string; } @@ -597,10 +612,14 @@ tmxfmt(char* buf, size_t len, const char* format, Time_t t) if (arg) { if ((zp = tmzone(arg, &f, 0, 0)) && !*f && tm->tm_zone != zp) + { tm = tmxtm(tm, tmxtime(tm, tm->tm_zone->west + (tm->tm_isdst ? tm->tm_zone->dst : 0)), zp); + if (zp->west || zp->dst) + flags &= ~TM_UTC; + } continue; } - p = (flags & TM_UTC) ? tm_info.format[TM_UT] : tm->tm_isdst && tm->tm_zone->daylight ? tm->tm_zone->daylight : tm->tm_zone->standard; + p = (flags & TM_UTC) ? tm_info.local->standard : tm->tm_isdst && tm->tm_zone->daylight ? tm->tm_zone->daylight : tm->tm_zone->standard; goto string; case '=': /* (AST) OBSOLETE use %([+-]flag...)Qo (old %=[=][+-]flag) */ for (arg = argbuf; *format == '=' || *format == '-' || *format == '+' || *format == '!'; format++) diff --git a/src/lib/libast/tm/tmxscan.c b/src/lib/libast/tm/tmxscan.c index 98d4749c0..2a69d5398 100644 --- a/src/lib/libast/tm/tmxscan.c +++ b/src/lib/libast/tm/tmxscan.c @@ -1,7 +1,7 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 1985-2011 AT&T Intellectual Property * +* Copyright (c) 1985-2014 AT&T Intellectual Property * * and is licensed under the * * Eclipse Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -14,9 +14,9 @@ * AT&T Research * * Florham Park NJ * * * -* Glenn Fowler * -* David Korn * -* Phong Vo * +* Glenn Fowler * +* David Korn * +* Phong Vo * * * ***********************************************************************/ #pragma prototyped @@ -296,11 +296,15 @@ scan(register const char* s, char** e, const char* format, char** f, Time_t t, l continue; case 'n': if (pedantic) + { while (*s == '\n') s++; - else - while (isspace(*s)) - s++; + continue; + } + /*FALLTHROUGH*/ + case 't': + while (isspace(*s)) + s++; continue; case 'N': NUMBER(9, 0, 999999999L); diff --git a/src/lib/libast/tm/tmzone.c b/src/lib/libast/tm/tmzone.c index 230a5f3eb..680d9a9a9 100644 --- a/src/lib/libast/tm/tmzone.c +++ b/src/lib/libast/tm/tmzone.c @@ -1,7 +1,7 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 1985-2011 AT&T Intellectual Property * +* Copyright (c) 1985-2012 AT&T Intellectual Property * * and is licensed under the * * Eclipse Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -14,9 +14,9 @@ * AT&T Research * * Florham Park NJ * * * -* Glenn Fowler * -* David Korn * -* Phong Vo * +* Glenn Fowler * +* David Korn * +* Phong Vo * * * ***********************************************************************/ #pragma prototyped @@ -29,6 +29,7 @@ #include #include +#include /* * return timezone pointer given name and type @@ -49,16 +50,63 @@ Tm_zone_t* tmzone(register const char* name, char** end, const char* type, int* dst) { register Tm_zone_t* zp; - register char* prev; + register char* p; char* e; + int d; static Tm_zone_t fixed; static char off[16]; tmset(tm_info.zone); - if ((*name == '+' || *name == '-') && (fixed.west = tmgoff(name, &e, TM_LOCALZONE)) != TM_LOCALZONE && !*e) + if ((name[0] == '+' || name[0] == '-') && (fixed.west = tmgoff(name, &e, TM_LOCALZONE)) != TM_LOCALZONE && (!*e || isspace(*e))) { - strlcpy(fixed.standard = fixed.daylight = off, name, sizeof(off)); + p = fixed.standard = fixed.daylight = off; + *p++ = 'Z'; + if ((d = fixed.west) <= 0) + { + d = -d; + *p++ = 'E'; + } + else + *p++ = 'W'; + p += sfsprintf(p, sizeof(off) - 2, "%u", d / 60); + if (d = (d % 60) / 15) + *p++ = 'A' + d - 1; + *p = 0; + fixed.dst = 0; + if (end) + *end = e; + if (dst) + *dst = 0; + return &fixed; + } + else if ((name[0] == 'Z' || name[0] == 'Y') && (name[1] == 'E' || name[1] == 'W') && name[2] >= '0' && name[2] <= '9') + { + e = (char*)name + 2; + fixed.west = 0; + while (*e >= '0' && *e <= '9') + fixed.west = fixed.west * 10 + (*e++ - '0'); + fixed.west *= 60; + d = 0; + switch (*e) + { + case 'C': + d += 15; + /*FALLTHROUGH*/ + case 'B': + d += 15; + /*FALLTHROUGH*/ + case 'A': + d += 15; + e++; + break; + } + fixed.west += d; + if (name[1] == 'E') + fixed.west = -fixed.west; + fixed.dst = name[0] == 'Z' ? 0 : d ? -d : TM_DST; + memcpy(fixed.standard = fixed.daylight = off, name, d); + off[d] = 0; if (end) *end = e; if (dst) @@ -66,12 +114,12 @@ tmzone(register const char* name, char** end, const char* type, int* dst) return &fixed; } zp = tm_info.local; - prev = 0; + p = 0; do { if (zp->type) - prev = zp->type; - if (!type || type == prev || !prev) + p = zp->type; + if (!type || type == p || !p) { if (tmword(name, end, zp->standard, NiL, 0)) { diff --git a/src/lib/libast/tm/tvtouch.c b/src/lib/libast/tm/tvtouch.c index 7a8567fe0..11133fc0a 100644 --- a/src/lib/libast/tm/tvtouch.c +++ b/src/lib/libast/tm/tvtouch.c @@ -1,7 +1,7 @@ /*********************************************************************** * * * This software is part of the ast package * -* Copyright (c) 1985-2012 AT&T Intellectual Property * +* Copyright (c) 1985-2013 AT&T Intellectual Property * * and is licensed under the * * Eclipse Public License, Version 1.0 * * by AT&T Intellectual Property * @@ -14,9 +14,9 @@ * AT&T Research * * Florham Park NJ * * * -* Glenn Fowler * -* David Korn * -* Phong Vo * +* Glenn Fowler * +* David Korn * +* Phong Vo * * * ***********************************************************************/ #pragma prototyped @@ -95,6 +95,7 @@ tvtouch(const char* path, register const Tv_t* av, register const Tv_t* mv, cons #if _lib_utimets || _lib_utimensat struct timespec ts[2]; #endif +#if !_lib_utimets #if _lib_utimes struct timeval am[2]; #else @@ -103,6 +104,7 @@ tvtouch(const char* path, register const Tv_t* av, register const Tv_t* mv, cons #else time_t am[2]; #endif +#endif #endif oerrno = errno; @@ -147,7 +149,7 @@ tvtouch(const char* path, register const Tv_t* av, register const Tv_t* mv, cons return -1; umask(mode = umask(0)); mode = (~mode) & (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); - if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_cloexec, mode)) < 0) + if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, mode)) < 0) return -1; close(fd); errno = oerrno; @@ -251,7 +253,7 @@ tvtouch(const char* path, register const Tv_t* av, register const Tv_t* mv, cons errno = EINVAL; return -1; } - if ((fd = open(path, O_RDWR|O_cloexec)) >= 0) + if ((fd = open(path, O_RDWR|O_CLOEXEC)) >= 0) { char c; @@ -271,7 +273,7 @@ tvtouch(const char* path, register const Tv_t* av, register const Tv_t* mv, cons return -1; umask(mode = umask(0)); mode = (~mode) & (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); - if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_cloexec, mode)) < 0) + if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, mode)) < 0) return -1; close(fd); errno = oerrno;