119304Speter/*- 219304Speter * Copyright (c) 1991, 1993, 1994 319304Speter * The Regents of the University of California. All rights reserved. 419304Speter * Copyright (c) 1991, 1993, 1994, 1995, 1996 519304Speter * Keith Bostic. All rights reserved. 619304Speter * 719304Speter * See the LICENSE file for redistribution information. 819304Speter */ 919304Speter 1019304Speter#include "config.h" 1119304Speter 1219304Speter#ifndef lint 13254225Speterstatic const char sccsid[] = "$Id: util.c,v 10.30 2013/03/19 10:00:27 yamt Exp $"; 1419304Speter#endif /* not lint */ 1519304Speter 1619304Speter#include <sys/types.h> 1719304Speter#include <sys/queue.h> 1819304Speter 19254225Speter#ifdef __APPLE__ 20254225Speter#include <mach/clock.h> 21254225Speter#include <mach/mach.h> 22254225Speter#include <mach/mach_time.h> 23254225Speter#endif 24254225Speter 2519304Speter#include <bitstring.h> 26254225Speter#include <ctype.h> 2719304Speter#include <errno.h> 2819304Speter#include <limits.h> 29254225Speter#include <pwd.h> 3019304Speter#include <stdio.h> 3119304Speter#include <stdlib.h> 3219304Speter#include <string.h> 33254225Speter#include <time.h> 3419304Speter#include <unistd.h> 3519304Speter 3619304Speter#include "common.h" 3719304Speter 3819304Speter/* 3919304Speter * binc -- 4019304Speter * Increase the size of a buffer. 4119304Speter * 42281373Sbapt * PUBLIC: void *binc(SCR *, void *, size_t *, size_t); 4319304Speter */ 4419304Spetervoid * 45254225Speterbinc( 46254225Speter SCR *sp, /* sp MAY BE NULL!!! */ 47254225Speter void *bp, 48254225Speter size_t *bsizep, 49254225Speter size_t min) 5019304Speter{ 5119304Speter size_t csize; 5219304Speter 5319304Speter /* If already larger than the minimum, just return. */ 5419304Speter if (min && *bsizep >= min) 5519304Speter return (bp); 5619304Speter 57254225Speter csize = p2roundup(MAX(min, 256)); 5819304Speter REALLOC(sp, bp, void *, csize); 5919304Speter 6019304Speter if (bp == NULL) { 6119304Speter *bsizep = 0; 6219304Speter return (NULL); 6319304Speter } 6419304Speter /* 6519304Speter * Memory is guaranteed to be zero-filled, various parts of 6619304Speter * nvi depend on this. 6719304Speter */ 6819304Speter memset((char *)bp + *bsizep, 0, csize - *bsizep); 6919304Speter *bsizep = csize; 7019304Speter return (bp); 7119304Speter} 7219304Speter 7319304Speter/* 7419304Speter * nonblank -- 7519304Speter * Set the column number of the first non-blank character 7619304Speter * including or after the starting column. On error, set 7719304Speter * the column to 0, it's safest. 7819304Speter * 79281373Sbapt * PUBLIC: int nonblank(SCR *, recno_t, size_t *); 8019304Speter */ 8119304Speterint 82254225Speternonblank( 83254225Speter SCR *sp, 84254225Speter recno_t lno, 85254225Speter size_t *cnop) 8619304Speter{ 87254225Speter CHAR_T *p; 8819304Speter size_t cnt, len, off; 8919304Speter int isempty; 9019304Speter 9119304Speter /* Default. */ 9219304Speter off = *cnop; 9319304Speter *cnop = 0; 9419304Speter 9519304Speter /* Get the line, succeeding in an empty file. */ 9619304Speter if (db_eget(sp, lno, &p, &len, &isempty)) 9719304Speter return (!isempty); 9819304Speter 9919304Speter /* Set the offset. */ 10019304Speter if (len == 0 || off >= len) 10119304Speter return (0); 10219304Speter 10319304Speter for (cnt = off, p = &p[off], 104254225Speter len -= off; len && ISBLANK(*p); ++cnt, ++p, --len); 10519304Speter 10619304Speter /* Set the return. */ 10719304Speter *cnop = len ? cnt : cnt - 1; 10819304Speter return (0); 10919304Speter} 11019304Speter 11119304Speter/* 11219304Speter * tail -- 11319304Speter * Return tail of a path. 11419304Speter * 115281373Sbapt * PUBLIC: char *tail(char *); 11619304Speter */ 11719304Speterchar * 118254225Spetertail(char *path) 11919304Speter{ 12019304Speter char *p; 12119304Speter 12219304Speter if ((p = strrchr(path, '/')) == NULL) 12319304Speter return (path); 12419304Speter return (p + 1); 12519304Speter} 12619304Speter 12719304Speter/* 128254225Speter * join -- 129254225Speter * Join two paths; need free. 130254225Speter * 131281373Sbapt * PUBLIC: char *join(char *, char *); 132254225Speter */ 133254225Speterchar * 134254225Speterjoin( 135281373Sbapt char *path1, 136281373Sbapt char *path2) 137254225Speter{ 138254225Speter char *p; 139254225Speter 140254225Speter if (path1[0] == '\0' || path2[0] == '/') 141254225Speter return strdup(path2); 142254225Speter (void)asprintf(&p, path1[strlen(path1)-1] == '/' ? 143254225Speter "%s%s" : "%s/%s", path1, path2); 144254225Speter return p; 145254225Speter} 146254225Speter 147254225Speter/* 148254225Speter * expanduser -- 149254225Speter * Return a "~" or "~user" expanded path; need free. 150254225Speter * 151281373Sbapt * PUBLIC: char *expanduser(char *); 152254225Speter */ 153254225Speterchar * 154254225Speterexpanduser(char *str) 155254225Speter{ 156254225Speter struct passwd *pwd; 157254225Speter char *p, *t, *u, *h; 158254225Speter 159254225Speter /* 160254225Speter * This function always expands the content between the 161254225Speter * leading '~' and the first '/' or '\0' from the input. 162254225Speter * Return NULL whenever we fail to do so. 163254225Speter */ 164254225Speter if (*str != '~') 165254225Speter return (NULL); 166254225Speter p = str + 1; 167254225Speter for (t = p; *t != '/' && *t != '\0'; ++t) 168254225Speter continue; 169254225Speter if (t == p) { 170254225Speter /* ~ */ 171254225Speter if (issetugid() != 0 || 172254225Speter (h = getenv("HOME")) == NULL) { 173254225Speter if (((h = getlogin()) != NULL && 174254225Speter (pwd = getpwnam(h)) != NULL) || 175254225Speter (pwd = getpwuid(getuid())) != NULL) 176254225Speter h = pwd->pw_dir; 177254225Speter else 178254225Speter return (NULL); 179254225Speter } 180254225Speter } else { 181254225Speter /* ~user */ 182254225Speter if ((u = strndup(p, t - p)) == NULL) 183254225Speter return (NULL); 184254225Speter if ((pwd = getpwnam(u)) == NULL) { 185254225Speter free(u); 186254225Speter return (NULL); 187254225Speter } else 188254225Speter h = pwd->pw_dir; 189254225Speter free(u); 190254225Speter } 191254225Speter 192254225Speter for (; *t == '/' && *t != '\0'; ++t) 193254225Speter continue; 194254225Speter return (join(h, t)); 195254225Speter} 196254225Speter 197254225Speter/* 198254225Speter * quote -- 199254225Speter * Return a escaped string for /bin/sh; need free. 200254225Speter * 201281373Sbapt * PUBLIC: char *quote(char *); 202254225Speter */ 203254225Speterchar * 204254225Speterquote(char *str) 205254225Speter{ 206254225Speter char *p, *t; 207254225Speter size_t i = 0, n = 0; 208254225Speter int unsafe = 0; 209254225Speter 210254225Speter for (p = str; *p != '\0'; p++, i++) { 211254225Speter if (*p == '\'') 212254225Speter n++; 213254225Speter if (unsafe) 214254225Speter continue; 215254225Speter if (isascii(*p)) { 216254225Speter if (isalnum(*p)) 217254225Speter continue; 218254225Speter switch (*p) { 219254225Speter case '%': case '+': case ',': case '-': case '.': 220254225Speter case '/': case ':': case '=': case '@': case '_': 221254225Speter continue; 222254225Speter } 223254225Speter } 224254225Speter unsafe = 1; 225254225Speter } 226254225Speter if (!unsafe) 227254225Speter t = strdup(str); 228254225Speter#define SQT "'\\''" 229254225Speter else if ((p = t = malloc(i + n * (sizeof(SQT) - 2) + 3)) != NULL) { 230254225Speter *p++ = '\''; 231254225Speter for (; *str != '\0'; str++) { 232254225Speter if (*str == '\'') { 233254225Speter (void)memcpy(p, SQT, sizeof(SQT) - 1); 234254225Speter p += sizeof(SQT) - 1; 235254225Speter } else 236254225Speter *p++ = *str; 237254225Speter } 238254225Speter *p++ = '\''; 239254225Speter *p = '\0'; 240254225Speter } 241254225Speter return t; 242254225Speter} 243254225Speter 244254225Speter/* 24519304Speter * v_strdup -- 246254225Speter * Strdup for 8-bit character strings with an associated length. 247254225Speter * 248281373Sbapt * PUBLIC: char *v_strdup(SCR *, const char *, size_t); 249254225Speter */ 250254225Speterchar * 251254225Speterv_strdup( 252254225Speter SCR *sp, 253254225Speter const char *str, 254254225Speter size_t len) 255254225Speter{ 256254225Speter char *copy; 257254225Speter 258254225Speter MALLOC(sp, copy, char *, len + 1); 259254225Speter if (copy == NULL) 260254225Speter return (NULL); 261254225Speter memcpy(copy, str, len); 262254225Speter copy[len] = '\0'; 263254225Speter return (copy); 264254225Speter} 265254225Speter 266254225Speter/* 267254225Speter * v_wstrdup -- 26819304Speter * Strdup for wide character strings with an associated length. 26919304Speter * 270281373Sbapt * PUBLIC: CHAR_T *v_wstrdup(SCR *, const CHAR_T *, size_t); 27119304Speter */ 27219304SpeterCHAR_T * 273254225Speterv_wstrdup(SCR *sp, 274254225Speter const CHAR_T *str, 275254225Speter size_t len) 27619304Speter{ 27719304Speter CHAR_T *copy; 27819304Speter 279254225Speter MALLOC(sp, copy, CHAR_T *, (len + 1) * sizeof(CHAR_T)); 28019304Speter if (copy == NULL) 28119304Speter return (NULL); 282254225Speter MEMCPY(copy, str, len); 28319304Speter copy[len] = '\0'; 28419304Speter return (copy); 28519304Speter} 28619304Speter 28719304Speter/* 28819304Speter * nget_uslong -- 28919304Speter * Get an unsigned long, checking for overflow. 29019304Speter * 291281373Sbapt * PUBLIC: enum nresult nget_uslong(u_long *, const CHAR_T *, CHAR_T **, int); 29219304Speter */ 29319304Speterenum nresult 294254225Speternget_uslong( 295254225Speter u_long *valp, 296254225Speter const CHAR_T *p, 297254225Speter CHAR_T **endp, 298254225Speter int base) 29919304Speter{ 30019304Speter errno = 0; 301254225Speter *valp = STRTOUL(p, endp, base); 30219304Speter if (errno == 0) 30319304Speter return (NUM_OK); 30419304Speter if (errno == ERANGE && *valp == ULONG_MAX) 30519304Speter return (NUM_OVER); 30619304Speter return (NUM_ERR); 30719304Speter} 30819304Speter 30919304Speter/* 31019304Speter * nget_slong -- 31119304Speter * Convert a signed long, checking for overflow and underflow. 31219304Speter * 313281373Sbapt * PUBLIC: enum nresult nget_slong(long *, const CHAR_T *, CHAR_T **, int); 31419304Speter */ 31519304Speterenum nresult 316254225Speternget_slong( 317254225Speter long *valp, 318254225Speter const CHAR_T *p, 319254225Speter CHAR_T **endp, 320254225Speter int base) 32119304Speter{ 32219304Speter errno = 0; 323254225Speter *valp = STRTOL(p, endp, base); 32419304Speter if (errno == 0) 32519304Speter return (NUM_OK); 32619304Speter if (errno == ERANGE) { 32719304Speter if (*valp == LONG_MAX) 32819304Speter return (NUM_OVER); 32919304Speter if (*valp == LONG_MIN) 33019304Speter return (NUM_UNDER); 33119304Speter } 33219304Speter return (NUM_ERR); 33319304Speter} 33419304Speter 335254225Speter/* 336254225Speter * timepoint_steady -- 337254225Speter * Get a timestamp from a monotonic clock. 338254225Speter * 339281373Sbapt * PUBLIC: void timepoint_steady(struct timespec *); 340254225Speter */ 341254225Spetervoid 342254225Spetertimepoint_steady( 343254225Speter struct timespec *ts) 344254225Speter{ 345254225Speter#ifdef __APPLE__ 346254225Speter static mach_timebase_info_data_t base = { 0 }; 347254225Speter uint64_t val; 348254225Speter uint64_t ns; 349254225Speter 350254225Speter if (base.denom == 0) 351254225Speter (void)mach_timebase_info(&base); 352254225Speter 353254225Speter val = mach_absolute_time(); 354254225Speter ns = val * base.numer / base.denom; 355254225Speter ts->tv_sec = ns / 1000000000; 356254225Speter ts->tv_nsec = ns % 1000000000; 35719304Speter#else 358254225Speter#ifdef CLOCK_MONOTONIC_FAST 359254225Speter (void)clock_gettime(CLOCK_MONOTONIC_FAST, ts); 360254225Speter#else 361254225Speter (void)clock_gettime(CLOCK_MONOTONIC, ts); 36219304Speter#endif 363254225Speter#endif 364254225Speter} 36519304Speter 36619304Speter/* 367254225Speter * timepoint_system -- 368254225Speter * Get the current calendar time. 369254225Speter * 370281373Sbapt * PUBLIC: void timepoint_system(struct timespec *); 371254225Speter */ 372254225Spetervoid 373254225Spetertimepoint_system( 374254225Speter struct timespec *ts) 375254225Speter{ 376254225Speter#ifdef __APPLE__ 377254225Speter clock_serv_t clk; 378254225Speter mach_timespec_t mts; 379254225Speter kern_return_t kr; 380254225Speter 381254225Speter kr = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &clk); 382254225Speter if (kr != KERN_SUCCESS) 383254225Speter return; 384254225Speter (void)clock_get_time(clk, &mts); 385254225Speter (void)mach_port_deallocate(mach_task_self(), clk); 386254225Speter ts->tv_sec = mts.tv_sec; 387254225Speter ts->tv_nsec = mts.tv_nsec; 388254225Speter#else 389254225Speter#ifdef CLOCK_REALTIME_FAST 390254225Speter (void)clock_gettime(CLOCK_REALTIME_FAST, ts); 391254225Speter#else 392254225Speter (void)clock_gettime(CLOCK_REALTIME, ts); 393254225Speter#endif 394254225Speter#endif 395254225Speter} 396254225Speter 397254225Speter#ifdef DEBUG 398254225Speter#include <stdarg.h> 399254225Speter 400254225Speter/* 40119304Speter * TRACE -- 40219304Speter * debugging trace routine. 40319304Speter * 404281373Sbapt * PUBLIC: void TRACE(SCR *, const char *, ...); 40519304Speter */ 40619304Spetervoid 407254225SpeterTRACE( 408254225Speter SCR *sp, 409254225Speter const char *fmt, 410254225Speter ...) 41119304Speter{ 41219304Speter FILE *tfp; 41319304Speter va_list ap; 41419304Speter 41519304Speter if ((tfp = sp->gp->tracefp) == NULL) 41619304Speter return; 41719304Speter va_start(ap, fmt); 41819304Speter (void)vfprintf(tfp, fmt, ap); 41919304Speter va_end(ap); 42019304Speter 42119304Speter (void)fflush(tfp); 42219304Speter} 42319304Speter#endif 424