diff options
author | Peter Wemm <peter@FreeBSD.org> | 2013-08-11 09:44:58 +0000 |
---|---|---|
committer | Peter Wemm <peter@FreeBSD.org> | 2013-08-11 09:44:58 +0000 |
commit | be3e4646eef6a3abcf58590dac24a5dfe54540f6 (patch) | |
tree | 5a0e2514f154d0eb24f2235092423adb95ac75ac /common/util.c | |
parent | 84ed61ee234d2654ec965be5bfdda4269f9dc4fd (diff) | |
download | src-be3e4646eef6a3abcf58590dac24a5dfe54540f6.tar.gz src-be3e4646eef6a3abcf58590dac24a5dfe54540f6.zip |
Import nvi-2.1.1-4334a8297f into the work area. This is the gsoc-2011vendor/nvi/2.1.1-4334a8297f
project to clean up and backport multibyte support from other nvi forks
in a form we can use.
GSoC info: http://www.google-melange.com/gsoc/proposal/review/google/gsoc2011/zy/1
Repo at: https://github.com/lichray/nvi2
Obtained from: Zhihao Yuan <lichray@gmail.com>
Notes
Notes:
svn path=/vendor/nvi/dist/; revision=254211
svn path=/vendor/nvi/2.1.1-4334a8297f/; revision=254212; tag=vendor/nvi/2.1.1-4334a8297f
Diffstat (limited to 'common/util.c')
-rw-r--r-- | common/util.c | 303 |
1 files changed, 248 insertions, 55 deletions
diff --git a/common/util.c b/common/util.c index 5a4422a2c422..43fa9d1e9f20 100644 --- a/common/util.c +++ b/common/util.c @@ -10,18 +10,27 @@ #include "config.h" #ifndef lint -static const char sccsid[] = "@(#)util.c 10.11 (Berkeley) 9/15/96"; +static const char sccsid[] = "$Id: util.c,v 10.30 2013/03/19 10:00:27 yamt Exp $"; #endif /* not lint */ #include <sys/types.h> #include <sys/queue.h> +#ifdef __APPLE__ +#include <mach/clock.h> +#include <mach/mach.h> +#include <mach/mach_time.h> +#endif + #include <bitstring.h> +#include <ctype.h> #include <errno.h> #include <limits.h> +#include <pwd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include <unistd.h> #include "common.h" @@ -33,10 +42,11 @@ static const char sccsid[] = "@(#)util.c 10.11 (Berkeley) 9/15/96"; * PUBLIC: void *binc __P((SCR *, void *, size_t *, size_t)); */ void * -binc(sp, bp, bsizep, min) - SCR *sp; /* sp MAY BE NULL!!! */ - void *bp; - size_t *bsizep, min; +binc( + SCR *sp, /* sp MAY BE NULL!!! */ + void *bp, + size_t *bsizep, + size_t min) { size_t csize; @@ -44,14 +54,10 @@ binc(sp, bp, bsizep, min) if (min && *bsizep >= min) return (bp); - csize = *bsizep + MAX(min, 256); + csize = p2roundup(MAX(min, 256)); REALLOC(sp, bp, void *, csize); if (bp == NULL) { - /* - * Theoretically, realloc is supposed to leave any already - * held memory alone if it can't get more. Don't trust it. - */ *bsizep = 0; return (NULL); } @@ -73,12 +79,12 @@ binc(sp, bp, bsizep, min) * PUBLIC: int nonblank __P((SCR *, recno_t, size_t *)); */ int -nonblank(sp, lno, cnop) - SCR *sp; - recno_t lno; - size_t *cnop; +nonblank( + SCR *sp, + recno_t lno, + size_t *cnop) { - char *p; + CHAR_T *p; size_t cnt, len, off; int isempty; @@ -95,7 +101,7 @@ nonblank(sp, lno, cnop) return (0); for (cnt = off, p = &p[off], - len -= off; len && isblank(*p); ++cnt, ++p, --len); + len -= off; len && ISBLANK(*p); ++cnt, ++p, --len); /* Set the return. */ *cnop = len ? cnt : cnt - 1; @@ -109,8 +115,7 @@ nonblank(sp, lno, cnop) * PUBLIC: char *tail __P((char *)); */ char * -tail(path) - char *path; +tail(char *path) { char *p; @@ -120,23 +125,161 @@ tail(path) } /* + * join -- + * Join two paths; need free. + * + * PUBLIC: char *join __P((char *, char *)); + */ +char * +join( + char *path1, + char *path2) +{ + char *p; + + if (path1[0] == '\0' || path2[0] == '/') + return strdup(path2); + (void)asprintf(&p, path1[strlen(path1)-1] == '/' ? + "%s%s" : "%s/%s", path1, path2); + return p; +} + +/* + * expanduser -- + * Return a "~" or "~user" expanded path; need free. + * + * PUBLIC: char *expanduser __P((char *)); + */ +char * +expanduser(char *str) +{ + struct passwd *pwd; + char *p, *t, *u, *h; + + /* + * This function always expands the content between the + * leading '~' and the first '/' or '\0' from the input. + * Return NULL whenever we fail to do so. + */ + if (*str != '~') + return (NULL); + p = str + 1; + for (t = p; *t != '/' && *t != '\0'; ++t) + continue; + if (t == p) { + /* ~ */ + if (issetugid() != 0 || + (h = getenv("HOME")) == NULL) { + if (((h = getlogin()) != NULL && + (pwd = getpwnam(h)) != NULL) || + (pwd = getpwuid(getuid())) != NULL) + h = pwd->pw_dir; + else + return (NULL); + } + } else { + /* ~user */ + if ((u = strndup(p, t - p)) == NULL) + return (NULL); + if ((pwd = getpwnam(u)) == NULL) { + free(u); + return (NULL); + } else + h = pwd->pw_dir; + free(u); + } + + for (; *t == '/' && *t != '\0'; ++t) + continue; + return (join(h, t)); +} + +/* + * quote -- + * Return a escaped string for /bin/sh; need free. + * + * PUBLIC: char *quote __P((char *)); + */ +char * +quote(char *str) +{ + char *p, *t; + size_t i = 0, n = 0; + int unsafe = 0; + + for (p = str; *p != '\0'; p++, i++) { + if (*p == '\'') + n++; + if (unsafe) + continue; + if (isascii(*p)) { + if (isalnum(*p)) + continue; + switch (*p) { + case '%': case '+': case ',': case '-': case '.': + case '/': case ':': case '=': case '@': case '_': + continue; + } + } + unsafe = 1; + } + if (!unsafe) + t = strdup(str); +#define SQT "'\\''" + else if ((p = t = malloc(i + n * (sizeof(SQT) - 2) + 3)) != NULL) { + *p++ = '\''; + for (; *str != '\0'; str++) { + if (*str == '\'') { + (void)memcpy(p, SQT, sizeof(SQT) - 1); + p += sizeof(SQT) - 1; + } else + *p++ = *str; + } + *p++ = '\''; + *p = '\0'; + } + return t; +} + +/* * v_strdup -- + * Strdup for 8-bit character strings with an associated length. + * + * PUBLIC: char *v_strdup __P((SCR *, const char *, size_t)); + */ +char * +v_strdup( + SCR *sp, + const char *str, + size_t len) +{ + char *copy; + + MALLOC(sp, copy, char *, len + 1); + if (copy == NULL) + return (NULL); + memcpy(copy, str, len); + copy[len] = '\0'; + return (copy); +} + +/* + * v_wstrdup -- * Strdup for wide character strings with an associated length. * - * PUBLIC: CHAR_T *v_strdup __P((SCR *, const CHAR_T *, size_t)); + * PUBLIC: CHAR_T *v_wstrdup __P((SCR *, const CHAR_T *, size_t)); */ CHAR_T * -v_strdup(sp, str, len) - SCR *sp; - const CHAR_T *str; - size_t len; +v_wstrdup(SCR *sp, + const CHAR_T *str, + size_t len) { CHAR_T *copy; - MALLOC(sp, copy, CHAR_T *, len + 1); + MALLOC(sp, copy, CHAR_T *, (len + 1) * sizeof(CHAR_T)); if (copy == NULL) return (NULL); - memcpy(copy, str, len * sizeof(CHAR_T)); + MEMCPY(copy, str, len); copy[len] = '\0'; return (copy); } @@ -145,17 +288,17 @@ v_strdup(sp, str, len) * nget_uslong -- * Get an unsigned long, checking for overflow. * - * PUBLIC: enum nresult nget_uslong __P((u_long *, const char *, char **, int)); + * PUBLIC: enum nresult nget_uslong __P((u_long *, const CHAR_T *, CHAR_T **, int)); */ enum nresult -nget_uslong(valp, p, endp, base) - u_long *valp; - const char *p; - char **endp; - int base; +nget_uslong( + u_long *valp, + const CHAR_T *p, + CHAR_T **endp, + int base) { errno = 0; - *valp = strtoul(p, endp, base); + *valp = STRTOUL(p, endp, base); if (errno == 0) return (NUM_OK); if (errno == ERANGE && *valp == ULONG_MAX) @@ -167,17 +310,17 @@ nget_uslong(valp, p, endp, base) * nget_slong -- * Convert a signed long, checking for overflow and underflow. * - * PUBLIC: enum nresult nget_slong __P((long *, const char *, char **, int)); + * PUBLIC: enum nresult nget_slong __P((long *, const CHAR_T *, CHAR_T **, int)); */ enum nresult -nget_slong(valp, p, endp, base) - long *valp; - const char *p; - char **endp; - int base; +nget_slong( + long *valp, + const CHAR_T *p, + CHAR_T **endp, + int base) { errno = 0; - *valp = strtol(p, endp, base); + *valp = STRTOL(p, endp, base); if (errno == 0) return (NUM_OK); if (errno == ERANGE) { @@ -189,12 +332,70 @@ nget_slong(valp, p, endp, base) return (NUM_ERR); } -#ifdef DEBUG -#ifdef __STDC__ -#include <stdarg.h> +/* + * timepoint_steady -- + * Get a timestamp from a monotonic clock. + * + * PUBLIC: void timepoint_steady __P((struct timespec *)); + */ +void +timepoint_steady( + struct timespec *ts) +{ +#ifdef __APPLE__ + static mach_timebase_info_data_t base = { 0 }; + uint64_t val; + uint64_t ns; + + if (base.denom == 0) + (void)mach_timebase_info(&base); + + val = mach_absolute_time(); + ns = val * base.numer / base.denom; + ts->tv_sec = ns / 1000000000; + ts->tv_nsec = ns % 1000000000; +#else +#ifdef CLOCK_MONOTONIC_FAST + (void)clock_gettime(CLOCK_MONOTONIC_FAST, ts); #else -#include <varargs.h> + (void)clock_gettime(CLOCK_MONOTONIC, ts); +#endif #endif +} + +/* + * timepoint_system -- + * Get the current calendar time. + * + * PUBLIC: void timepoint_system __P((struct timespec *)); + */ +void +timepoint_system( + struct timespec *ts) +{ +#ifdef __APPLE__ + clock_serv_t clk; + mach_timespec_t mts; + kern_return_t kr; + + kr = host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &clk); + if (kr != KERN_SUCCESS) + return; + (void)clock_get_time(clk, &mts); + (void)mach_port_deallocate(mach_task_self(), clk); + ts->tv_sec = mts.tv_sec; + ts->tv_nsec = mts.tv_nsec; +#else +#ifdef CLOCK_REALTIME_FAST + (void)clock_gettime(CLOCK_REALTIME_FAST, ts); +#else + (void)clock_gettime(CLOCK_REALTIME, ts); +#endif +#endif +} + +#ifdef DEBUG +#include <stdarg.h> /* * TRACE -- @@ -203,25 +404,17 @@ nget_slong(valp, p, endp, base) * PUBLIC: void TRACE __P((SCR *, const char *, ...)); */ void -#ifdef __STDC__ -TRACE(SCR *sp, const char *fmt, ...) -#else -TRACE(sp, fmt, va_alist) - SCR *sp; - char *fmt; - va_dcl -#endif +TRACE( + SCR *sp, + const char *fmt, + ...) { FILE *tfp; va_list ap; if ((tfp = sp->gp->tracefp) == NULL) return; -#ifdef __STDC__ va_start(ap, fmt); -#else - va_start(ap); -#endif (void)vfprintf(tfp, fmt, ap); va_end(ap); |