13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier * This routine converts time as follows.
33e12c5d1SDavid du Colombier * The epoch is 0000 Jan 1 1970 GMT.
43e12c5d1SDavid du Colombier * The argument time is in seconds since then.
53e12c5d1SDavid du Colombier * The localtime(t) entry returns a pointer to an array
63e12c5d1SDavid du Colombier * containing
73e12c5d1SDavid du Colombier *
83e12c5d1SDavid du Colombier * seconds (0-59)
93e12c5d1SDavid du Colombier * minutes (0-59)
103e12c5d1SDavid du Colombier * hours (0-23)
113e12c5d1SDavid du Colombier * day of month (1-31)
123e12c5d1SDavid du Colombier * month (0-11)
133e12c5d1SDavid du Colombier * year-1970
143e12c5d1SDavid du Colombier * weekday (0-6, Sun is 0)
153e12c5d1SDavid du Colombier * day of the year
163e12c5d1SDavid du Colombier * daylight savings flag
173e12c5d1SDavid du Colombier *
183e12c5d1SDavid du Colombier * The routine gets the daylight savings time from the environment.
193e12c5d1SDavid du Colombier *
203e12c5d1SDavid du Colombier * asctime(tvec))
213e12c5d1SDavid du Colombier * where tvec is produced by localtime
223e12c5d1SDavid du Colombier * returns a ptr to a character string
233e12c5d1SDavid du Colombier * that has the ascii time in the form
243e12c5d1SDavid du Colombier *
253e12c5d1SDavid du Colombier * \\
263e12c5d1SDavid du Colombier * Thu Jan 01 00:00:00 1970n0
273e12c5d1SDavid du Colombier * 01234567890123456789012345
283e12c5d1SDavid du Colombier * 0 1 2
293e12c5d1SDavid du Colombier *
303e12c5d1SDavid du Colombier * ctime(t) just calls localtime, then asctime.
313e12c5d1SDavid du Colombier */
323e12c5d1SDavid du Colombier
333e12c5d1SDavid du Colombier #include <sys/types.h>
343e12c5d1SDavid du Colombier #include <sys/stat.h>
353e12c5d1SDavid du Colombier #include <fcntl.h>
363e12c5d1SDavid du Colombier #include <time.h>
373e12c5d1SDavid du Colombier #include <unistd.h>
383e12c5d1SDavid du Colombier #include <string.h>
393e12c5d1SDavid du Colombier
403e12c5d1SDavid du Colombier static char dmsize[12] =
413e12c5d1SDavid du Colombier {
423e12c5d1SDavid du Colombier 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
433e12c5d1SDavid du Colombier };
443e12c5d1SDavid du Colombier
453e12c5d1SDavid du Colombier /*
463e12c5d1SDavid du Colombier * The following table is used for 1974 and 1975 and
473e12c5d1SDavid du Colombier * gives the day number of the first day after the Sunday of the
483e12c5d1SDavid du Colombier * change.
493e12c5d1SDavid du Colombier */
503e12c5d1SDavid du Colombier
513e12c5d1SDavid du Colombier static int dysize(int);
523e12c5d1SDavid du Colombier static void ct_numb(char*, int);
533e12c5d1SDavid du Colombier static void readtimezone(void);
543e12c5d1SDavid du Colombier static int rd_name(char**, char*);
553e12c5d1SDavid du Colombier static int rd_long(char**, long*);
562d069feaSDavid du Colombier
572d069feaSDavid du Colombier #define TZSIZE 150
582d069feaSDavid du Colombier
593e12c5d1SDavid du Colombier static
603e12c5d1SDavid du Colombier struct
613e12c5d1SDavid du Colombier {
623e12c5d1SDavid du Colombier char stname[4];
633e12c5d1SDavid du Colombier char dlname[4];
643e12c5d1SDavid du Colombier long stdiff;
653e12c5d1SDavid du Colombier long dldiff;
663e12c5d1SDavid du Colombier long dlpairs[TZSIZE];
673e12c5d1SDavid du Colombier } timezone;
683e12c5d1SDavid du Colombier
693e12c5d1SDavid du Colombier char*
ctime(const time_t * t)703e12c5d1SDavid du Colombier ctime(const time_t *t)
713e12c5d1SDavid du Colombier {
723e12c5d1SDavid du Colombier return asctime(localtime(t));
733e12c5d1SDavid du Colombier }
743e12c5d1SDavid du Colombier
753e12c5d1SDavid du Colombier struct tm*
gmtime_r(const time_t * timp,struct tm * result)762d069feaSDavid du Colombier gmtime_r(const time_t *timp, struct tm *result)
772d069feaSDavid du Colombier {
782d069feaSDavid du Colombier int d0, d1;
792d069feaSDavid du Colombier long hms, day;
802d069feaSDavid du Colombier time_t tim;
812d069feaSDavid du Colombier
822d069feaSDavid du Colombier tim = *timp;
832d069feaSDavid du Colombier /*
842d069feaSDavid du Colombier * break initial number into days
852d069feaSDavid du Colombier */
862d069feaSDavid du Colombier hms = tim % 86400L;
872d069feaSDavid du Colombier day = tim / 86400L;
882d069feaSDavid du Colombier if(hms < 0) {
892d069feaSDavid du Colombier hms += 86400L;
902d069feaSDavid du Colombier day -= 1;
912d069feaSDavid du Colombier }
922d069feaSDavid du Colombier
932d069feaSDavid du Colombier /*
942d069feaSDavid du Colombier * generate hours:minutes:seconds
952d069feaSDavid du Colombier */
962d069feaSDavid du Colombier result->tm_sec = hms % 60;
972d069feaSDavid du Colombier d1 = hms / 60;
982d069feaSDavid du Colombier result->tm_min = d1 % 60;
992d069feaSDavid du Colombier d1 /= 60;
1002d069feaSDavid du Colombier result->tm_hour = d1;
1012d069feaSDavid du Colombier
1022d069feaSDavid du Colombier /*
1032d069feaSDavid du Colombier * day is the day number.
1042d069feaSDavid du Colombier * generate day of the week.
1052d069feaSDavid du Colombier * The addend is 4 mod 7 (1/1/1970 was Thursday)
1062d069feaSDavid du Colombier */
1072d069feaSDavid du Colombier
1082d069feaSDavid du Colombier result->tm_wday = (day + 7340036L) % 7;
1092d069feaSDavid du Colombier
1102d069feaSDavid du Colombier /*
1112d069feaSDavid du Colombier * year number
1122d069feaSDavid du Colombier */
1132d069feaSDavid du Colombier if(day >= 0)
1142d069feaSDavid du Colombier for(d1 = 70; day >= dysize(d1); d1++)
1152d069feaSDavid du Colombier day -= dysize(d1);
1162d069feaSDavid du Colombier else
1172d069feaSDavid du Colombier for (d1 = 70; day < 0; d1--)
1182d069feaSDavid du Colombier day += dysize(d1-1);
1192d069feaSDavid du Colombier result->tm_year = d1;
1202d069feaSDavid du Colombier result->tm_yday = d0 = day;
1212d069feaSDavid du Colombier
1222d069feaSDavid du Colombier /*
1232d069feaSDavid du Colombier * generate month
1242d069feaSDavid du Colombier */
1252d069feaSDavid du Colombier
1262d069feaSDavid du Colombier if(dysize(d1) == 366)
1272d069feaSDavid du Colombier dmsize[1] = 29;
1282d069feaSDavid du Colombier for(d1 = 0; d0 >= dmsize[d1]; d1++)
1292d069feaSDavid du Colombier d0 -= dmsize[d1];
1302d069feaSDavid du Colombier dmsize[1] = 28;
1312d069feaSDavid du Colombier result->tm_mday = d0 + 1;
1322d069feaSDavid du Colombier result->tm_mon = d1;
1332d069feaSDavid du Colombier result->tm_isdst = 0;
1342d069feaSDavid du Colombier return result;
1352d069feaSDavid du Colombier }
1362d069feaSDavid du Colombier
1372d069feaSDavid du Colombier struct tm*
gmtime(const time_t * timp)1382d069feaSDavid du Colombier gmtime(const time_t *timp)
1392d069feaSDavid du Colombier {
1402d069feaSDavid du Colombier static struct tm xtime;
1412d069feaSDavid du Colombier
1422d069feaSDavid du Colombier return gmtime_r(timp, &xtime);
1432d069feaSDavid du Colombier }
1442d069feaSDavid du Colombier
1452d069feaSDavid du Colombier struct tm*
localtime_r(const time_t * timp,struct tm * result)1462d069feaSDavid du Colombier localtime_r(const time_t *timp, struct tm *result)
1473e12c5d1SDavid du Colombier {
1483e12c5d1SDavid du Colombier struct tm *ct;
1493e12c5d1SDavid du Colombier time_t t, tim;
1503e12c5d1SDavid du Colombier long *p;
151781103c4SDavid du Colombier int dlflag;
1523e12c5d1SDavid du Colombier
1533e12c5d1SDavid du Colombier tim = *timp;
1543e12c5d1SDavid du Colombier if(timezone.stname[0] == 0)
1553e12c5d1SDavid du Colombier readtimezone();
1563e12c5d1SDavid du Colombier t = tim + timezone.stdiff;
1573e12c5d1SDavid du Colombier dlflag = 0;
1583e12c5d1SDavid du Colombier for(p = timezone.dlpairs; *p; p += 2)
1593e12c5d1SDavid du Colombier if(t >= p[0])
1603e12c5d1SDavid du Colombier if(t < p[1]) {
1613e12c5d1SDavid du Colombier t = tim + timezone.dldiff;
1623e12c5d1SDavid du Colombier dlflag++;
1633e12c5d1SDavid du Colombier break;
1643e12c5d1SDavid du Colombier }
1652d069feaSDavid du Colombier ct = gmtime_r(&t, result);
1663e12c5d1SDavid du Colombier ct->tm_isdst = dlflag;
1673e12c5d1SDavid du Colombier return ct;
1683e12c5d1SDavid du Colombier }
1693e12c5d1SDavid du Colombier
1703e12c5d1SDavid du Colombier struct tm*
localtime(const time_t * timp)1712d069feaSDavid du Colombier localtime(const time_t *timp)
1723e12c5d1SDavid du Colombier {
1733e12c5d1SDavid du Colombier static struct tm xtime;
1743e12c5d1SDavid du Colombier
1752d069feaSDavid du Colombier return localtime_r(timp, &xtime);
1763e12c5d1SDavid du Colombier }
1773e12c5d1SDavid du Colombier
1782d069feaSDavid du Colombier char*
asctime_r(const struct tm * t,char * buf)1792d069feaSDavid du Colombier asctime_r(const struct tm *t, char *buf)
1802d069feaSDavid du Colombier {
1812d069feaSDavid du Colombier char *ncp;
1823e12c5d1SDavid du Colombier
1832d069feaSDavid du Colombier strcpy(buf, "Thu Jan 01 00:00:00 1970\n");
1842d069feaSDavid du Colombier ncp = &"SunMonTueWedThuFriSat"[t->tm_wday*3];
1852d069feaSDavid du Colombier buf[0] = *ncp++;
1862d069feaSDavid du Colombier buf[1] = *ncp++;
1872d069feaSDavid du Colombier buf[2] = *ncp;
1882d069feaSDavid du Colombier ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[t->tm_mon*3];
1892d069feaSDavid du Colombier buf[4] = *ncp++;
1902d069feaSDavid du Colombier buf[5] = *ncp++;
1912d069feaSDavid du Colombier buf[6] = *ncp;
1922d069feaSDavid du Colombier ct_numb(buf+8, t->tm_mday);
1932d069feaSDavid du Colombier ct_numb(buf+11, t->tm_hour+100);
1942d069feaSDavid du Colombier ct_numb(buf+14, t->tm_min+100);
1952d069feaSDavid du Colombier ct_numb(buf+17, t->tm_sec+100);
1962d069feaSDavid du Colombier if(t->tm_year >= 100) {
1972d069feaSDavid du Colombier buf[20] = '2';
198*24617541SDavid du Colombier buf[21] = t->tm_year >= 200? '1': '0';
1992d069feaSDavid du Colombier }
2002d069feaSDavid du Colombier ct_numb(buf+22, t->tm_year+100);
2012d069feaSDavid du Colombier return buf;
2023e12c5d1SDavid du Colombier }
2033e12c5d1SDavid du Colombier
2043e12c5d1SDavid du Colombier char*
asctime(const struct tm * t)2053e12c5d1SDavid du Colombier asctime(const struct tm *t)
2063e12c5d1SDavid du Colombier {
2073e12c5d1SDavid du Colombier static char cbuf[30];
2083e12c5d1SDavid du Colombier
2092d069feaSDavid du Colombier return asctime_r(t, cbuf);
2103e12c5d1SDavid du Colombier }
2113e12c5d1SDavid du Colombier
2123e12c5d1SDavid du Colombier static
dysize(int y)2133e12c5d1SDavid du Colombier dysize(int y)
2143e12c5d1SDavid du Colombier {
2153e12c5d1SDavid du Colombier if((y%4) == 0)
2163e12c5d1SDavid du Colombier return 366;
2173e12c5d1SDavid du Colombier return 365;
2183e12c5d1SDavid du Colombier }
2193e12c5d1SDavid du Colombier
2203e12c5d1SDavid du Colombier static
2213e12c5d1SDavid du Colombier void
ct_numb(char * cp,int n)2223e12c5d1SDavid du Colombier ct_numb(char *cp, int n)
2233e12c5d1SDavid du Colombier {
2243e12c5d1SDavid du Colombier cp[0] = ' ';
2253e12c5d1SDavid du Colombier if(n >= 10)
2263e12c5d1SDavid du Colombier cp[0] = (n/10)%10 + '0';
2273e12c5d1SDavid du Colombier cp[1] = n%10 + '0';
2283e12c5d1SDavid du Colombier }
2293e12c5d1SDavid du Colombier
2303e12c5d1SDavid du Colombier static
2313e12c5d1SDavid du Colombier void
readtimezone(void)2323e12c5d1SDavid du Colombier readtimezone(void)
2333e12c5d1SDavid du Colombier {
2343e12c5d1SDavid du Colombier char buf[TZSIZE*11+30], *p;
2353e12c5d1SDavid du Colombier int i;
2363e12c5d1SDavid du Colombier
2373e12c5d1SDavid du Colombier memset(buf, 0, sizeof(buf));
2383e12c5d1SDavid du Colombier i = open("/env/timezone", 0);
2393e12c5d1SDavid du Colombier if(i < 0)
2403e12c5d1SDavid du Colombier goto error;
2413e12c5d1SDavid du Colombier if(read(i, buf, sizeof(buf)) >= sizeof(buf))
2423e12c5d1SDavid du Colombier goto error;
2433e12c5d1SDavid du Colombier close(i);
2443e12c5d1SDavid du Colombier p = buf;
2453e12c5d1SDavid du Colombier if(rd_name(&p, timezone.stname))
2463e12c5d1SDavid du Colombier goto error;
2473e12c5d1SDavid du Colombier if(rd_long(&p, &timezone.stdiff))
2483e12c5d1SDavid du Colombier goto error;
2493e12c5d1SDavid du Colombier if(rd_name(&p, timezone.dlname))
2503e12c5d1SDavid du Colombier goto error;
2513e12c5d1SDavid du Colombier if(rd_long(&p, &timezone.dldiff))
2523e12c5d1SDavid du Colombier goto error;
2533e12c5d1SDavid du Colombier for(i=0; i<TZSIZE; i++) {
2543e12c5d1SDavid du Colombier if(rd_long(&p, &timezone.dlpairs[i]))
2553e12c5d1SDavid du Colombier goto error;
2563e12c5d1SDavid du Colombier if(timezone.dlpairs[i] == 0)
2573e12c5d1SDavid du Colombier return;
2583e12c5d1SDavid du Colombier }
2593e12c5d1SDavid du Colombier
2603e12c5d1SDavid du Colombier error:
2613e12c5d1SDavid du Colombier timezone.stdiff = 0;
2623e12c5d1SDavid du Colombier strcpy(timezone.stname, "GMT");
2633e12c5d1SDavid du Colombier timezone.dlpairs[0] = 0;
2643e12c5d1SDavid du Colombier }
2653e12c5d1SDavid du Colombier
2663e12c5d1SDavid du Colombier static
rd_name(char ** f,char * p)2673e12c5d1SDavid du Colombier rd_name(char **f, char *p)
2683e12c5d1SDavid du Colombier {
2693e12c5d1SDavid du Colombier int c, i;
2703e12c5d1SDavid du Colombier
2713e12c5d1SDavid du Colombier for(;;) {
2723e12c5d1SDavid du Colombier c = *(*f)++;
2733e12c5d1SDavid du Colombier if(c != ' ' && c != '\n')
2743e12c5d1SDavid du Colombier break;
2753e12c5d1SDavid du Colombier }
2763e12c5d1SDavid du Colombier for(i=0; i<3; i++) {
2773e12c5d1SDavid du Colombier if(c == ' ' || c == '\n')
2783e12c5d1SDavid du Colombier return 1;
2793e12c5d1SDavid du Colombier *p++ = c;
2803e12c5d1SDavid du Colombier c = *(*f)++;
2813e12c5d1SDavid du Colombier }
2823e12c5d1SDavid du Colombier if(c != ' ' && c != '\n')
2833e12c5d1SDavid du Colombier return 1;
2843e12c5d1SDavid du Colombier *p = 0;
2853e12c5d1SDavid du Colombier return 0;
2863e12c5d1SDavid du Colombier }
2873e12c5d1SDavid du Colombier
2883e12c5d1SDavid du Colombier static
rd_long(char ** f,long * p)2893e12c5d1SDavid du Colombier rd_long(char **f, long *p)
2903e12c5d1SDavid du Colombier {
2913e12c5d1SDavid du Colombier int c, s;
2923e12c5d1SDavid du Colombier long l;
2933e12c5d1SDavid du Colombier
2943e12c5d1SDavid du Colombier s = 0;
2953e12c5d1SDavid du Colombier for(;;) {
2963e12c5d1SDavid du Colombier c = *(*f)++;
2973e12c5d1SDavid du Colombier if(c == '-') {
2983e12c5d1SDavid du Colombier s++;
2993e12c5d1SDavid du Colombier continue;
3003e12c5d1SDavid du Colombier }
3013e12c5d1SDavid du Colombier if(c != ' ' && c != '\n')
3023e12c5d1SDavid du Colombier break;
3033e12c5d1SDavid du Colombier }
3043e12c5d1SDavid du Colombier if(c == 0) {
3053e12c5d1SDavid du Colombier *p = 0;
3063e12c5d1SDavid du Colombier return 0;
3073e12c5d1SDavid du Colombier }
3083e12c5d1SDavid du Colombier l = 0;
3093e12c5d1SDavid du Colombier for(;;) {
3103e12c5d1SDavid du Colombier if(c == ' ' || c == '\n')
3113e12c5d1SDavid du Colombier break;
3123e12c5d1SDavid du Colombier if(c < '0' || c > '9')
3133e12c5d1SDavid du Colombier return 1;
3143e12c5d1SDavid du Colombier l = l*10 + c-'0';
3153e12c5d1SDavid du Colombier c = *(*f)++;
3163e12c5d1SDavid du Colombier }
3173e12c5d1SDavid du Colombier if(s)
3183e12c5d1SDavid du Colombier l = -l;
3193e12c5d1SDavid du Colombier *p = l;
3203e12c5d1SDavid du Colombier return 0;
3213e12c5d1SDavid du Colombier }
322