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.
12 #include <sys/types.h>
13 #include <sys/queue.h>
16 #include <mach/clock.h>
17 #include <mach/mach.h>
18 #include <mach/mach_time.h>
21 #include <bitstring.h>
36 * Increase the size of a buffer.
38 * PUBLIC: void *binc(SCR *, void *, size_t *, size_t);
41 binc(SCR *sp, /* sp MAY BE NULL!!! */
42 void *bp, size_t *bsizep, size_t min)
46 /* If already larger than the minimum, just return. */
47 if (min && *bsizep >= min)
50 csize = p2roundup(MAX(min, 256));
51 REALLOC(sp, bp, void *, csize);
58 * Memory is guaranteed to be zero-filled, various parts of
61 memset((char *)bp + *bsizep, 0, csize - *bsizep);
68 * Set the column number of the first non-blank character
69 * including or after the starting column. On error, set
70 * the column to 0, it's safest.
72 * PUBLIC: int nonblank(SCR *, recno_t, size_t *);
75 nonblank(SCR *sp, recno_t lno, size_t *cnop)
85 /* Get the line, succeeding in an empty file. */
86 if (db_eget(sp, lno, &p, &len, &isempty))
90 if (len == 0 || off >= len)
93 for (cnt = off, p = &p[off],
94 len -= off; len && ISBLANK(*p); ++cnt, ++p, --len);
97 *cnop = len ? cnt : cnt - 1;
103 * Join two paths; need free.
105 * PUBLIC: char *join(char *, char *);
108 join(char *path1, char *path2)
112 if (path1[0] == '\0' || path2[0] == '/')
113 return strdup(path2);
114 (void)asprintf(&p, path1[strlen(path1)-1] == '/' ?
115 "%s%s" : "%s/%s", path1, path2);
121 * Return a "~" or "~user" expanded path; need free.
123 * PUBLIC: char *expanduser(char *);
126 expanduser(char *str)
132 * This function always expands the content between the
133 * leading '~' and the first '/' or '\0' from the input.
134 * Return NULL whenever we fail to do so.
139 for (t = p; *t != '/' && *t != '\0'; ++t)
143 if (issetugid() != 0 ||
144 (h = getenv("HOME")) == NULL) {
145 if (((h = getlogin()) != NULL &&
146 (pwd = getpwnam(h)) != NULL) ||
147 (pwd = getpwuid(getuid())) != NULL)
154 if ((u = strndup(p, t - p)) == NULL)
156 if ((pwd = getpwnam(u)) == NULL) {
164 for (; *t == '/' && *t != '\0'; ++t)
171 * Return a escaped string for /bin/sh; need free.
173 * PUBLIC: char *quote(char *);
182 for (p = str; *p != '\0'; p++, i++) {
187 if (isascii((u_char)*p)) {
188 if (isalnum((u_char)*p))
191 case '%': case '+': case ',': case '-': case '.':
192 case '/': case ':': case '=': case '@': case '_':
201 else if ((p = t = malloc(i + n * (sizeof(SQT) - 2) + 3)) != NULL) {
203 for (; *str != '\0'; str++) {
205 (void)memcpy(p, SQT, sizeof(SQT) - 1);
206 p += sizeof(SQT) - 1;
218 * Strdup for 8-bit character strings with an associated length.
220 * PUBLIC: char *v_strdup(SCR *, const char *, size_t);
223 v_strdup(SCR *sp, const char *str, size_t len)
227 MALLOC(sp, copy, len + 1);
230 memcpy(copy, str, len);
237 * Strdup for wide character strings with an associated length.
239 * PUBLIC: CHAR_T *v_wstrdup(SCR *, const CHAR_T *, size_t);
242 v_wstrdup(SCR *sp, const CHAR_T *str, size_t len)
246 MALLOC(sp, copy, (len + 1) * sizeof(CHAR_T));
249 MEMCPY(copy, str, len);
256 * Get an unsigned long, checking for overflow.
258 * PUBLIC: enum nresult nget_uslong(u_long *, const CHAR_T *, CHAR_T **, int);
261 nget_uslong(u_long *valp, const CHAR_T *p, CHAR_T **endp, int base)
264 *valp = STRTOUL(p, endp, base);
267 if (errno == ERANGE && *valp == ULONG_MAX)
274 * Convert a signed long, checking for overflow and underflow.
276 * PUBLIC: enum nresult nget_slong(long *, const CHAR_T *, CHAR_T **, int);
279 nget_slong(long *valp, const CHAR_T *p, CHAR_T **endp, int base)
282 *valp = STRTOL(p, endp, base);
285 if (errno == ERANGE) {
286 if (*valp == LONG_MAX)
288 if (*valp == LONG_MIN)
295 * timepoint_steady --
296 * Get a timestamp from a monotonic clock.
298 * PUBLIC: void timepoint_steady(struct timespec *);
301 timepoint_steady(struct timespec *ts)
304 static mach_timebase_info_data_t base = { 0 };
309 (void)mach_timebase_info(&base);
311 val = mach_absolute_time();
312 ns = val * base.numer / base.denom;
313 ts->tv_sec = ns / 1000000000;
314 ts->tv_nsec = ns % 1000000000;
316 #ifdef CLOCK_MONOTONIC_FAST
317 (void)clock_gettime(CLOCK_MONOTONIC_FAST, ts);
319 (void)clock_gettime(CLOCK_MONOTONIC, ts);
325 * timepoint_system --
326 * Get the current calendar time.
328 * PUBLIC: void timepoint_system(struct timespec *);
331 timepoint_system(struct timespec *ts)
338 kr = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &clk);
339 if (kr != KERN_SUCCESS)
341 (void)clock_get_time(clk, &mts);
342 (void)mach_port_deallocate(mach_task_self(), clk);
343 ts->tv_sec = mts.tv_sec;
344 ts->tv_nsec = mts.tv_nsec;
346 #ifdef CLOCK_REALTIME_FAST
347 (void)clock_gettime(CLOCK_REALTIME_FAST, ts);
349 (void)clock_gettime(CLOCK_REALTIME, ts);
359 * debugging trace routine.
361 * PUBLIC: void TRACE(SCR *, const char *, ...);
364 TRACE(SCR *sp, const char *fmt, ...)
369 if ((tfp = sp->gp->tracefp) == NULL)
372 (void)vfprintf(tfp, fmt, ap);