diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/ap/posix/tzset.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/ap/posix/tzset.c')
-rwxr-xr-x | sys/src/ape/lib/ap/posix/tzset.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/sys/src/ape/lib/ap/posix/tzset.c b/sys/src/ape/lib/ap/posix/tzset.c new file mode 100755 index 000000000..8502c6d66 --- /dev/null +++ b/sys/src/ape/lib/ap/posix/tzset.c @@ -0,0 +1,141 @@ +#include <stdlib.h> +#include <sys/types.h> +#include <fcntl.h> +#include <time.h> +#include <ctype.h> +#include <string.h> +#include <unistd.h> + +#define TZFILE "/etc/TZ" + +static char TZ[128]; +static char std[32] = "GMT0"; +static char dst[32]; +char *tzname[2] = { + std, dst +}; +time_t tzoffset, tzdstoffset; +int tzdst = 0; + +static int +offset(char *env, time_t *off) +{ + int n, sign; + size_t len, retlen; + + retlen = 0; + sign = 1; + /* + * strictly, no sign is allowed in the 'time' part of the + * dst start/stop rules, but who cares? + */ + if (*env == '-' || *env == '+') { + if (*env++ == '-') + sign = -1; + retlen++; + } + if ((len = strspn(env, ":0123456789")) == 0) + return 0; + retlen += len; + for (*off = 0; len && isdigit(*env); len--) /* hours */ + *off = *off*10 + (*env++ - '0')*60*60; + if (len) { + if (*env++ != ':') + return 0; + len--; + } + for (n = 0; len && isdigit(*env); len--) /* minutes */ + n = n*10 + (*env++ - '0')*60; + *off += n; + if (len) { + if (*env++ != ':') + return 0; + len--; + } + for (n = 0; len && isdigit(*env); len--) /* seconds */ + n = n*10 + (*env++ - '0'); + *off = (*off + n)*sign; + return retlen; +} + +/* + * TZ=stdoffset[dst[offset][,start[/time],end[/time]]] + */ +void +tzset(void) +{ + char *env, *p, envbuf[128]; + int fd, i; + size_t len, retlen; + time_t off; + + /* + * get the TZ environment variable and check for validity. + * the implementation-defined manner for dealing with the + * leading ':' format is to reject it. + * if it's ok, stash a copy away for quick comparison next time. + */ + if ((env = getenv("TZ")) == 0) { + if ((fd = open(TZFILE, O_RDONLY)) == -1) + return; + if (read(fd, envbuf, sizeof(envbuf)-1) == -1) { + close(fd); + return; + } + close(fd); + for (i = 0; i < sizeof(envbuf); i++) { + if (envbuf[i] != '\n') + continue; + envbuf[i] = '\0'; + break; + } + env = envbuf; + } + if (strcmp(env, TZ) == 0) + return; + if (*env == 0 || *env == ':') + return; + strncpy(TZ, env, sizeof(TZ)-1); + TZ[sizeof(TZ)-1] = 0; + /* + * get the 'std' string. + * before committing, check there is a valid offset. + */ + if ((len = strcspn(env, ":0123456789,-+")) == 0) + return; + if ((retlen = offset(env+len, &off)) == 0) + return; + for (p = std, i = len+retlen; i; i--) + *p++ = *env++; + *p = 0; + tzoffset = -off; + /* + * get the 'dst' string (if any). + */ + if (*env == 0 || (len = strcspn(env, ":0123456789,-+")) == 0) + return; + for (p = dst; len; len--) + *p++ = *env++; + *p = 0; + /* + * optional dst offset. + * default is one hour. + */ + tzdst = 1; + if (retlen = offset(env+len, &off)) { + tzdstoffset = -off; + env += retlen; + } + else + tzdstoffset = tzoffset + 60*60; + /* + * optional rule(s) for start/end of dst. + */ + if (*env == 0 || *env != ',' || *(env+1) == 0) + return; + env++; + /* + * we could go on... + * but why bother? + */ +} |