1 /* $OpenBSD: util.c,v 1.8 2009/10/27 23:59:47 deraadt Exp $ */ 2 3 /*- 4 * Copyright (c) 1991, 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * Copyright (c) 1991, 1993, 1994, 1995, 1996 7 * Keith Bostic. All rights reserved. 8 * 9 * See the LICENSE file for redistribution information. 10 */ 11 12 #include "config.h" 13 14 #include <sys/param.h> 15 #include <sys/queue.h> 16 17 #include <bitstring.h> 18 #include <errno.h> 19 #include <limits.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <unistd.h> 24 25 #include "common.h" 26 27 /* 28 * binc -- 29 * Increase the size of a buffer. 30 * 31 * PUBLIC: void *binc(SCR *, void *, size_t *, size_t); 32 */ 33 void * 34 binc(sp, bp, bsizep, min) 35 SCR *sp; /* sp MAY BE NULL!!! */ 36 void *bp; 37 size_t *bsizep, min; 38 { 39 size_t csize; 40 41 /* If already larger than the minimum, just return. */ 42 if (min && *bsizep >= min) 43 return (bp); 44 45 csize = *bsizep + MAX(min, 256); 46 REALLOC(sp, bp, void *, csize); 47 48 if (bp == NULL) { 49 /* 50 * Theoretically, realloc is supposed to leave any already 51 * held memory alone if it can't get more. Don't trust it. 52 */ 53 *bsizep = 0; 54 return (NULL); 55 } 56 /* 57 * Memory is guaranteed to be zero-filled, various parts of 58 * nvi depend on this. 59 */ 60 memset((char *)bp + *bsizep, 0, csize - *bsizep); 61 *bsizep = csize; 62 return (bp); 63 } 64 65 /* 66 * nonblank -- 67 * Set the column number of the first non-blank character 68 * including or after the starting column. On error, set 69 * the column to 0, it's safest. 70 * 71 * PUBLIC: int nonblank(SCR *, recno_t, size_t *); 72 */ 73 int 74 nonblank(sp, lno, cnop) 75 SCR *sp; 76 recno_t lno; 77 size_t *cnop; 78 { 79 char *p; 80 size_t cnt, len, off; 81 int isempty; 82 83 /* Default. */ 84 off = *cnop; 85 *cnop = 0; 86 87 /* Get the line, succeeding in an empty file. */ 88 if (db_eget(sp, lno, &p, &len, &isempty)) 89 return (!isempty); 90 91 /* Set the offset. */ 92 if (len == 0 || off >= len) 93 return (0); 94 95 for (cnt = off, p = &p[off], 96 len -= off; len && isblank(*p); ++cnt, ++p, --len); 97 98 /* Set the return. */ 99 *cnop = len ? cnt : cnt - 1; 100 return (0); 101 } 102 103 /* 104 * tail -- 105 * Return tail of a path. 106 * 107 * PUBLIC: char *tail(char *); 108 */ 109 char * 110 tail(path) 111 char *path; 112 { 113 char *p; 114 115 if ((p = strrchr(path, '/')) == NULL) 116 return (path); 117 return (p + 1); 118 } 119 120 /* 121 * v_strdup -- 122 * Strdup for wide character strings with an associated length. 123 * 124 * PUBLIC: CHAR_T *v_strdup(SCR *, const CHAR_T *, size_t); 125 */ 126 CHAR_T * 127 v_strdup(sp, str, len) 128 SCR *sp; 129 const CHAR_T *str; 130 size_t len; 131 { 132 CHAR_T *copy; 133 134 MALLOC(sp, copy, CHAR_T *, len + 1); 135 if (copy == NULL) 136 return (NULL); 137 memcpy(copy, str, len * sizeof(CHAR_T)); 138 copy[len] = '\0'; 139 return (copy); 140 } 141 142 /* 143 * nget_uslong -- 144 * Get an unsigned long, checking for overflow. 145 * 146 * PUBLIC: enum nresult nget_uslong(u_long *, const char *, char **, int); 147 */ 148 enum nresult 149 nget_uslong(valp, p, endp, base) 150 u_long *valp; 151 const char *p; 152 char **endp; 153 int base; 154 { 155 errno = 0; 156 *valp = strtoul(p, endp, base); 157 if (errno == 0) 158 return (NUM_OK); 159 if (errno == ERANGE && *valp == ULONG_MAX) 160 return (NUM_OVER); 161 return (NUM_ERR); 162 } 163 164 /* 165 * nget_slong -- 166 * Convert a signed long, checking for overflow and underflow. 167 * 168 * PUBLIC: enum nresult nget_slong(long *, const char *, char **, int); 169 */ 170 enum nresult 171 nget_slong(valp, p, endp, base) 172 long *valp; 173 const char *p; 174 char **endp; 175 int base; 176 { 177 errno = 0; 178 *valp = strtol(p, endp, base); 179 if (errno == 0) 180 return (NUM_OK); 181 if (errno == ERANGE) { 182 if (*valp == LONG_MAX) 183 return (NUM_OVER); 184 if (*valp == LONG_MIN) 185 return (NUM_UNDER); 186 } 187 return (NUM_ERR); 188 } 189 190 #ifdef DEBUG 191 #include <stdarg.h> 192 193 /* 194 * TRACE -- 195 * debugging trace routine. 196 * 197 * PUBLIC: void TRACE(SCR *, const char *, ...); 198 */ 199 void 200 TRACE(SCR *sp, const char *fmt, ...) 201 { 202 FILE *tfp; 203 va_list ap; 204 205 if ((tfp = sp->gp->tracefp) == NULL) 206 return; 207 va_start(ap, fmt); 208 (void)vfprintf(tfp, fmt, ap); 209 va_end(ap); 210 211 (void)fflush(tfp); 212 } 213 #endif 214