2 * Copyright © 2004, 2005, 2006, 2007, 2011, 2012, 2017
3 * mirabilos <m@mirbsd.org>
5 * Provided that these terms and disclaimer and all copyright notices
6 * are retained or reproduced in an accompanying document, permission
7 * is granted to deal in this work without restriction, including un‐
8 * limited rights to use, publicly perform, distribute, sell, modify,
9 * merge, give away, or sublicence.
11 * This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
12 * the utmost extent permitted by applicable law, neither express nor
13 * implied; without malicious intent or gross negligence. In no event
14 * may a licensor, author or contributor be held liable for indirect,
15 * direct, other damage, loss, or other issues arising in any way out
16 * of dealing in the work, even if advised of the possibility of such
17 * damage or existence of a defect, except proven that it results out
18 * of said person’s immediate fault when using the work as intended.
20 * Compatibility and fully new utility functions for jupp.
22 * – ctime: based on mirtime from MirBSD libc; not leap second capable
23 * src/kern/include/mirtime.h,v 1.2 2011/11/20 23:40:11 tg Exp
24 * src/kern/c/mirtime.c,v 1.3 2011/11/20 23:40:10 tg Exp
25 * – strlcpy, strlcat: pulled in via "strlfun.inc"
26 * – popen, pclose: pulled in via "popen.inc"
27 * - ustoc_{hex,oct}, ustol: parse integers
33 __RCSID("$MirOS: contrib/code/jupp/compat.c,v 1.9 2017/12/02 17:00:53 tg Exp $");
47 #if defined(L_strlcat) || defined(L_strlcpy)
49 #define __RCSID(x) __IDSTRING(rcsid_strlfun_inc,x)
50 #define OUTSIDE_OF_LIBKERN
51 #include "strlfun.inc"
55 #ifdef TIME_WITH_SYS_TIME
56 # include <sys/time.h>
59 # ifdef HAVE_SYS_TIME_H
60 # include <sys/time.h>
67 int tm_sec; /* seconds [0-60] */
68 int tm_min; /* minutes [0-59] */
69 int tm_hour; /* hours [0-23] */
70 int tm_mday; /* day of month [1-31] */
71 int tm_mon; /* month of year - 1 [0-11] */
72 int tm_year; /* year - 1900 */
73 int tm_wday; /* day of week (0 = sunday) */
76 static void joe_timet2tm(joe_tm *, const time_t *);
79 char *ctime(const time_t *);
82 /* 302 / 1000 is log10(2.0) rounded up */
83 #define T_SIGNED(t) (((t)-1) < 0)
84 #define T_MAXLEN(t) ((sizeof(t) * CHAR_BIT - T_SIGNED(t)) * 302 / 1000 + \
85 /* div.trunc. */ 1 + /* minus sign */ T_SIGNED(t))
87 static const char joe_days[7][4] = {
88 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
91 static const char joe_months[12][4] = {
92 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
93 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
97 * Dimensions for the buffer, example formats:
98 * "Sun Jan 1 12:34:56 1234\n"
99 * "Sat Dec 31 12:34:56 12345\n"
100 * <- 24 -----------------> + max.length of a year + NL + NUL
102 static char joe_ctime_buf[24 + T_MAXLEN(time_t) + 2];
105 ctime(const time_t *tp)
110 joe_timet2tm(&tm, tp);
111 year = (int)(tm.tm_year + 1900);
112 joe_snprintf_7(joe_ctime_buf, sizeof(joe_ctime_buf),
113 (year >= -999 && year <= 9999) ?
114 "%s %s %2d %02d:%02d:%02d %04d\n" :
115 "%s %s %2d %02d:%02d:%02d %d\n",
116 joe_days[tm.tm_wday], joe_months[tm.tm_mon],
117 tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, year);
118 return (joe_ctime_buf);
122 joe_timet2tm(joe_tm *tm, const time_t *tp)
129 sec = (int)(y % 86400);
137 /* calculate 400-year cycle (y) and offset in it (day) */
138 day = (int)(y % 146097);
141 /* add bias: 678881 = days between "convenient origin" and MJD 0 */
142 /* convenient origin is Wed(3) 1 March 0(fictional)/-1(real) */
144 /* recalculate offset in cycle (Gregorian Period) */
148 /* days in 400 years are cyclic, they have 20871 weeks */
149 tm->tm_wday = (day + 3) % 7;
151 /* calculate year from period, taking leap years into account */
153 /* a long (Julian) century is at the end of each Gregorian Period */
166 /* March to December, or January/February? */
167 /* a leap year is at the end of each olympiad */
176 /* count days and months from 1st March using fixed-point */
178 mon = (day + 5) / 306;
179 day = (day + 5) % 306;
181 /* adjust for Jan/Feb offset */
189 /* adjust for year 0(fictional) which did not exist */
193 /* fill in the values still missing */
194 tm->tm_sec = sec % 60;
196 tm->tm_min = sec % 60;
197 tm->tm_hour = sec / 60;
198 tm->tm_mday = day + 1;
200 /*XXX truncate, for joe_snprintf doesn't know %lld portably */
201 tm->tm_year = (int)(y - 1900);
203 #endif /* ndef HAVE_CTIME */
207 #define __RCSID(x) __IDSTRING(rcsid_popen_inc,x)
212 ustoc_hex(const void *us, int *dp, size_t lim)
215 const unsigned char *s = (const unsigned char *)us;
216 int rv = 0, rounds = 0;
218 while (rounds++ < 2 && lim-- > 0)
219 if ((c = *s++) >= '0' && c <= '9')
220 rv = (rv << 4) | (c & 15);
221 else if ((c |= 0x20) >= 'a' && c <= 'f')
222 rv = (rv << 4) | (c - 'a' + 10);
229 return (s - (const unsigned char *)us);
233 ustoc_oct(const void *us, int *dp, size_t lim)
236 const unsigned char *s = (const unsigned char *)us;
237 int rv = 0, rounds = 0;
239 while (rounds++ < 3 && lim-- > 0)
240 if ((c = *s++) >= '0' && c <= '7')
241 rv = (rv << 3) | (c & 7);
248 return (s - (const unsigned char *)us);
251 #define USTOL_MODEMASK 0x03
253 static const char ustol_wsp[] = "\t\x0B\x0C\r ";
256 ustol(void *us, void **dpp, int flags)
258 unsigned char c, *s = (unsigned char *)us;
261 unsigned char neg = 0;
263 if (flags & USTOL_LTRIM)
264 while ((c = *s) && strchr(ustol_wsp, c))
267 switch (flags & USTOL_MODEMASK) {
269 if (s[0] == '0' && (s[1] | 0x20) == 'x')
275 else if ((s[1] | 0x20) != 'x')
285 switch (flags & USTOL_MODEMASK) {
287 while ((c = *s++) >= '0' && c <= '7') {
289 if (a > (ULONG_MAX >> 3))
291 /* accumulate trivially */
292 a = (a << 3) | (c & 7);
296 while ((c = *s++) >= '0') {
299 else if ((c |= 0x20) >= 'a' && c <= 'f')
304 if (a > (ULONG_MAX >> 4))
306 /* accumulate trivially */
318 while ((c = *s++) >= '0' && c <= '9') {
320 if (a > (ULONG_MAX / 10))
323 if (a > (ULONG_MAX - c))
328 if (a > (((unsigned long)(-(LONG_MIN + 1L))) + 1UL))
331 } else if (a > (unsigned long)LONG_MAX)
334 /* check we had at least one digit */
338 if (flags & USTOL_RTRIM)
339 while ((c = *s) && strchr(ustol_wsp, c))
342 /* don’t check for EOS, or arrived at EOS */
343 if (!(flags & USTOL_EOS) || !*s)
356 ustolb(void *us, void **dpp, long lower, long upper, int flags)
361 rv = ustol(us, &dp, flags);
362 if (dp != NULL && (rv < lower || rv > upper)) {