2 * Copyright (c) 1991, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1991, 1993, 1994, 1995, 1996
5 * Keith Bostic. All rights reserved.
7 * See the LICENSE file for redistribution information.
13 static const char sccsid[] = "$Id: util.c,v 10.30 2013/03/19 10:00:27 yamt Exp $";
16 #include <sys/types.h>
17 #include <sys/queue.h>
20 #include <mach/clock.h>
21 #include <mach/mach.h>
22 #include <mach/mach_time.h>
25 #include <bitstring.h>
40 * Increase the size of a buffer.
42 * PUBLIC: void *binc __P((SCR *, void *, size_t *, size_t));
46 SCR *sp, /* sp MAY BE NULL!!! */
53 /* If already larger than the minimum, just return. */
54 if (min && *bsizep >= min)
57 csize = p2roundup(MAX(min, 256));
58 REALLOC(sp, bp, void *, csize);
65 * Memory is guaranteed to be zero-filled, various parts of
68 memset((char *)bp + *bsizep, 0, csize - *bsizep);
75 * Set the column number of the first non-blank character
76 * including or after the starting column. On error, set
77 * the column to 0, it's safest.
79 * PUBLIC: int nonblank __P((SCR *, recno_t, size_t *));
95 /* Get the line, succeeding in an empty file. */
96 if (db_eget(sp, lno, &p, &len, &isempty))
100 if (len == 0 || off >= len)
103 for (cnt = off, p = &p[off],
104 len -= off; len && ISBLANK(*p); ++cnt, ++p, --len);
106 /* Set the return. */
107 *cnop = len ? cnt : cnt - 1;
113 * Return tail of a path.
115 * PUBLIC: char *tail __P((char *));
122 if ((p = strrchr(path, '/')) == NULL)
129 * Join two paths; need free.
131 * PUBLIC: char *join __P((char *, char *));
140 if (path1[0] == '\0' || path2[0] == '/')
141 return strdup(path2);
142 (void)asprintf(&p, path1[strlen(path1)-1] == '/' ?
143 "%s%s" : "%s/%s", path1, path2);
149 * Return a "~" or "~user" expanded path; need free.
151 * PUBLIC: char *expanduser __P((char *));
154 expanduser(char *str)
160 * This function always expands the content between the
161 * leading '~' and the first '/' or '\0' from the input.
162 * Return NULL whenever we fail to do so.
167 for (t = p; *t != '/' && *t != '\0'; ++t)
171 if (issetugid() != 0 ||
172 (h = getenv("HOME")) == NULL) {
173 if (((h = getlogin()) != NULL &&
174 (pwd = getpwnam(h)) != NULL) ||
175 (pwd = getpwuid(getuid())) != NULL)
182 if ((u = strndup(p, t - p)) == NULL)
184 if ((pwd = getpwnam(u)) == NULL) {
192 for (; *t == '/' && *t != '\0'; ++t)
199 * Return a escaped string for /bin/sh; need free.
201 * PUBLIC: char *quote __P((char *));
210 for (p = str; *p != '\0'; p++, i++) {
219 case '%': case '+': case ',': case '-': case '.':
220 case '/': case ':': case '=': case '@': case '_':
229 else if ((p = t = malloc(i + n * (sizeof(SQT) - 2) + 3)) != NULL) {
231 for (; *str != '\0'; str++) {
233 (void)memcpy(p, SQT, sizeof(SQT) - 1);
234 p += sizeof(SQT) - 1;
246 * Strdup for 8-bit character strings with an associated length.
248 * PUBLIC: char *v_strdup __P((SCR *, const char *, size_t));
258 MALLOC(sp, copy, char *, len + 1);
261 memcpy(copy, str, len);
268 * Strdup for wide character strings with an associated length.
270 * PUBLIC: CHAR_T *v_wstrdup __P((SCR *, const CHAR_T *, size_t));
279 MALLOC(sp, copy, CHAR_T *, (len + 1) * sizeof(CHAR_T));
282 MEMCPY(copy, str, len);
289 * Get an unsigned long, checking for overflow.
291 * PUBLIC: enum nresult nget_uslong __P((u_long *, const CHAR_T *, CHAR_T **, int));
301 *valp = STRTOUL(p, endp, base);
304 if (errno == ERANGE && *valp == ULONG_MAX)
311 * Convert a signed long, checking for overflow and underflow.
313 * PUBLIC: enum nresult nget_slong __P((long *, const CHAR_T *, CHAR_T **, int));
323 *valp = STRTOL(p, endp, base);
326 if (errno == ERANGE) {
327 if (*valp == LONG_MAX)
329 if (*valp == LONG_MIN)
336 * timepoint_steady --
337 * Get a timestamp from a monotonic clock.
339 * PUBLIC: void timepoint_steady __P((struct timespec *));
346 static mach_timebase_info_data_t base = { 0 };
351 (void)mach_timebase_info(&base);
353 val = mach_absolute_time();
354 ns = val * base.numer / base.denom;
355 ts->tv_sec = ns / 1000000000;
356 ts->tv_nsec = ns % 1000000000;
358 #ifdef CLOCK_MONOTONIC_FAST
359 (void)clock_gettime(CLOCK_MONOTONIC_FAST, ts);
361 (void)clock_gettime(CLOCK_MONOTONIC, ts);
367 * timepoint_system --
368 * Get the current calendar time.
370 * PUBLIC: void timepoint_system __P((struct timespec *));
381 kr = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &clk);
382 if (kr != KERN_SUCCESS)
384 (void)clock_get_time(clk, &mts);
385 (void)mach_port_deallocate(mach_task_self(), clk);
386 ts->tv_sec = mts.tv_sec;
387 ts->tv_nsec = mts.tv_nsec;
389 #ifdef CLOCK_REALTIME_FAST
390 (void)clock_gettime(CLOCK_REALTIME_FAST, ts);
392 (void)clock_gettime(CLOCK_REALTIME, ts);
402 * debugging trace routine.
404 * PUBLIC: void TRACE __P((SCR *, const char *, ...));
415 if ((tfp = sp->gp->tracefp) == NULL)
418 (void)vfprintf(tfp, fmt, ap);