1 /* 2 * This routine converts time as follows. 3 * The epoch is 0000 Jan 1 1970 GMT. 4 * The argument time is in seconds since then. 5 * The localtime(t) entry returns a pointer to an array 6 * containing 7 * 8 * seconds (0-59) 9 * minutes (0-59) 10 * hours (0-23) 11 * day of month (1-31) 12 * month (0-11) 13 * year-1970 14 * weekday (0-6, Sun is 0) 15 * day of the year 16 * daylight savings flag 17 * 18 * The routine gets the daylight savings time from the environment. 19 * 20 * asctime(tvec)) 21 * where tvec is produced by localtime 22 * returns a ptr to a character string 23 * that has the ascii time in the form 24 * 25 * \\ 26 * Thu Jan 01 00:00:00 1970n0 27 * 01234567890123456789012345 28 * 0 1 2 29 * 30 * ctime(t) just calls localtime, then asctime. 31 */ 32 33 #include <sys/types.h> 34 #include <sys/stat.h> 35 #include <fcntl.h> 36 #include <time.h> 37 #include <unistd.h> 38 #include <string.h> 39 40 static char dmsize[12] = 41 { 42 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 43 }; 44 45 /* 46 * The following table is used for 1974 and 1975 and 47 * gives the day number of the first day after the Sunday of the 48 * change. 49 */ 50 51 static int dysize(int); 52 static void ct_numb(char*, int); 53 static void readtimezone(void); 54 static int rd_name(char**, char*); 55 static int rd_long(char**, long*); 56 57 #define TZSIZE 150 58 59 static 60 struct 61 { 62 char stname[4]; 63 char dlname[4]; 64 long stdiff; 65 long dldiff; 66 long dlpairs[TZSIZE]; 67 } timezone; 68 69 char* 70 ctime(const time_t *t) 71 { 72 return asctime(localtime(t)); 73 } 74 75 struct tm* 76 gmtime_r(const time_t *timp, struct tm *result) 77 { 78 int d0, d1; 79 long hms, day; 80 time_t tim; 81 82 tim = *timp; 83 /* 84 * break initial number into days 85 */ 86 hms = tim % 86400L; 87 day = tim / 86400L; 88 if(hms < 0) { 89 hms += 86400L; 90 day -= 1; 91 } 92 93 /* 94 * generate hours:minutes:seconds 95 */ 96 result->tm_sec = hms % 60; 97 d1 = hms / 60; 98 result->tm_min = d1 % 60; 99 d1 /= 60; 100 result->tm_hour = d1; 101 102 /* 103 * day is the day number. 104 * generate day of the week. 105 * The addend is 4 mod 7 (1/1/1970 was Thursday) 106 */ 107 108 result->tm_wday = (day + 7340036L) % 7; 109 110 /* 111 * year number 112 */ 113 if(day >= 0) 114 for(d1 = 70; day >= dysize(d1); d1++) 115 day -= dysize(d1); 116 else 117 for (d1 = 70; day < 0; d1--) 118 day += dysize(d1-1); 119 result->tm_year = d1; 120 result->tm_yday = d0 = day; 121 122 /* 123 * generate month 124 */ 125 126 if(dysize(d1) == 366) 127 dmsize[1] = 29; 128 for(d1 = 0; d0 >= dmsize[d1]; d1++) 129 d0 -= dmsize[d1]; 130 dmsize[1] = 28; 131 result->tm_mday = d0 + 1; 132 result->tm_mon = d1; 133 result->tm_isdst = 0; 134 return result; 135 } 136 137 struct tm* 138 gmtime(const time_t *timp) 139 { 140 static struct tm xtime; 141 142 return gmtime_r(timp, &xtime); 143 } 144 145 struct tm* 146 localtime_r(const time_t *timp, struct tm *result) 147 { 148 struct tm *ct; 149 time_t t, tim; 150 long *p; 151 int i, dlflag; 152 153 tim = *timp; 154 if(timezone.stname[0] == 0) 155 readtimezone(); 156 t = tim + timezone.stdiff; 157 dlflag = 0; 158 for(p = timezone.dlpairs; *p; p += 2) 159 if(t >= p[0]) 160 if(t < p[1]) { 161 t = tim + timezone.dldiff; 162 dlflag++; 163 break; 164 } 165 ct = gmtime_r(&t, result); 166 ct->tm_isdst = dlflag; 167 return ct; 168 } 169 170 struct tm* 171 localtime(const time_t *timp) 172 { 173 static struct tm xtime; 174 175 return localtime_r(timp, &xtime); 176 } 177 178 char* 179 asctime_r(const struct tm *t, char *buf) 180 { 181 char *ncp; 182 183 strcpy(buf, "Thu Jan 01 00:00:00 1970\n"); 184 ncp = &"SunMonTueWedThuFriSat"[t->tm_wday*3]; 185 buf[0] = *ncp++; 186 buf[1] = *ncp++; 187 buf[2] = *ncp; 188 ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[t->tm_mon*3]; 189 buf[4] = *ncp++; 190 buf[5] = *ncp++; 191 buf[6] = *ncp; 192 ct_numb(buf+8, t->tm_mday); 193 ct_numb(buf+11, t->tm_hour+100); 194 ct_numb(buf+14, t->tm_min+100); 195 ct_numb(buf+17, t->tm_sec+100); 196 if(t->tm_year >= 100) { 197 buf[20] = '2'; 198 buf[21] = '0'; 199 } 200 ct_numb(buf+22, t->tm_year+100); 201 return buf; 202 } 203 204 char* 205 asctime(const struct tm *t) 206 { 207 static char cbuf[30]; 208 209 return asctime_r(t, cbuf); 210 } 211 212 static 213 dysize(int y) 214 { 215 if((y%4) == 0) 216 return 366; 217 return 365; 218 } 219 220 static 221 void 222 ct_numb(char *cp, int n) 223 { 224 cp[0] = ' '; 225 if(n >= 10) 226 cp[0] = (n/10)%10 + '0'; 227 cp[1] = n%10 + '0'; 228 } 229 230 static 231 void 232 readtimezone(void) 233 { 234 char buf[TZSIZE*11+30], *p; 235 int i; 236 237 memset(buf, 0, sizeof(buf)); 238 i = open("/env/timezone", 0); 239 if(i < 0) 240 goto error; 241 if(read(i, buf, sizeof(buf)) >= sizeof(buf)) 242 goto error; 243 close(i); 244 p = buf; 245 if(rd_name(&p, timezone.stname)) 246 goto error; 247 if(rd_long(&p, &timezone.stdiff)) 248 goto error; 249 if(rd_name(&p, timezone.dlname)) 250 goto error; 251 if(rd_long(&p, &timezone.dldiff)) 252 goto error; 253 for(i=0; i<TZSIZE; i++) { 254 if(rd_long(&p, &timezone.dlpairs[i])) 255 goto error; 256 if(timezone.dlpairs[i] == 0) 257 return; 258 } 259 260 error: 261 timezone.stdiff = 0; 262 strcpy(timezone.stname, "GMT"); 263 timezone.dlpairs[0] = 0; 264 } 265 266 static 267 rd_name(char **f, char *p) 268 { 269 int c, i; 270 271 for(;;) { 272 c = *(*f)++; 273 if(c != ' ' && c != '\n') 274 break; 275 } 276 for(i=0; i<3; i++) { 277 if(c == ' ' || c == '\n') 278 return 1; 279 *p++ = c; 280 c = *(*f)++; 281 } 282 if(c != ' ' && c != '\n') 283 return 1; 284 *p = 0; 285 return 0; 286 } 287 288 static 289 rd_long(char **f, long *p) 290 { 291 int c, s; 292 long l; 293 294 s = 0; 295 for(;;) { 296 c = *(*f)++; 297 if(c == '-') { 298 s++; 299 continue; 300 } 301 if(c != ' ' && c != '\n') 302 break; 303 } 304 if(c == 0) { 305 *p = 0; 306 return 0; 307 } 308 l = 0; 309 for(;;) { 310 if(c == ' ' || c == '\n') 311 break; 312 if(c < '0' || c > '9') 313 return 1; 314 l = l*10 + c-'0'; 315 c = *(*f)++; 316 } 317 if(s) 318 l = -l; 319 *p = l; 320 return 0; 321 } 322