1 #include <u.h> 2 #include <libc.h> 3 4 #define TZSIZE 150 5 static void readtimezone(void); 6 static int rd_name(char**, char*); 7 static int rd_long(char**, long*); 8 static 9 struct 10 { 11 char stname[4]; 12 char dlname[4]; 13 long stdiff; 14 long dldiff; 15 long dlpairs[TZSIZE]; 16 } timezone; 17 18 #define SEC2MIN 60L 19 #define SEC2HOUR (60L*SEC2MIN) 20 #define SEC2DAY (24L*SEC2HOUR) 21 22 /* 23 * days per month plus days/year 24 */ 25 static int dmsize[] = 26 { 27 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 28 }; 29 static int ldmsize[] = 30 { 31 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 32 }; 33 34 /* 35 * return the days/month for the given year 36 */ 37 static int * 38 yrsize(int y) 39 { 40 if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0)) 41 return ldmsize; 42 else 43 return dmsize; 44 } 45 46 /* 47 * compute seconds since Jan 1 1970 GMT 48 * and convert to our timezone. 49 */ 50 long 51 tm2sec(Tm *tm) 52 { 53 long secs; 54 int i, yday, year, *d2m; 55 56 if(strcmp(tm->zone, "GMT") != 0 && timezone.stname[0] == 0) 57 readtimezone(); 58 secs = 0; 59 60 /* 61 * seconds per year 62 */ 63 year = tm->year + 1900; 64 for(i = 1970; i < year; i++){ 65 d2m = yrsize(i); 66 secs += d2m[0] * SEC2DAY; 67 } 68 69 /* 70 * if mday is set, use mon and mday to compute yday 71 */ 72 if(tm->mday){ 73 yday = 0; 74 d2m = yrsize(year); 75 for(i=0; i<tm->mon; i++) 76 yday += d2m[i+1]; 77 yday += tm->mday-1; 78 }else{ 79 yday = tm->yday; 80 } 81 secs += yday * SEC2DAY; 82 83 /* 84 * hours, minutes, seconds 85 */ 86 secs += tm->hour * SEC2HOUR; 87 secs += tm->min * SEC2MIN; 88 secs += tm->sec; 89 90 /* 91 * Only handles zones mentioned in /env/timezone, 92 * but things get too ambiguous otherwise. 93 */ 94 if(strcmp(tm->zone, timezone.stname) == 0) 95 secs -= timezone.stdiff; 96 else if(strcmp(tm->zone, timezone.dlname) == 0) 97 secs -= timezone.dldiff; 98 if(secs < 0) 99 secs = 0; 100 return secs; 101 } 102 103 static 104 void 105 readtimezone(void) 106 { 107 char buf[TZSIZE*11+30], *p; 108 int i; 109 110 memset(buf, 0, sizeof(buf)); 111 i = open("/env/timezone", 0); 112 if(i < 0) 113 goto error; 114 if(read(i, buf, sizeof(buf)) >= sizeof(buf)) 115 goto error; 116 close(i); 117 p = buf; 118 if(rd_name(&p, timezone.stname)) 119 goto error; 120 if(rd_long(&p, &timezone.stdiff)) 121 goto error; 122 if(rd_name(&p, timezone.dlname)) 123 goto error; 124 if(rd_long(&p, &timezone.dldiff)) 125 goto error; 126 for(i=0; i<TZSIZE; i++) { 127 if(rd_long(&p, &timezone.dlpairs[i])) 128 goto error; 129 if(timezone.dlpairs[i] == 0) 130 return; 131 } 132 133 error: 134 timezone.stdiff = 0; 135 strcpy(timezone.stname, "GMT"); 136 timezone.dlpairs[0] = 0; 137 } 138 139 static int 140 rd_name(char **f, char *p) 141 { 142 int c, i; 143 144 for(;;) { 145 c = *(*f)++; 146 if(c != ' ' && c != '\n') 147 break; 148 } 149 for(i=0; i<3; i++) { 150 if(c == ' ' || c == '\n') 151 return 1; 152 *p++ = c; 153 c = *(*f)++; 154 } 155 if(c != ' ' && c != '\n') 156 return 1; 157 *p = 0; 158 return 0; 159 } 160 161 static int 162 rd_long(char **f, long *p) 163 { 164 int c, s; 165 long l; 166 167 s = 0; 168 for(;;) { 169 c = *(*f)++; 170 if(c == '-') { 171 s++; 172 continue; 173 } 174 if(c != ' ' && c != '\n') 175 break; 176 } 177 if(c == 0) { 178 *p = 0; 179 return 0; 180 } 181 l = 0; 182 for(;;) { 183 if(c == ' ' || c == '\n') 184 break; 185 if(c < '0' || c > '9') 186 return 1; 187 l = l*10 + c-'0'; 188 c = *(*f)++; 189 } 190 if(s) 191 l = -l; 192 *p = l; 193 return 0; 194 } 195