17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier
47dd7cddfSDavid du Colombier #define TZSIZE 150
57dd7cddfSDavid du Colombier static void readtimezone(void);
67dd7cddfSDavid du Colombier static int rd_name(char**, char*);
77dd7cddfSDavid du Colombier static int rd_long(char**, long*);
87dd7cddfSDavid du Colombier static
97dd7cddfSDavid du Colombier struct
107dd7cddfSDavid du Colombier {
117dd7cddfSDavid du Colombier char stname[4];
127dd7cddfSDavid du Colombier char dlname[4];
137dd7cddfSDavid du Colombier long stdiff;
147dd7cddfSDavid du Colombier long dldiff;
157dd7cddfSDavid du Colombier long dlpairs[TZSIZE];
167dd7cddfSDavid du Colombier } timezone;
177dd7cddfSDavid du Colombier
187dd7cddfSDavid du Colombier #define SEC2MIN 60L
197dd7cddfSDavid du Colombier #define SEC2HOUR (60L*SEC2MIN)
207dd7cddfSDavid du Colombier #define SEC2DAY (24L*SEC2HOUR)
217dd7cddfSDavid du Colombier
227dd7cddfSDavid du Colombier /*
237dd7cddfSDavid du Colombier * days per month plus days/year
247dd7cddfSDavid du Colombier */
257dd7cddfSDavid du Colombier static int dmsize[] =
267dd7cddfSDavid du Colombier {
277dd7cddfSDavid du Colombier 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
287dd7cddfSDavid du Colombier };
297dd7cddfSDavid du Colombier static int ldmsize[] =
307dd7cddfSDavid du Colombier {
317dd7cddfSDavid du Colombier 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
327dd7cddfSDavid du Colombier };
337dd7cddfSDavid du Colombier
347dd7cddfSDavid du Colombier /*
357dd7cddfSDavid du Colombier * return the days/month for the given year
367dd7cddfSDavid du Colombier */
377dd7cddfSDavid du Colombier static int *
yrsize(int y)387dd7cddfSDavid du Colombier yrsize(int y)
397dd7cddfSDavid du Colombier {
407dd7cddfSDavid du Colombier if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
417dd7cddfSDavid du Colombier return ldmsize;
427dd7cddfSDavid du Colombier else
437dd7cddfSDavid du Colombier return dmsize;
447dd7cddfSDavid du Colombier }
457dd7cddfSDavid du Colombier
467dd7cddfSDavid du Colombier /*
477dd7cddfSDavid du Colombier * compute seconds since Jan 1 1970 GMT
487dd7cddfSDavid du Colombier * and convert to our timezone.
497dd7cddfSDavid du Colombier */
507dd7cddfSDavid du Colombier long
tm2sec(Tm * tm)517dd7cddfSDavid du Colombier tm2sec(Tm *tm)
527dd7cddfSDavid du Colombier {
53d9306527SDavid du Colombier long secs;
54*07a38badSDavid du Colombier int i, yday, year, *d2m;
557dd7cddfSDavid du Colombier
567dd7cddfSDavid du Colombier if(strcmp(tm->zone, "GMT") != 0 && timezone.stname[0] == 0)
577dd7cddfSDavid du Colombier readtimezone();
587dd7cddfSDavid du Colombier secs = 0;
597dd7cddfSDavid du Colombier
607dd7cddfSDavid du Colombier /*
617dd7cddfSDavid du Colombier * seconds per year
627dd7cddfSDavid du Colombier */
637dd7cddfSDavid du Colombier year = tm->year + 1900;
647dd7cddfSDavid du Colombier for(i = 1970; i < year; i++){
657dd7cddfSDavid du Colombier d2m = yrsize(i);
667dd7cddfSDavid du Colombier secs += d2m[0] * SEC2DAY;
677dd7cddfSDavid du Colombier }
687dd7cddfSDavid du Colombier
697dd7cddfSDavid du Colombier /*
70*07a38badSDavid du Colombier * if mday is set, use mon and mday to compute yday
716b6b9ac8SDavid du Colombier */
72*07a38badSDavid du Colombier if(tm->mday){
73*07a38badSDavid du Colombier yday = 0;
747dd7cddfSDavid du Colombier d2m = yrsize(year);
757dd7cddfSDavid du Colombier for(i=0; i<tm->mon; i++)
76*07a38badSDavid du Colombier yday += d2m[i+1];
77*07a38badSDavid du Colombier yday += tm->mday-1;
78*07a38badSDavid du Colombier }else{
79*07a38badSDavid du Colombier yday = tm->yday;
806b6b9ac8SDavid du Colombier }
81*07a38badSDavid du Colombier secs += yday * SEC2DAY;
827dd7cddfSDavid du Colombier
837dd7cddfSDavid du Colombier /*
847dd7cddfSDavid du Colombier * hours, minutes, seconds
857dd7cddfSDavid du Colombier */
867dd7cddfSDavid du Colombier secs += tm->hour * SEC2HOUR;
877dd7cddfSDavid du Colombier secs += tm->min * SEC2MIN;
887dd7cddfSDavid du Colombier secs += tm->sec;
897dd7cddfSDavid du Colombier
907dd7cddfSDavid du Colombier /*
91d9306527SDavid du Colombier * Only handles zones mentioned in /env/timezone,
92d9306527SDavid du Colombier * but things get too ambiguous otherwise.
937dd7cddfSDavid du Colombier */
94d9306527SDavid du Colombier if(strcmp(tm->zone, timezone.stname) == 0)
95d9306527SDavid du Colombier secs -= timezone.stdiff;
96d9306527SDavid du Colombier else if(strcmp(tm->zone, timezone.dlname) == 0)
97d9306527SDavid du Colombier secs -= timezone.dldiff;
98d9306527SDavid du Colombier if(secs < 0)
99d9306527SDavid du Colombier secs = 0;
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++) {
1277dd7cddfSDavid du Colombier if(rd_long(&p, &timezone.dlpairs[i]))
1287dd7cddfSDavid du Colombier goto error;
1297dd7cddfSDavid du Colombier if(timezone.dlpairs[i] == 0)
1307dd7cddfSDavid du Colombier return;
1317dd7cddfSDavid du Colombier }
1327dd7cddfSDavid du Colombier
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