17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier
4*54dec067SDavid du Colombier #define TZSIZE ((136*2)+10) /* 1970-2106; match tm2sec.c */
5*54dec067SDavid du Colombier
67dd7cddfSDavid du Colombier static void readtimezone(void);
77dd7cddfSDavid du Colombier static int rd_name(char**, char*);
87dd7cddfSDavid du Colombier static int rd_long(char**, long*);
9*54dec067SDavid du Colombier
107dd7cddfSDavid du Colombier static
117dd7cddfSDavid du Colombier struct
127dd7cddfSDavid du Colombier {
137dd7cddfSDavid du Colombier char stname[4];
147dd7cddfSDavid du Colombier char dlname[4];
157dd7cddfSDavid du Colombier long stdiff;
167dd7cddfSDavid du Colombier long dldiff;
17*54dec067SDavid du Colombier ulong dlpairs[TZSIZE];
187dd7cddfSDavid du Colombier } timezone;
197dd7cddfSDavid du Colombier
20*54dec067SDavid du Colombier #define SEC2MIN 60UL
21*54dec067SDavid du Colombier #define SEC2HOUR (60UL*SEC2MIN)
22*54dec067SDavid du Colombier #define SEC2DAY (24UL*SEC2HOUR)
237dd7cddfSDavid du Colombier
247dd7cddfSDavid du Colombier /*
257dd7cddfSDavid du Colombier * days per month plus days/year
267dd7cddfSDavid du Colombier */
277dd7cddfSDavid du Colombier static int dmsize[] =
287dd7cddfSDavid du Colombier {
297dd7cddfSDavid du Colombier 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
307dd7cddfSDavid du Colombier };
317dd7cddfSDavid du Colombier static int ldmsize[] =
327dd7cddfSDavid du Colombier {
337dd7cddfSDavid du Colombier 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
347dd7cddfSDavid du Colombier };
357dd7cddfSDavid du Colombier
367dd7cddfSDavid du Colombier /*
377dd7cddfSDavid du Colombier * return the days/month for the given year
387dd7cddfSDavid du Colombier */
397dd7cddfSDavid du Colombier static int *
yrsize(int y)407dd7cddfSDavid du Colombier yrsize(int y)
417dd7cddfSDavid du Colombier {
427dd7cddfSDavid du Colombier if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
437dd7cddfSDavid du Colombier return ldmsize;
447dd7cddfSDavid du Colombier else
457dd7cddfSDavid du Colombier return dmsize;
467dd7cddfSDavid du Colombier }
477dd7cddfSDavid du Colombier
487dd7cddfSDavid du Colombier /*
497dd7cddfSDavid du Colombier * compute seconds since Jan 1 1970 GMT
507dd7cddfSDavid du Colombier * and convert to our timezone.
517dd7cddfSDavid du Colombier */
527dd7cddfSDavid du Colombier long
tm2sec(Tm * tm)537dd7cddfSDavid du Colombier tm2sec(Tm *tm)
547dd7cddfSDavid du Colombier {
55*54dec067SDavid du Colombier ulong secs;
5607a38badSDavid du Colombier int i, yday, year, *d2m;
577dd7cddfSDavid du Colombier
587dd7cddfSDavid du Colombier if(strcmp(tm->zone, "GMT") != 0 && timezone.stname[0] == 0)
597dd7cddfSDavid du Colombier readtimezone();
607dd7cddfSDavid du Colombier secs = 0;
617dd7cddfSDavid du Colombier
627dd7cddfSDavid du Colombier /*
637dd7cddfSDavid du Colombier * seconds per year
647dd7cddfSDavid du Colombier */
657dd7cddfSDavid du Colombier year = tm->year + 1900;
667dd7cddfSDavid du Colombier for(i = 1970; i < year; i++){
677dd7cddfSDavid du Colombier d2m = yrsize(i);
687dd7cddfSDavid du Colombier secs += d2m[0] * SEC2DAY;
697dd7cddfSDavid du Colombier }
707dd7cddfSDavid du Colombier
717dd7cddfSDavid du Colombier /*
7207a38badSDavid du Colombier * if mday is set, use mon and mday to compute yday
736b6b9ac8SDavid du Colombier */
7407a38badSDavid du Colombier if(tm->mday){
7507a38badSDavid du Colombier yday = 0;
767dd7cddfSDavid du Colombier d2m = yrsize(year);
777dd7cddfSDavid du Colombier for(i=0; i<tm->mon; i++)
7807a38badSDavid du Colombier yday += d2m[i+1];
7907a38badSDavid du Colombier yday += tm->mday-1;
8007a38badSDavid du Colombier }else{
8107a38badSDavid du Colombier yday = tm->yday;
826b6b9ac8SDavid du Colombier }
8307a38badSDavid du Colombier secs += yday * SEC2DAY;
847dd7cddfSDavid du Colombier
857dd7cddfSDavid du Colombier /*
867dd7cddfSDavid du Colombier * hours, minutes, seconds
877dd7cddfSDavid du Colombier */
887dd7cddfSDavid du Colombier secs += tm->hour * SEC2HOUR;
897dd7cddfSDavid du Colombier secs += tm->min * SEC2MIN;
907dd7cddfSDavid du Colombier secs += tm->sec;
917dd7cddfSDavid du Colombier
927dd7cddfSDavid du Colombier /*
93d9306527SDavid du Colombier * Only handles zones mentioned in /env/timezone,
94d9306527SDavid du Colombier * but things get too ambiguous otherwise.
957dd7cddfSDavid du Colombier */
96d9306527SDavid du Colombier if(strcmp(tm->zone, timezone.stname) == 0)
97d9306527SDavid du Colombier secs -= timezone.stdiff;
98d9306527SDavid du Colombier else if(strcmp(tm->zone, timezone.dlname) == 0)
99d9306527SDavid du Colombier secs -= timezone.dldiff;
1007dd7cddfSDavid du Colombier return secs;
1017dd7cddfSDavid du Colombier }
1027dd7cddfSDavid du Colombier
1037dd7cddfSDavid du Colombier static
1047dd7cddfSDavid du Colombier void
readtimezone(void)1057dd7cddfSDavid du Colombier readtimezone(void)
1067dd7cddfSDavid du Colombier {
1077dd7cddfSDavid du Colombier char buf[TZSIZE*11+30], *p;
1087dd7cddfSDavid du Colombier int i;
1097dd7cddfSDavid du Colombier
1107dd7cddfSDavid du Colombier memset(buf, 0, sizeof(buf));
1117dd7cddfSDavid du Colombier i = open("/env/timezone", 0);
1127dd7cddfSDavid du Colombier if(i < 0)
1137dd7cddfSDavid du Colombier goto error;
1147dd7cddfSDavid du Colombier if(read(i, buf, sizeof(buf)) >= sizeof(buf))
1157dd7cddfSDavid du Colombier goto error;
1167dd7cddfSDavid du Colombier close(i);
1177dd7cddfSDavid du Colombier p = buf;
1187dd7cddfSDavid du Colombier if(rd_name(&p, timezone.stname))
1197dd7cddfSDavid du Colombier goto error;
1207dd7cddfSDavid du Colombier if(rd_long(&p, &timezone.stdiff))
1217dd7cddfSDavid du Colombier goto error;
1227dd7cddfSDavid du Colombier if(rd_name(&p, timezone.dlname))
1237dd7cddfSDavid du Colombier goto error;
1247dd7cddfSDavid du Colombier if(rd_long(&p, &timezone.dldiff))
1257dd7cddfSDavid du Colombier goto error;
1267dd7cddfSDavid du Colombier for(i=0; i<TZSIZE; i++) {
127*54dec067SDavid du Colombier if(rd_long(&p, (long *)&timezone.dlpairs[i]))
1287dd7cddfSDavid du Colombier goto error;
1297dd7cddfSDavid du Colombier if(timezone.dlpairs[i] == 0)
1307dd7cddfSDavid du Colombier return;
1317dd7cddfSDavid du Colombier }
132*54dec067SDavid du Colombier /* array too small for input */
1337dd7cddfSDavid du Colombier error:
1347dd7cddfSDavid du Colombier timezone.stdiff = 0;
1357dd7cddfSDavid du Colombier strcpy(timezone.stname, "GMT");
1367dd7cddfSDavid du Colombier timezone.dlpairs[0] = 0;
1377dd7cddfSDavid du Colombier }
1387dd7cddfSDavid du Colombier
1397dd7cddfSDavid du Colombier static int
rd_name(char ** f,char * p)1407dd7cddfSDavid du Colombier rd_name(char **f, char *p)
1417dd7cddfSDavid du Colombier {
1427dd7cddfSDavid du Colombier int c, i;
1437dd7cddfSDavid du Colombier
1447dd7cddfSDavid du Colombier for(;;) {
1457dd7cddfSDavid du Colombier c = *(*f)++;
1467dd7cddfSDavid du Colombier if(c != ' ' && c != '\n')
1477dd7cddfSDavid du Colombier break;
1487dd7cddfSDavid du Colombier }
1497dd7cddfSDavid du Colombier for(i=0; i<3; i++) {
1507dd7cddfSDavid du Colombier if(c == ' ' || c == '\n')
1517dd7cddfSDavid du Colombier return 1;
1527dd7cddfSDavid du Colombier *p++ = c;
1537dd7cddfSDavid du Colombier c = *(*f)++;
1547dd7cddfSDavid du Colombier }
1557dd7cddfSDavid du Colombier if(c != ' ' && c != '\n')
1567dd7cddfSDavid du Colombier return 1;
1577dd7cddfSDavid du Colombier *p = 0;
1587dd7cddfSDavid du Colombier return 0;
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier
1617dd7cddfSDavid du Colombier static int
rd_long(char ** f,long * p)1627dd7cddfSDavid du Colombier rd_long(char **f, long *p)
1637dd7cddfSDavid du Colombier {
1647dd7cddfSDavid du Colombier int c, s;
1657dd7cddfSDavid du Colombier long l;
1667dd7cddfSDavid du Colombier
1677dd7cddfSDavid du Colombier s = 0;
1687dd7cddfSDavid du Colombier for(;;) {
1697dd7cddfSDavid du Colombier c = *(*f)++;
1707dd7cddfSDavid du Colombier if(c == '-') {
1717dd7cddfSDavid du Colombier s++;
1727dd7cddfSDavid du Colombier continue;
1737dd7cddfSDavid du Colombier }
1747dd7cddfSDavid du Colombier if(c != ' ' && c != '\n')
1757dd7cddfSDavid du Colombier break;
1767dd7cddfSDavid du Colombier }
1777dd7cddfSDavid du Colombier if(c == 0) {
1787dd7cddfSDavid du Colombier *p = 0;
1797dd7cddfSDavid du Colombier return 0;
1807dd7cddfSDavid du Colombier }
1817dd7cddfSDavid du Colombier l = 0;
1827dd7cddfSDavid du Colombier for(;;) {
1837dd7cddfSDavid du Colombier if(c == ' ' || c == '\n')
1847dd7cddfSDavid du Colombier break;
1857dd7cddfSDavid du Colombier if(c < '0' || c > '9')
1867dd7cddfSDavid du Colombier return 1;
1877dd7cddfSDavid du Colombier l = l*10 + c-'0';
1887dd7cddfSDavid du Colombier c = *(*f)++;
1897dd7cddfSDavid du Colombier }
1907dd7cddfSDavid du Colombier if(s)
1917dd7cddfSDavid du Colombier l = -l;
1927dd7cddfSDavid du Colombier *p = l;
1937dd7cddfSDavid du Colombier return 0;
1947dd7cddfSDavid du Colombier }
195