14297a3b0SGarrett D'Amore /* 26b5e5868SGarrett D'Amore * Copyright 2010, Nexenta Systems, Inc. All rights reserved. 34297a3b0SGarrett D'Amore * Copyright (c) 1994 Powerdog Industries. All rights reserved. 44297a3b0SGarrett D'Amore * 54297a3b0SGarrett D'Amore * Redistribution and use in source and binary forms, with or without 64297a3b0SGarrett D'Amore * modification, are permitted provided that the following conditions 74297a3b0SGarrett D'Amore * are met: 8*5aec55ebSGarrett D'Amore * 94297a3b0SGarrett D'Amore * 1. Redistributions of source code must retain the above copyright 104297a3b0SGarrett D'Amore * notice, this list of conditions and the following disclaimer. 11*5aec55ebSGarrett D'Amore * 124297a3b0SGarrett D'Amore * 2. Redistributions in binary form must reproduce the above copyright 134297a3b0SGarrett D'Amore * notice, this list of conditions and the following disclaimer 144297a3b0SGarrett D'Amore * in the documentation and/or other materials provided with the 154297a3b0SGarrett D'Amore * distribution. 164297a3b0SGarrett D'Amore * 174297a3b0SGarrett D'Amore * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY 184297a3b0SGarrett D'Amore * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 194297a3b0SGarrett D'Amore * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 204297a3b0SGarrett D'Amore * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE 214297a3b0SGarrett D'Amore * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 224297a3b0SGarrett D'Amore * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 234297a3b0SGarrett D'Amore * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 244297a3b0SGarrett D'Amore * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 254297a3b0SGarrett D'Amore * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 264297a3b0SGarrett D'Amore * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 274297a3b0SGarrett D'Amore * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*5aec55ebSGarrett D'Amore * 29*5aec55ebSGarrett D'Amore * The views and conclusions contained in the software and documentation 30*5aec55ebSGarrett D'Amore * are those of the authors and should not be interpreted as representing 31*5aec55ebSGarrett D'Amore * official policies, either expressed or implied, of Powerdog Industries. 324297a3b0SGarrett D'Amore */ 33*5aec55ebSGarrett D'Amore 344297a3b0SGarrett D'Amore #include "lint.h" 354297a3b0SGarrett D'Amore #include <time.h> 364297a3b0SGarrett D'Amore #include <ctype.h> 374297a3b0SGarrett D'Amore #include <errno.h> 384297a3b0SGarrett D'Amore #include <stdlib.h> 394297a3b0SGarrett D'Amore #include <string.h> 404297a3b0SGarrett D'Amore #include <pthread.h> 414297a3b0SGarrett D'Amore #include <alloca.h> 424297a3b0SGarrett D'Amore #include "timelocal.h" 434297a3b0SGarrett D'Amore 444297a3b0SGarrett D'Amore #define asizeof(a) (sizeof (a) / sizeof ((a)[0])) 454297a3b0SGarrett D'Amore 464297a3b0SGarrett D'Amore static char * 474297a3b0SGarrett D'Amore __strptime(const char *buf, const char *fmt, struct tm *tm) 484297a3b0SGarrett D'Amore { 494297a3b0SGarrett D'Amore char c; 504297a3b0SGarrett D'Amore const char *ptr; 514297a3b0SGarrett D'Amore int i, len; 524297a3b0SGarrett D'Amore int Ealternative, Oalternative; 534297a3b0SGarrett D'Amore struct lc_time_T *tptr = __get_current_time_locale(); 544297a3b0SGarrett D'Amore 554297a3b0SGarrett D'Amore ptr = fmt; 564297a3b0SGarrett D'Amore while (*ptr != 0) { 574297a3b0SGarrett D'Amore if (*buf == 0) 584297a3b0SGarrett D'Amore break; 594297a3b0SGarrett D'Amore 604297a3b0SGarrett D'Amore c = *ptr++; 614297a3b0SGarrett D'Amore 624297a3b0SGarrett D'Amore if (c != '%') { 634297a3b0SGarrett D'Amore if (isspace((unsigned char)c)) 644297a3b0SGarrett D'Amore while (*buf != 0 && 654297a3b0SGarrett D'Amore isspace((unsigned char)*buf)) 664297a3b0SGarrett D'Amore buf++; 674297a3b0SGarrett D'Amore else if (c != *buf++) 684297a3b0SGarrett D'Amore return (0); 694297a3b0SGarrett D'Amore continue; 704297a3b0SGarrett D'Amore } 714297a3b0SGarrett D'Amore 724297a3b0SGarrett D'Amore Ealternative = 0; 734297a3b0SGarrett D'Amore Oalternative = 0; 744297a3b0SGarrett D'Amore label: 754297a3b0SGarrett D'Amore c = *ptr++; 764297a3b0SGarrett D'Amore switch (c) { 774297a3b0SGarrett D'Amore case 0: 784297a3b0SGarrett D'Amore case '%': 794297a3b0SGarrett D'Amore if (*buf++ != '%') 804297a3b0SGarrett D'Amore return (0); 814297a3b0SGarrett D'Amore break; 824297a3b0SGarrett D'Amore 834297a3b0SGarrett D'Amore case '+': 844297a3b0SGarrett D'Amore buf = __strptime(buf, tptr->date_fmt, tm); 854297a3b0SGarrett D'Amore if (buf == 0) 864297a3b0SGarrett D'Amore return (0); 874297a3b0SGarrett D'Amore break; 884297a3b0SGarrett D'Amore 894297a3b0SGarrett D'Amore case 'C': 904297a3b0SGarrett D'Amore if (!isdigit((unsigned char)*buf)) 914297a3b0SGarrett D'Amore return (0); 924297a3b0SGarrett D'Amore 934297a3b0SGarrett D'Amore /* XXX This will break for 3-digit centuries. */ 944297a3b0SGarrett D'Amore len = 2; 954297a3b0SGarrett D'Amore for (i = 0; 964297a3b0SGarrett D'Amore len && isdigit((unsigned char)*buf); 974297a3b0SGarrett D'Amore buf++) { 984297a3b0SGarrett D'Amore i *= 10; 994297a3b0SGarrett D'Amore i += *buf - '0'; 1004297a3b0SGarrett D'Amore len--; 1014297a3b0SGarrett D'Amore } 1024297a3b0SGarrett D'Amore if (i < 19) 1034297a3b0SGarrett D'Amore return (0); 1044297a3b0SGarrett D'Amore 1054297a3b0SGarrett D'Amore tm->tm_year = i * 100 - 1900; 1064297a3b0SGarrett D'Amore break; 1074297a3b0SGarrett D'Amore 1084297a3b0SGarrett D'Amore case 'c': 1094297a3b0SGarrett D'Amore buf = __strptime(buf, tptr->c_fmt, tm); 1104297a3b0SGarrett D'Amore if (buf == 0) 1114297a3b0SGarrett D'Amore return (0); 1124297a3b0SGarrett D'Amore break; 1134297a3b0SGarrett D'Amore 1144297a3b0SGarrett D'Amore case 'D': 1154297a3b0SGarrett D'Amore buf = __strptime(buf, "%m/%d/%y", tm); 1164297a3b0SGarrett D'Amore if (buf == 0) 1174297a3b0SGarrett D'Amore return (0); 1184297a3b0SGarrett D'Amore break; 1194297a3b0SGarrett D'Amore 1204297a3b0SGarrett D'Amore case 'E': 1214297a3b0SGarrett D'Amore if (Ealternative || Oalternative) 1224297a3b0SGarrett D'Amore break; 1234297a3b0SGarrett D'Amore Ealternative++; 1244297a3b0SGarrett D'Amore goto label; 1254297a3b0SGarrett D'Amore 1264297a3b0SGarrett D'Amore case 'O': 1274297a3b0SGarrett D'Amore if (Ealternative || Oalternative) 1284297a3b0SGarrett D'Amore break; 1294297a3b0SGarrett D'Amore Oalternative++; 1304297a3b0SGarrett D'Amore goto label; 1314297a3b0SGarrett D'Amore 1324297a3b0SGarrett D'Amore case 'F': 1334297a3b0SGarrett D'Amore buf = __strptime(buf, "%Y-%m-%d", tm); 1344297a3b0SGarrett D'Amore if (buf == 0) 1354297a3b0SGarrett D'Amore return (0); 1364297a3b0SGarrett D'Amore break; 1374297a3b0SGarrett D'Amore 1384297a3b0SGarrett D'Amore case 'R': 1394297a3b0SGarrett D'Amore buf = __strptime(buf, "%H:%M", tm); 1404297a3b0SGarrett D'Amore if (buf == 0) 1414297a3b0SGarrett D'Amore return (0); 1424297a3b0SGarrett D'Amore break; 1434297a3b0SGarrett D'Amore 1444297a3b0SGarrett D'Amore case 'r': 1454297a3b0SGarrett D'Amore buf = __strptime(buf, tptr->ampm_fmt, tm); 1464297a3b0SGarrett D'Amore if (buf == 0) 1474297a3b0SGarrett D'Amore return (0); 1484297a3b0SGarrett D'Amore break; 1494297a3b0SGarrett D'Amore 1504297a3b0SGarrett D'Amore case 'T': 1514297a3b0SGarrett D'Amore buf = __strptime(buf, "%H:%M:%S", tm); 1524297a3b0SGarrett D'Amore if (buf == 0) 1534297a3b0SGarrett D'Amore return (0); 1544297a3b0SGarrett D'Amore break; 1554297a3b0SGarrett D'Amore 1564297a3b0SGarrett D'Amore case 'X': 1574297a3b0SGarrett D'Amore buf = __strptime(buf, tptr->X_fmt, tm); 1584297a3b0SGarrett D'Amore if (buf == 0) 1594297a3b0SGarrett D'Amore return (0); 1604297a3b0SGarrett D'Amore break; 1614297a3b0SGarrett D'Amore 1624297a3b0SGarrett D'Amore case 'x': 1634297a3b0SGarrett D'Amore buf = __strptime(buf, tptr->x_fmt, tm); 1644297a3b0SGarrett D'Amore if (buf == 0) 1654297a3b0SGarrett D'Amore return (0); 1664297a3b0SGarrett D'Amore break; 1674297a3b0SGarrett D'Amore 1684297a3b0SGarrett D'Amore case 'j': 1694297a3b0SGarrett D'Amore if (!isdigit((unsigned char)*buf)) 1704297a3b0SGarrett D'Amore return (0); 1714297a3b0SGarrett D'Amore 1724297a3b0SGarrett D'Amore len = 3; 1734297a3b0SGarrett D'Amore for (i = 0; 1744297a3b0SGarrett D'Amore len && isdigit((unsigned char)*buf); 1754297a3b0SGarrett D'Amore buf++) { 1764297a3b0SGarrett D'Amore i *= 10; 1774297a3b0SGarrett D'Amore i += *buf - '0'; 1784297a3b0SGarrett D'Amore len--; 1794297a3b0SGarrett D'Amore } 1804297a3b0SGarrett D'Amore if (i < 1 || i > 366) 1814297a3b0SGarrett D'Amore return (0); 1824297a3b0SGarrett D'Amore 1834297a3b0SGarrett D'Amore tm->tm_yday = i - 1; 1844297a3b0SGarrett D'Amore break; 1854297a3b0SGarrett D'Amore 1864297a3b0SGarrett D'Amore case 'M': 1874297a3b0SGarrett D'Amore case 'S': 1884297a3b0SGarrett D'Amore if (*buf == 0 || isspace((unsigned char)*buf)) 1894297a3b0SGarrett D'Amore break; 1904297a3b0SGarrett D'Amore 1914297a3b0SGarrett D'Amore if (!isdigit((unsigned char)*buf)) 1924297a3b0SGarrett D'Amore return (0); 1934297a3b0SGarrett D'Amore 1944297a3b0SGarrett D'Amore len = 2; 1954297a3b0SGarrett D'Amore for (i = 0; 1964297a3b0SGarrett D'Amore len && isdigit((unsigned char)*buf); 1974297a3b0SGarrett D'Amore buf++) { 1984297a3b0SGarrett D'Amore i *= 10; 1994297a3b0SGarrett D'Amore i += *buf - '0'; 2004297a3b0SGarrett D'Amore len--; 2014297a3b0SGarrett D'Amore } 2024297a3b0SGarrett D'Amore 2034297a3b0SGarrett D'Amore if (c == 'M') { 2044297a3b0SGarrett D'Amore if (i > 59) 2054297a3b0SGarrett D'Amore return (0); 2064297a3b0SGarrett D'Amore tm->tm_min = i; 2074297a3b0SGarrett D'Amore } else { 2084297a3b0SGarrett D'Amore if (i > 60) 2094297a3b0SGarrett D'Amore return (0); 2104297a3b0SGarrett D'Amore tm->tm_sec = i; 2114297a3b0SGarrett D'Amore } 2124297a3b0SGarrett D'Amore 2134297a3b0SGarrett D'Amore if (*buf != 0 && isspace((unsigned char)*buf)) 2144297a3b0SGarrett D'Amore while (*ptr != 0 && 2154297a3b0SGarrett D'Amore !isspace((unsigned char)*ptr)) 2164297a3b0SGarrett D'Amore ptr++; 2174297a3b0SGarrett D'Amore break; 2184297a3b0SGarrett D'Amore 2194297a3b0SGarrett D'Amore case 'H': 2204297a3b0SGarrett D'Amore case 'I': 2214297a3b0SGarrett D'Amore case 'k': 2224297a3b0SGarrett D'Amore case 'l': 2234297a3b0SGarrett D'Amore /* 2244297a3b0SGarrett D'Amore * Of these, %l is the only specifier explicitly 2254297a3b0SGarrett D'Amore * documented as not being zero-padded. However, 2264297a3b0SGarrett D'Amore * there is no harm in allowing zero-padding. 2274297a3b0SGarrett D'Amore * 2284297a3b0SGarrett D'Amore * XXX The %l specifier may gobble one too many 2294297a3b0SGarrett D'Amore * digits if used incorrectly. 2304297a3b0SGarrett D'Amore */ 2314297a3b0SGarrett D'Amore if (!isdigit((unsigned char)*buf)) 2324297a3b0SGarrett D'Amore return (0); 2334297a3b0SGarrett D'Amore 2344297a3b0SGarrett D'Amore len = 2; 2354297a3b0SGarrett D'Amore for (i = 0; 2364297a3b0SGarrett D'Amore len && isdigit((unsigned char)*buf); 2374297a3b0SGarrett D'Amore buf++) { 2384297a3b0SGarrett D'Amore i *= 10; 2394297a3b0SGarrett D'Amore i += *buf - '0'; 2404297a3b0SGarrett D'Amore len--; 2414297a3b0SGarrett D'Amore } 2424297a3b0SGarrett D'Amore if (c == 'H' || c == 'k') { 2434297a3b0SGarrett D'Amore if (i > 23) 2444297a3b0SGarrett D'Amore return (0); 2454297a3b0SGarrett D'Amore } else if (i > 12) 2464297a3b0SGarrett D'Amore return (0); 2474297a3b0SGarrett D'Amore 2484297a3b0SGarrett D'Amore tm->tm_hour = i; 2494297a3b0SGarrett D'Amore 2504297a3b0SGarrett D'Amore if (*buf != 0 && isspace((unsigned char)*buf)) 2514297a3b0SGarrett D'Amore while (*ptr != 0 && 2524297a3b0SGarrett D'Amore !isspace((unsigned char)*ptr)) 2534297a3b0SGarrett D'Amore ptr++; 2544297a3b0SGarrett D'Amore break; 2554297a3b0SGarrett D'Amore 2564297a3b0SGarrett D'Amore case 'p': 2574297a3b0SGarrett D'Amore /* 2584297a3b0SGarrett D'Amore * XXX This is bogus if parsed before hour-related 2594297a3b0SGarrett D'Amore * specifiers. 2604297a3b0SGarrett D'Amore */ 2614297a3b0SGarrett D'Amore len = strlen(tptr->am); 2624297a3b0SGarrett D'Amore if (strncasecmp(buf, tptr->am, len) == 0) { 2634297a3b0SGarrett D'Amore if (tm->tm_hour > 12) 2644297a3b0SGarrett D'Amore return (0); 2654297a3b0SGarrett D'Amore if (tm->tm_hour == 12) 2664297a3b0SGarrett D'Amore tm->tm_hour = 0; 2674297a3b0SGarrett D'Amore buf += len; 2684297a3b0SGarrett D'Amore break; 2694297a3b0SGarrett D'Amore } 2704297a3b0SGarrett D'Amore 2714297a3b0SGarrett D'Amore len = strlen(tptr->pm); 2724297a3b0SGarrett D'Amore if (strncasecmp(buf, tptr->pm, len) == 0) { 2734297a3b0SGarrett D'Amore if (tm->tm_hour > 12) 2744297a3b0SGarrett D'Amore return (0); 2754297a3b0SGarrett D'Amore if (tm->tm_hour != 12) 2764297a3b0SGarrett D'Amore tm->tm_hour += 12; 2774297a3b0SGarrett D'Amore buf += len; 2784297a3b0SGarrett D'Amore break; 2794297a3b0SGarrett D'Amore } 2804297a3b0SGarrett D'Amore 2814297a3b0SGarrett D'Amore return (0); 2824297a3b0SGarrett D'Amore 2834297a3b0SGarrett D'Amore case 'A': 2844297a3b0SGarrett D'Amore case 'a': 2854297a3b0SGarrett D'Amore for (i = 0; i < asizeof(tptr->weekday); i++) { 2864297a3b0SGarrett D'Amore len = strlen(tptr->weekday[i]); 2874297a3b0SGarrett D'Amore if (strncasecmp(buf, tptr->weekday[i], len) == 2884297a3b0SGarrett D'Amore 0) 2894297a3b0SGarrett D'Amore break; 2904297a3b0SGarrett D'Amore len = strlen(tptr->wday[i]); 2914297a3b0SGarrett D'Amore if (strncasecmp(buf, tptr->wday[i], len) == 0) 2924297a3b0SGarrett D'Amore break; 2934297a3b0SGarrett D'Amore } 2944297a3b0SGarrett D'Amore if (i == asizeof(tptr->weekday)) 2954297a3b0SGarrett D'Amore return (0); 2964297a3b0SGarrett D'Amore 2974297a3b0SGarrett D'Amore tm->tm_wday = i; 2984297a3b0SGarrett D'Amore buf += len; 2994297a3b0SGarrett D'Amore break; 3004297a3b0SGarrett D'Amore 3014297a3b0SGarrett D'Amore case 'U': 3024297a3b0SGarrett D'Amore case 'W': 3034297a3b0SGarrett D'Amore /* 3044297a3b0SGarrett D'Amore * XXX This is bogus, as we can not assume any valid 3054297a3b0SGarrett D'Amore * information present in the tm structure at this 3064297a3b0SGarrett D'Amore * point to calculate a real value, so just check the 3074297a3b0SGarrett D'Amore * range for now. 3084297a3b0SGarrett D'Amore */ 3094297a3b0SGarrett D'Amore if (!isdigit((unsigned char)*buf)) 3104297a3b0SGarrett D'Amore return (0); 3114297a3b0SGarrett D'Amore 3124297a3b0SGarrett D'Amore len = 2; 3134297a3b0SGarrett D'Amore for (i = 0; 3144297a3b0SGarrett D'Amore len && isdigit((unsigned char)*buf); 3154297a3b0SGarrett D'Amore buf++) { 3164297a3b0SGarrett D'Amore i *= 10; 3174297a3b0SGarrett D'Amore i += *buf - '0'; 3184297a3b0SGarrett D'Amore len--; 3194297a3b0SGarrett D'Amore } 3204297a3b0SGarrett D'Amore if (i > 53) 3214297a3b0SGarrett D'Amore return (0); 3224297a3b0SGarrett D'Amore 3234297a3b0SGarrett D'Amore if (*buf != 0 && isspace((unsigned char)*buf)) 3244297a3b0SGarrett D'Amore while (*ptr != 0 && 3254297a3b0SGarrett D'Amore !isspace((unsigned char)*ptr)) 3264297a3b0SGarrett D'Amore ptr++; 3274297a3b0SGarrett D'Amore break; 3284297a3b0SGarrett D'Amore 3294297a3b0SGarrett D'Amore case 'w': 3304297a3b0SGarrett D'Amore if (!isdigit((unsigned char)*buf)) 3314297a3b0SGarrett D'Amore return (0); 3324297a3b0SGarrett D'Amore 3334297a3b0SGarrett D'Amore i = *buf - '0'; 3344297a3b0SGarrett D'Amore if (i > 6) 3354297a3b0SGarrett D'Amore return (0); 3364297a3b0SGarrett D'Amore 3374297a3b0SGarrett D'Amore tm->tm_wday = i; 3384297a3b0SGarrett D'Amore 3394297a3b0SGarrett D'Amore if (*buf != 0 && isspace((unsigned char)*buf)) 3404297a3b0SGarrett D'Amore while (*ptr != 0 && 3414297a3b0SGarrett D'Amore !isspace((unsigned char)*ptr)) 3424297a3b0SGarrett D'Amore ptr++; 3434297a3b0SGarrett D'Amore break; 3444297a3b0SGarrett D'Amore 3454297a3b0SGarrett D'Amore case 'd': 3464297a3b0SGarrett D'Amore case 'e': 3474297a3b0SGarrett D'Amore /* 3484297a3b0SGarrett D'Amore * The %e specifier is explicitly documented as not 3494297a3b0SGarrett D'Amore * being zero-padded but there is no harm in allowing 3504297a3b0SGarrett D'Amore * such padding. 3514297a3b0SGarrett D'Amore * 3524297a3b0SGarrett D'Amore * XXX The %e specifier may gobble one too many 3534297a3b0SGarrett D'Amore * digits if used incorrectly. 3544297a3b0SGarrett D'Amore */ 3554297a3b0SGarrett D'Amore if (!isdigit((unsigned char)*buf)) 3564297a3b0SGarrett D'Amore return (0); 3574297a3b0SGarrett D'Amore 3584297a3b0SGarrett D'Amore len = 2; 3594297a3b0SGarrett D'Amore for (i = 0; 3604297a3b0SGarrett D'Amore len && isdigit((unsigned char)*buf); 3614297a3b0SGarrett D'Amore buf++) { 3624297a3b0SGarrett D'Amore i *= 10; 3634297a3b0SGarrett D'Amore i += *buf - '0'; 3644297a3b0SGarrett D'Amore len--; 3654297a3b0SGarrett D'Amore } 3664297a3b0SGarrett D'Amore if (i > 31) 3674297a3b0SGarrett D'Amore return (0); 3684297a3b0SGarrett D'Amore 3694297a3b0SGarrett D'Amore tm->tm_mday = i; 3704297a3b0SGarrett D'Amore 3714297a3b0SGarrett D'Amore if (*buf != 0 && isspace((unsigned char)*buf)) 3724297a3b0SGarrett D'Amore while (*ptr != 0 && 3734297a3b0SGarrett D'Amore !isspace((unsigned char)*ptr)) 3744297a3b0SGarrett D'Amore ptr++; 3754297a3b0SGarrett D'Amore break; 3764297a3b0SGarrett D'Amore 3774297a3b0SGarrett D'Amore case 'B': 3784297a3b0SGarrett D'Amore case 'b': 3794297a3b0SGarrett D'Amore case 'h': 3804297a3b0SGarrett D'Amore for (i = 0; i < asizeof(tptr->month); i++) { 3814297a3b0SGarrett D'Amore len = strlen(tptr->month[i]); 3824297a3b0SGarrett D'Amore if (strncasecmp(buf, tptr->month[i], len) == 0) 3834297a3b0SGarrett D'Amore break; 3844297a3b0SGarrett D'Amore } 3854297a3b0SGarrett D'Amore /* 3864297a3b0SGarrett D'Amore * Try the abbreviated month name if the full name 3874297a3b0SGarrett D'Amore * wasn't found. 3884297a3b0SGarrett D'Amore */ 3894297a3b0SGarrett D'Amore if (i == asizeof(tptr->month)) { 3904297a3b0SGarrett D'Amore for (i = 0; i < asizeof(tptr->month); i++) { 3914297a3b0SGarrett D'Amore len = strlen(tptr->mon[i]); 3924297a3b0SGarrett D'Amore if (strncasecmp(buf, tptr->mon[i], 3934297a3b0SGarrett D'Amore len) == 0) 3944297a3b0SGarrett D'Amore break; 3954297a3b0SGarrett D'Amore } 3964297a3b0SGarrett D'Amore } 3974297a3b0SGarrett D'Amore if (i == asizeof(tptr->month)) 3984297a3b0SGarrett D'Amore return (0); 3994297a3b0SGarrett D'Amore 4004297a3b0SGarrett D'Amore tm->tm_mon = i; 4014297a3b0SGarrett D'Amore buf += len; 4024297a3b0SGarrett D'Amore break; 4034297a3b0SGarrett D'Amore 4044297a3b0SGarrett D'Amore case 'm': 4054297a3b0SGarrett D'Amore if (!isdigit((unsigned char)*buf)) 4064297a3b0SGarrett D'Amore return (0); 4074297a3b0SGarrett D'Amore 4084297a3b0SGarrett D'Amore len = 2; 4094297a3b0SGarrett D'Amore for (i = 0; 4104297a3b0SGarrett D'Amore len && isdigit((unsigned char)*buf); 4114297a3b0SGarrett D'Amore buf++) { 4124297a3b0SGarrett D'Amore i *= 10; 4134297a3b0SGarrett D'Amore i += *buf - '0'; 4144297a3b0SGarrett D'Amore len--; 4154297a3b0SGarrett D'Amore } 4164297a3b0SGarrett D'Amore if (i < 1 || i > 12) 4174297a3b0SGarrett D'Amore return (0); 4184297a3b0SGarrett D'Amore 4194297a3b0SGarrett D'Amore tm->tm_mon = i - 1; 4204297a3b0SGarrett D'Amore 4214297a3b0SGarrett D'Amore if (*buf != 0 && isspace((unsigned char)*buf)) 4224297a3b0SGarrett D'Amore while (*ptr != 0 && 4234297a3b0SGarrett D'Amore !isspace((unsigned char)*ptr)) 4244297a3b0SGarrett D'Amore ptr++; 4254297a3b0SGarrett D'Amore break; 4264297a3b0SGarrett D'Amore 4274297a3b0SGarrett D'Amore case 'Y': 4284297a3b0SGarrett D'Amore case 'y': 4294297a3b0SGarrett D'Amore if (*buf == 0 || isspace((unsigned char)*buf)) 4304297a3b0SGarrett D'Amore break; 4314297a3b0SGarrett D'Amore 4324297a3b0SGarrett D'Amore if (!isdigit((unsigned char)*buf)) 4334297a3b0SGarrett D'Amore return (0); 4344297a3b0SGarrett D'Amore 4354297a3b0SGarrett D'Amore len = (c == 'Y') ? 4 : 2; 4364297a3b0SGarrett D'Amore for (i = 0; 4374297a3b0SGarrett D'Amore len && isdigit((unsigned char)*buf); 4384297a3b0SGarrett D'Amore buf++) { 4394297a3b0SGarrett D'Amore i *= 10; 4404297a3b0SGarrett D'Amore i += *buf - '0'; 4414297a3b0SGarrett D'Amore len--; 4424297a3b0SGarrett D'Amore } 4434297a3b0SGarrett D'Amore if (c == 'Y') 4444297a3b0SGarrett D'Amore i -= 1900; 4454297a3b0SGarrett D'Amore if (c == 'y' && i < 69) 4464297a3b0SGarrett D'Amore i += 100; 4474297a3b0SGarrett D'Amore if (i < 0) 4484297a3b0SGarrett D'Amore return (0); 4494297a3b0SGarrett D'Amore 4504297a3b0SGarrett D'Amore tm->tm_year = i; 4514297a3b0SGarrett D'Amore 4524297a3b0SGarrett D'Amore if (*buf != 0 && isspace((unsigned char)*buf)) 4534297a3b0SGarrett D'Amore while (*ptr != 0 && 4544297a3b0SGarrett D'Amore !isspace((unsigned char)*ptr)) 4554297a3b0SGarrett D'Amore ptr++; 4564297a3b0SGarrett D'Amore break; 4574297a3b0SGarrett D'Amore 4584297a3b0SGarrett D'Amore case 'Z': 4594297a3b0SGarrett D'Amore { 4604297a3b0SGarrett D'Amore const char *cp = buf; 4614297a3b0SGarrett D'Amore char *zonestr; 4624297a3b0SGarrett D'Amore 4634297a3b0SGarrett D'Amore while (isupper((unsigned char)*cp)) 4644297a3b0SGarrett D'Amore ++cp; 4654297a3b0SGarrett D'Amore if (cp - buf) { 4664297a3b0SGarrett D'Amore zonestr = alloca(cp - buf + 1); 4674297a3b0SGarrett D'Amore (void) strncpy(zonestr, buf, cp - buf); 4684297a3b0SGarrett D'Amore zonestr[cp - buf] = '\0'; 4694297a3b0SGarrett D'Amore tzset(); 4704297a3b0SGarrett D'Amore /* 4714297a3b0SGarrett D'Amore * Once upon a time this supported "GMT", 4724297a3b0SGarrett D'Amore * for GMT, but we removed this as Solaris 4734297a3b0SGarrett D'Amore * doesn't have it, and we lack the needed 4744297a3b0SGarrett D'Amore * timegm function. 4754297a3b0SGarrett D'Amore */ 4764297a3b0SGarrett D'Amore if (0 == strcmp(zonestr, tzname[0])) { 4774297a3b0SGarrett D'Amore tm->tm_isdst = 0; 4784297a3b0SGarrett D'Amore } else if (0 == strcmp(zonestr, tzname[1])) { 4794297a3b0SGarrett D'Amore tm->tm_isdst = 1; 4804297a3b0SGarrett D'Amore } else { 4814297a3b0SGarrett D'Amore return (0); 4824297a3b0SGarrett D'Amore } 4834297a3b0SGarrett D'Amore buf += cp - buf; 4844297a3b0SGarrett D'Amore } 4854297a3b0SGarrett D'Amore } 4864297a3b0SGarrett D'Amore break; 4874297a3b0SGarrett D'Amore 4884297a3b0SGarrett D'Amore /* 4894297a3b0SGarrett D'Amore * Note that there used to be support %z and %s, but these 4904297a3b0SGarrett D'Amore * are not supported by Solaris, so we have removed them. 4914297a3b0SGarrett D'Amore * They would have required timegm() which is missing. 4924297a3b0SGarrett D'Amore */ 4934297a3b0SGarrett D'Amore } 4944297a3b0SGarrett D'Amore } 4954297a3b0SGarrett D'Amore return ((char *)buf); 4964297a3b0SGarrett D'Amore } 4974297a3b0SGarrett D'Amore 4984297a3b0SGarrett D'Amore char * 4994297a3b0SGarrett D'Amore strptime(const char *buf, const char *fmt, struct tm *tm) 5004297a3b0SGarrett D'Amore { 5014297a3b0SGarrett D'Amore /* Legacy Solaris strptime clears the incoming tm structure. */ 5024297a3b0SGarrett D'Amore (void) memset(tm, 0, sizeof (*tm)); 5034297a3b0SGarrett D'Amore 5044297a3b0SGarrett D'Amore return (__strptime(buf, fmt, tm)); 5054297a3b0SGarrett D'Amore } 5064297a3b0SGarrett D'Amore 5074297a3b0SGarrett D'Amore /* 5084297a3b0SGarrett D'Amore * This is used by Solaris, and is a variant that does not clear the 5094297a3b0SGarrett D'Amore * incoming tm. It is triggered by -D_STRPTIME_DONTZERO. 5104297a3b0SGarrett D'Amore */ 5114297a3b0SGarrett D'Amore char * 5124297a3b0SGarrett D'Amore __strptime_dontzero(const char *buf, const char *fmt, struct tm *tm) 5134297a3b0SGarrett D'Amore { 5144297a3b0SGarrett D'Amore return (__strptime(buf, fmt, tm)); 5154297a3b0SGarrett D'Amore } 516