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(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(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(char *);
122 if ((p
= strrchr(path
, '/')) == NULL
)
129 * Join two paths; need free.
131 * PUBLIC: char *join(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(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(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(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(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(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(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(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(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(SCR *, const char *, ...);
415 if ((tfp
= sp
->gp
->tracefp
) == NULL
)
418 (void)vfprintf(tfp
, fmt
, ap
);