17c478bd9Sstevel@tonic-gate /* 2*d67944fbSScott Rotondo * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* 77c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 87c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 97c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 107c478bd9Sstevel@tonic-gate */ 117c478bd9Sstevel@tonic-gate 127c478bd9Sstevel@tonic-gate /* 137c478bd9Sstevel@tonic-gate * This localtime is a modified version of offtime from libc, which does not 147c478bd9Sstevel@tonic-gate * bother to figure out the time zone from the kernel, from environment 157c478bd9Sstevel@tonic-gate * variables, or from Unix files. 167c478bd9Sstevel@tonic-gate */ 177c478bd9Sstevel@tonic-gate 187c478bd9Sstevel@tonic-gate #include <sys/types.h> 197c478bd9Sstevel@tonic-gate #include <sys/salib.h> 207c478bd9Sstevel@tonic-gate #include <tzfile.h> 217c478bd9Sstevel@tonic-gate #include <errno.h> 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate static int mon_lengths[2][MONS_PER_YEAR] = { 247c478bd9Sstevel@tonic-gate 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 257c478bd9Sstevel@tonic-gate 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 267c478bd9Sstevel@tonic-gate }; 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate static int year_lengths[2] = { 297c478bd9Sstevel@tonic-gate DAYS_PER_NYEAR, DAYS_PER_LYEAR 307c478bd9Sstevel@tonic-gate }; 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate struct tm * 337c478bd9Sstevel@tonic-gate localtime(const time_t *clock) 347c478bd9Sstevel@tonic-gate { 357c478bd9Sstevel@tonic-gate struct tm *tmp; 367c478bd9Sstevel@tonic-gate long days; 377c478bd9Sstevel@tonic-gate long rem; 387c478bd9Sstevel@tonic-gate int y; 397c478bd9Sstevel@tonic-gate int yleap; 407c478bd9Sstevel@tonic-gate int *ip; 417c478bd9Sstevel@tonic-gate static struct tm tm; 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate tmp = &tm; 447c478bd9Sstevel@tonic-gate days = *clock / SECS_PER_DAY; 457c478bd9Sstevel@tonic-gate rem = *clock % SECS_PER_DAY; 467c478bd9Sstevel@tonic-gate while (rem < 0) { 477c478bd9Sstevel@tonic-gate rem += SECS_PER_DAY; 487c478bd9Sstevel@tonic-gate --days; 497c478bd9Sstevel@tonic-gate } 507c478bd9Sstevel@tonic-gate while (rem >= SECS_PER_DAY) { 517c478bd9Sstevel@tonic-gate rem -= SECS_PER_DAY; 527c478bd9Sstevel@tonic-gate ++days; 537c478bd9Sstevel@tonic-gate } 547c478bd9Sstevel@tonic-gate tmp->tm_hour = (int)(rem / SECS_PER_HOUR); 557c478bd9Sstevel@tonic-gate rem = rem % SECS_PER_HOUR; 567c478bd9Sstevel@tonic-gate tmp->tm_min = (int)(rem / SECS_PER_MIN); 577c478bd9Sstevel@tonic-gate tmp->tm_sec = (int)(rem % SECS_PER_MIN); 587c478bd9Sstevel@tonic-gate tmp->tm_wday = (int)((EPOCH_WDAY + days) % DAYS_PER_WEEK); 597c478bd9Sstevel@tonic-gate if (tmp->tm_wday < 0) 607c478bd9Sstevel@tonic-gate tmp->tm_wday += DAYS_PER_WEEK; 617c478bd9Sstevel@tonic-gate y = EPOCH_YEAR; 627c478bd9Sstevel@tonic-gate if (days >= 0) { 637c478bd9Sstevel@tonic-gate for (;;) { 647c478bd9Sstevel@tonic-gate yleap = isleap(y); 657c478bd9Sstevel@tonic-gate if (days < (long)year_lengths[yleap]) 667c478bd9Sstevel@tonic-gate break; 677c478bd9Sstevel@tonic-gate if (++y > 9999) { 687c478bd9Sstevel@tonic-gate errno = EOVERFLOW; 697c478bd9Sstevel@tonic-gate return (NULL); 707c478bd9Sstevel@tonic-gate } 717c478bd9Sstevel@tonic-gate days = days - (long)year_lengths[yleap]; 727c478bd9Sstevel@tonic-gate } 737c478bd9Sstevel@tonic-gate } else { 747c478bd9Sstevel@tonic-gate do { 757c478bd9Sstevel@tonic-gate if (--y < 0) { 767c478bd9Sstevel@tonic-gate errno = EOVERFLOW; 777c478bd9Sstevel@tonic-gate return (NULL); 787c478bd9Sstevel@tonic-gate } 797c478bd9Sstevel@tonic-gate yleap = isleap(y); 807c478bd9Sstevel@tonic-gate days = days + (long)year_lengths[yleap]; 817c478bd9Sstevel@tonic-gate } while (days < 0); 827c478bd9Sstevel@tonic-gate } 837c478bd9Sstevel@tonic-gate tmp->tm_year = y - TM_YEAR_BASE; 847c478bd9Sstevel@tonic-gate tmp->tm_yday = (int)days; 857c478bd9Sstevel@tonic-gate ip = mon_lengths[yleap]; 867c478bd9Sstevel@tonic-gate for (tmp->tm_mon = 0; days >= (long)ip[tmp->tm_mon]; ++(tmp->tm_mon)) 877c478bd9Sstevel@tonic-gate days = days - (long)ip[tmp->tm_mon]; 887c478bd9Sstevel@tonic-gate tmp->tm_mday = (int)(days + 1); 897c478bd9Sstevel@tonic-gate tmp->tm_isdst = 0; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate return (tmp); 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate /* 957c478bd9Sstevel@tonic-gate * So is ctime... 967c478bd9Sstevel@tonic-gate */ 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * This routine converts time as follows. 1007c478bd9Sstevel@tonic-gate * The epoch is 0000 Jan 1 1970 GMT. 1017c478bd9Sstevel@tonic-gate * The argument time is in seconds since then. 1027c478bd9Sstevel@tonic-gate * The localtime(t) entry returns a pointer to an array 1037c478bd9Sstevel@tonic-gate * containing 1047c478bd9Sstevel@tonic-gate * seconds (0-59) 1057c478bd9Sstevel@tonic-gate * minutes (0-59) 1067c478bd9Sstevel@tonic-gate * hours (0-23) 1077c478bd9Sstevel@tonic-gate * day of month (1-31) 1087c478bd9Sstevel@tonic-gate * month (0-11) 1097c478bd9Sstevel@tonic-gate * year-1970 1107c478bd9Sstevel@tonic-gate * weekday (0-6, Sun is 0) 1117c478bd9Sstevel@tonic-gate * day of the year 1127c478bd9Sstevel@tonic-gate * daylight savings flag 1137c478bd9Sstevel@tonic-gate * 1147c478bd9Sstevel@tonic-gate * The routine corrects for daylight saving 1157c478bd9Sstevel@tonic-gate * time and will work in any time zone provided 1167c478bd9Sstevel@tonic-gate * "timezone" is adjusted to the difference between 1177c478bd9Sstevel@tonic-gate * Greenwich and local standard time (measured in seconds). 1187c478bd9Sstevel@tonic-gate * In places like Michigan "daylight" must 1197c478bd9Sstevel@tonic-gate * be initialized to 0 to prevent the conversion 1207c478bd9Sstevel@tonic-gate * to daylight time. 1217c478bd9Sstevel@tonic-gate * There is a table which accounts for the peculiarities 1227c478bd9Sstevel@tonic-gate * undergone by daylight time in 1974-1975. 1237c478bd9Sstevel@tonic-gate * 1247c478bd9Sstevel@tonic-gate * The routine does not work 1257c478bd9Sstevel@tonic-gate * in Saudi Arabia which runs on Solar time. 1267c478bd9Sstevel@tonic-gate * 1277c478bd9Sstevel@tonic-gate * asctime(tvec) 1287c478bd9Sstevel@tonic-gate * where tvec is produced by localtime 1297c478bd9Sstevel@tonic-gate * returns a ptr to a character string 1307c478bd9Sstevel@tonic-gate * that has the ascii time in the form 1317c478bd9Sstevel@tonic-gate * Thu Jan 01 00:00:00 1970\n\0 1327c478bd9Sstevel@tonic-gate * 01234567890123456789012345 1337c478bd9Sstevel@tonic-gate * 0 1 2 1347c478bd9Sstevel@tonic-gate * 1357c478bd9Sstevel@tonic-gate * ctime(t) just calls localtime, then asctime. 1367c478bd9Sstevel@tonic-gate * 1377c478bd9Sstevel@tonic-gate * tzset() looks for an environment variable named 1387c478bd9Sstevel@tonic-gate * TZ. 1397c478bd9Sstevel@tonic-gate * If the variable is present, it will set the external 1407c478bd9Sstevel@tonic-gate * variables "timezone", "altzone", "daylight", and "tzname" 1417c478bd9Sstevel@tonic-gate * appropriately. It is called by localtime, and 1427c478bd9Sstevel@tonic-gate * may also be called explicitly by the user. 1437c478bd9Sstevel@tonic-gate */ 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate #define dysize(A) (((A)%4)? 365: 366) 1487c478bd9Sstevel@tonic-gate #define CBUFSIZ 26 1497c478bd9Sstevel@tonic-gate 150*d67944fbSScott Rotondo static char *ct_numb(); 151*d67944fbSScott Rotondo 1527c478bd9Sstevel@tonic-gate /* 1537c478bd9Sstevel@tonic-gate * POSIX.1c standard version of the function asctime_r. 1547c478bd9Sstevel@tonic-gate * User gets it via static asctime_r from the header file. 1557c478bd9Sstevel@tonic-gate */ 1567c478bd9Sstevel@tonic-gate char * 1577c478bd9Sstevel@tonic-gate __posix_asctime_r(const struct tm *t, char *cbuf) 1587c478bd9Sstevel@tonic-gate { 1597c478bd9Sstevel@tonic-gate const char *Date = "Day Mon 00 00:00:00 1900\n"; 1607c478bd9Sstevel@tonic-gate const char *Day = "SunMonTueWedThuFriSat"; 1617c478bd9Sstevel@tonic-gate const char *Month = "JanFebMarAprMayJunJulAugSepOctNovDec"; 1627c478bd9Sstevel@tonic-gate const char *ncp; 1637c478bd9Sstevel@tonic-gate const int *tp; 1647c478bd9Sstevel@tonic-gate char *cp; 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate if (t == NULL) 1677c478bd9Sstevel@tonic-gate return (NULL); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate cp = cbuf; 1707257d1b4Sraf for (ncp = Date; *cp++ = *ncp++; /* */) 1717257d1b4Sraf ; 1727c478bd9Sstevel@tonic-gate ncp = Day + (3*t->tm_wday); 1737c478bd9Sstevel@tonic-gate cp = cbuf; 1747c478bd9Sstevel@tonic-gate *cp++ = *ncp++; 1757c478bd9Sstevel@tonic-gate *cp++ = *ncp++; 1767c478bd9Sstevel@tonic-gate *cp++ = *ncp++; 1777c478bd9Sstevel@tonic-gate cp++; 1787c478bd9Sstevel@tonic-gate tp = &t->tm_mon; 1797c478bd9Sstevel@tonic-gate ncp = Month + ((*tp) * 3); 1807c478bd9Sstevel@tonic-gate *cp++ = *ncp++; 1817c478bd9Sstevel@tonic-gate *cp++ = *ncp++; 1827c478bd9Sstevel@tonic-gate *cp++ = *ncp++; 1837c478bd9Sstevel@tonic-gate cp = ct_numb(cp, *--tp); 1847c478bd9Sstevel@tonic-gate cp = ct_numb(cp, *--tp+100); 1857c478bd9Sstevel@tonic-gate cp = ct_numb(cp, *--tp+100); 1867c478bd9Sstevel@tonic-gate cp = ct_numb(cp, *--tp+100); 1877c478bd9Sstevel@tonic-gate if (t->tm_year > 9999) { 1887c478bd9Sstevel@tonic-gate errno = EOVERFLOW; 1897c478bd9Sstevel@tonic-gate return (NULL); 1907c478bd9Sstevel@tonic-gate } else { 1917c478bd9Sstevel@tonic-gate uint_t hun = 19 + (t->tm_year / 100); 1927c478bd9Sstevel@tonic-gate cp[1] = (hun / 10) + '0'; 1937c478bd9Sstevel@tonic-gate cp[2] = (hun % 10) + '0'; 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate cp += 2; 1967c478bd9Sstevel@tonic-gate cp = ct_numb(cp, t->tm_year+100); 1977c478bd9Sstevel@tonic-gate return (cbuf); 1987c478bd9Sstevel@tonic-gate } 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate /* 2017c478bd9Sstevel@tonic-gate * POSIX.1c Draft-6 version of the function asctime_r. 2027c478bd9Sstevel@tonic-gate * It was implemented by Solaris 2.3. 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate char * 2057257d1b4Sraf asctime_r(const struct tm *t, char *cbuf, int buflen) 2067c478bd9Sstevel@tonic-gate { 2077c478bd9Sstevel@tonic-gate if (buflen < CBUFSIZ) { 2087c478bd9Sstevel@tonic-gate errno = ERANGE; 2097c478bd9Sstevel@tonic-gate return (NULL); 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate return (__posix_asctime_r(t, cbuf)); 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate char * 2157c478bd9Sstevel@tonic-gate ctime(const time_t *t) 2167c478bd9Sstevel@tonic-gate { 2177c478bd9Sstevel@tonic-gate return (asctime(localtime(t))); 2187c478bd9Sstevel@tonic-gate } 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate char * 2227c478bd9Sstevel@tonic-gate asctime(const struct tm *t) 2237c478bd9Sstevel@tonic-gate { 2247c478bd9Sstevel@tonic-gate static char cbuf[CBUFSIZ]; 2257c478bd9Sstevel@tonic-gate 2267257d1b4Sraf return (asctime_r(t, cbuf, CBUFSIZ)); 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate static char * 2317c478bd9Sstevel@tonic-gate ct_numb(char *cp, int n) 2327c478bd9Sstevel@tonic-gate { 2337c478bd9Sstevel@tonic-gate cp++; 2347c478bd9Sstevel@tonic-gate if (n >= 10) 2357c478bd9Sstevel@tonic-gate *cp++ = (n/10)%10 + '0'; 2367c478bd9Sstevel@tonic-gate else 2377c478bd9Sstevel@tonic-gate *cp++ = ' '; /* Pad with blanks */ 2387c478bd9Sstevel@tonic-gate *cp++ = n%10 + '0'; 2397c478bd9Sstevel@tonic-gate return (cp); 2407c478bd9Sstevel@tonic-gate } 241