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 54 #define TZSIZE 150 55 static void readtimezone(void); 56 static int rd_name(char**, char*); 57 static int rd_long(char**, long*); 58 static 59 struct 60 { 61 char stname[4]; 62 char dlname[4]; 63 long stdiff; 64 long dldiff; 65 long dlpairs[TZSIZE]; 66 } timezone; 67 68 char* 69 ctime(const time_t *t) 70 { 71 return asctime(localtime(t)); 72 } 73 74 struct tm* 75 localtime(const time_t *timp) 76 { 77 struct tm *ct; 78 time_t t, tim; 79 long *p; 80 int i, dlflag; 81 82 tim = *timp; 83 if(timezone.stname[0] == 0) 84 readtimezone(); 85 t = tim + timezone.stdiff; 86 dlflag = 0; 87 for(p = timezone.dlpairs; *p; p += 2) 88 if(t >= p[0]) 89 if(t < p[1]) { 90 t = tim + timezone.dldiff; 91 dlflag++; 92 break; 93 } 94 ct = gmtime(&t); 95 ct->tm_isdst = dlflag; 96 return ct; 97 } 98 99 struct tm* 100 gmtime(const time_t *timp) 101 { 102 int d0, d1; 103 long hms, day; 104 time_t tim; 105 static struct tm xtime; 106 107 tim = *timp; 108 /* 109 * break initial number into days 110 */ 111 hms = tim % 86400L; 112 day = tim / 86400L; 113 if(hms < 0) { 114 hms += 86400L; 115 day -= 1; 116 } 117 118 /* 119 * generate hours:minutes:seconds 120 */ 121 xtime.tm_sec = hms % 60; 122 d1 = hms / 60; 123 xtime.tm_min = d1 % 60; 124 d1 /= 60; 125 xtime.tm_hour = d1; 126 127 /* 128 * day is the day number. 129 * generate day of the week. 130 * The addend is 4 mod 7 (1/1/1970 was Thursday) 131 */ 132 133 xtime.tm_wday = (day + 7340036L) % 7; 134 135 /* 136 * year number 137 */ 138 if(day >= 0) 139 for(d1 = 70; day >= dysize(d1); d1++) 140 day -= dysize(d1); 141 else 142 for (d1 = 70; day < 0; d1--) 143 day += dysize(d1-1); 144 xtime.tm_year = d1; 145 xtime.tm_yday = d0 = day; 146 147 /* 148 * generate month 149 */ 150 151 if(dysize(d1) == 366) 152 dmsize[1] = 29; 153 for(d1 = 0; d0 >= dmsize[d1]; d1++) 154 d0 -= dmsize[d1]; 155 dmsize[1] = 28; 156 xtime.tm_mday = d0 + 1; 157 xtime.tm_mon = d1; 158 xtime.tm_isdst = 0; 159 return &xtime; 160 } 161 162 char* 163 asctime(const struct tm *t) 164 { 165 char *ncp; 166 static char cbuf[30]; 167 168 strcpy(cbuf, "Thu Jan 01 00:00:00 1970\n"); 169 ncp = &"SunMonTueWedThuFriSat"[t->tm_wday*3]; 170 cbuf[0] = *ncp++; 171 cbuf[1] = *ncp++; 172 cbuf[2] = *ncp; 173 ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[t->tm_mon*3]; 174 cbuf[4] = *ncp++; 175 cbuf[5] = *ncp++; 176 cbuf[6] = *ncp; 177 ct_numb(cbuf+8, t->tm_mday); 178 ct_numb(cbuf+11, t->tm_hour+100); 179 ct_numb(cbuf+14, t->tm_min+100); 180 ct_numb(cbuf+17, t->tm_sec+100); 181 if(t->tm_year >= 100) { 182 cbuf[20] = '2'; 183 cbuf[21] = '0'; 184 } 185 ct_numb(cbuf+22, t->tm_year+100); 186 return cbuf; 187 } 188 189 static 190 dysize(int y) 191 { 192 193 if((y%4) == 0) 194 return 366; 195 return 365; 196 } 197 198 static 199 void 200 ct_numb(char *cp, int n) 201 { 202 203 cp[0] = ' '; 204 if(n >= 10) 205 cp[0] = (n/10)%10 + '0'; 206 cp[1] = n%10 + '0'; 207 } 208 209 static 210 void 211 readtimezone(void) 212 { 213 char buf[TZSIZE*11+30], *p; 214 int i; 215 216 memset(buf, 0, sizeof(buf)); 217 i = open("/env/timezone", 0); 218 if(i < 0) 219 goto error; 220 if(read(i, buf, sizeof(buf)) >= sizeof(buf)) 221 goto error; 222 close(i); 223 p = buf; 224 if(rd_name(&p, timezone.stname)) 225 goto error; 226 if(rd_long(&p, &timezone.stdiff)) 227 goto error; 228 if(rd_name(&p, timezone.dlname)) 229 goto error; 230 if(rd_long(&p, &timezone.dldiff)) 231 goto error; 232 for(i=0; i<TZSIZE; i++) { 233 if(rd_long(&p, &timezone.dlpairs[i])) 234 goto error; 235 if(timezone.dlpairs[i] == 0) 236 return; 237 } 238 239 error: 240 timezone.stdiff = 0; 241 strcpy(timezone.stname, "GMT"); 242 timezone.dlpairs[0] = 0; 243 } 244 245 static 246 rd_name(char **f, char *p) 247 { 248 int c, i; 249 250 for(;;) { 251 c = *(*f)++; 252 if(c != ' ' && c != '\n') 253 break; 254 } 255 for(i=0; i<3; i++) { 256 if(c == ' ' || c == '\n') 257 return 1; 258 *p++ = c; 259 c = *(*f)++; 260 } 261 if(c != ' ' && c != '\n') 262 return 1; 263 *p = 0; 264 return 0; 265 } 266 267 static 268 rd_long(char **f, long *p) 269 { 270 int c, s; 271 long l; 272 273 s = 0; 274 for(;;) { 275 c = *(*f)++; 276 if(c == '-') { 277 s++; 278 continue; 279 } 280 if(c != ' ' && c != '\n') 281 break; 282 } 283 if(c == 0) { 284 *p = 0; 285 return 0; 286 } 287 l = 0; 288 for(;;) { 289 if(c == ' ' || c == '\n') 290 break; 291 if(c < '0' || c > '9') 292 return 1; 293 l = l*10 + c-'0'; 294 c = *(*f)++; 295 } 296 if(s) 297 l = -l; 298 *p = l; 299 return 0; 300 } 301