![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
strcompat.c
Go to the documentation of this file.
00001 /* 00002 * Asterisk -- An open source telephony toolkit. 00003 * 00004 * Copyright (C) 1999 - 2006, Digium, Inc. 00005 * 00006 * See http://www.asterisk.org for more information about 00007 * the Asterisk project. Please do not directly contact 00008 * any of the maintainers of this project for assistance; 00009 * the project provides a web site, mailing lists and IRC 00010 * channels for your use. 00011 * 00012 * This program is free software, distributed under the terms of 00013 * the GNU General Public License Version 2. See the LICENSE file 00014 * at the top of the source tree. 00015 */ 00016 00017 /*! \file 00018 * 00019 * \brief Compatibility functions for strsep and strtoq missing on Solaris 00020 */ 00021 00022 #include "asterisk.h" 00023 00024 #include <sys/types.h> 00025 #include <ctype.h> 00026 #include <stdio.h> 00027 #include <stdlib.h> 00028 #include <string.h> 00029 00030 #ifdef HAVE_ALLOCA_H 00031 #include <alloca.h> 00032 #endif 00033 00034 #ifndef HAVE_STRSEP 00035 char *strsep(char **str, const char *delims) 00036 { 00037 char *token; 00038 00039 if (!*str) { 00040 /* No more tokens */ 00041 return NULL; 00042 } 00043 00044 token = *str; 00045 while (**str != '\0') { 00046 if (strchr(delims, **str)) { 00047 **str = '\0'; 00048 (*str)++; 00049 return token; 00050 } 00051 (*str)++; 00052 } 00053 00054 /* There is no other token */ 00055 *str = NULL; 00056 00057 return token; 00058 } 00059 #endif 00060 00061 #ifndef HAVE_SETENV 00062 int setenv(const char *name, const char *value, int overwrite) 00063 { 00064 unsigned char *buf; 00065 int buflen; 00066 00067 buflen = strlen(name) + strlen(value) + 2; 00068 buf = alloca(buflen); 00069 00070 if (!overwrite && getenv(name)) 00071 return 0; 00072 00073 snprintf(buf, buflen, "%s=%s", name, value); 00074 00075 return putenv(buf); 00076 } 00077 #endif 00078 00079 #ifndef HAVE_UNSETENV 00080 int unsetenv(const char *name) 00081 { 00082 return setenv(name, "", 0); 00083 } 00084 #endif 00085 00086 #ifndef HAVE_STRCASESTR 00087 static char *upper(const char *orig, char *buf, int bufsize) 00088 { 00089 int i = 0; 00090 00091 while (i < (bufsize - 1) && orig[i]) { 00092 buf[i] = toupper(orig[i]); 00093 i++; 00094 } 00095 00096 buf[i] = '\0'; 00097 00098 return buf; 00099 } 00100 00101 char *strcasestr(const char *haystack, const char *needle) 00102 { 00103 char *u1, *u2; 00104 int u1len = strlen(haystack) + 1, u2len = strlen(needle) + 1; 00105 00106 u1 = alloca(u1len); 00107 u2 = alloca(u2len); 00108 if (u1 && u2) { 00109 char *offset; 00110 if (u2len > u1len) { 00111 /* Needle bigger than haystack */ 00112 return NULL; 00113 } 00114 offset = strstr(upper(haystack, u1, u1len), upper(needle, u2, u2len)); 00115 if (offset) { 00116 /* Return the offset into the original string */ 00117 return ((char *)((unsigned long)haystack + (unsigned long)(offset - u1))); 00118 } else { 00119 return NULL; 00120 } 00121 } else { 00122 return NULL; 00123 } 00124 } 00125 #endif /* !HAVE_STRCASESTR */ 00126 00127 #ifndef HAVE_STRNLEN 00128 size_t strnlen(const char *s, size_t n) 00129 { 00130 size_t len; 00131 00132 for (len = 0; len < n; len++) 00133 if (s[len] == '\0') 00134 break; 00135 00136 return len; 00137 } 00138 #endif /* !HAVE_STRNLEN */ 00139 00140 #if !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC) 00141 char *strndup(const char *s, size_t n) 00142 { 00143 size_t len = strnlen(s, n); 00144 char *new = malloc(len + 1); 00145 00146 if (!new) 00147 return NULL; 00148 00149 new[len] = '\0'; 00150 return memcpy(new, s, len); 00151 } 00152 #endif /* !defined(HAVE_STRNDUP) && !defined(__AST_DEBUG_MALLOC) */ 00153 00154 #if !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC) 00155 int vasprintf(char **strp, const char *fmt, va_list ap) 00156 { 00157 int size; 00158 va_list ap2; 00159 char s; 00160 00161 *strp = NULL; 00162 va_copy(ap2, ap); 00163 size = vsnprintf(&s, 1, fmt, ap2); 00164 va_end(ap2); 00165 *strp = malloc(size + 1); 00166 if (!*strp) 00167 return -1; 00168 vsnprintf(*strp, size + 1, fmt, ap); 00169 00170 return size; 00171 } 00172 #endif /* !defined(HAVE_VASPRINTF) && !defined(__AST_DEBUG_MALLOC) */ 00173 00174 /* 00175 * Based on Code from bsd-asprintf from OpenSSH 00176 * Copyright (c) 2004 Darren Tucker. 00177 * 00178 * Based originally on asprintf.c from OpenBSD: 00179 * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> 00180 * 00181 * Permission to use, copy, modify, and distribute this software for any 00182 * purpose with or without fee is hereby granted, provided that the above 00183 * copyright notice and this permission notice appear in all copies. 00184 * 00185 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 00186 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00187 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 00188 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00189 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00190 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00191 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00192 */ 00193 #if !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC) 00194 int asprintf(char **str, const char *fmt, ...) 00195 { 00196 va_list ap; 00197 int ret; 00198 00199 *str = NULL; 00200 va_start(ap, fmt); 00201 ret = vasprintf(str, fmt, ap); 00202 va_end(ap); 00203 00204 return ret; 00205 } 00206 #endif /* !defined(HAVE_ASPRINTF) && !defined(__AST_DEBUG_MALLOC) */ 00207 00208 #ifndef HAVE_STRTOQ 00209 #ifndef LONG_MIN 00210 #define LONG_MIN (-9223372036854775807L-1L) 00211 /* min value of a "long int" */ 00212 #endif 00213 #ifndef LONG_MAX 00214 #define LONG_MAX 9223372036854775807L 00215 /* max value of a "long int" */ 00216 #endif 00217 00218 /*! \brief 00219 * Convert a string to a quad integer. 00220 * 00221 * \note Ignores `locale' stuff. Assumes that the upper and lower case 00222 * alphabets and digits are each contiguous. 00223 */ 00224 uint64_t strtoq(const char *nptr, char **endptr, int base) 00225 { 00226 const char *s; 00227 uint64_t acc; 00228 unsigned char c; 00229 uint64_t qbase, cutoff; 00230 int neg, any, cutlim; 00231 00232 /* 00233 * Skip white space and pick up leading +/- sign if any. 00234 * If base is 0, allow 0x for hex and 0 for octal, else 00235 * assume decimal; if base is already 16, allow 0x. 00236 */ 00237 s = nptr; 00238 do { 00239 c = *s++; 00240 } while (isspace(c)); 00241 if (c == '-') { 00242 neg = 1; 00243 c = *s++; 00244 } else { 00245 neg = 0; 00246 if (c == '+') 00247 c = *s++; 00248 } 00249 if ((base == 0 || base == 16) && 00250 c == '\0' && (*s == 'x' || *s == 'X')) { 00251 c = s[1]; 00252 s += 2; 00253 base = 16; 00254 } 00255 if (base == 0) 00256 base = c == '\0' ? 8 : 10; 00257 00258 /* 00259 * Compute the cutoff value between legal numbers and illegal 00260 * numbers. That is the largest legal value, divided by the 00261 * base. An input number that is greater than this value, if 00262 * followed by a legal input character, is too big. One that 00263 * is equal to this value may be valid or not; the limit 00264 * between valid and invalid numbers is then based on the last 00265 * digit. For instance, if the range for quads is 00266 * [-9223372036854775808..9223372036854775807] and the input base 00267 * is 10, cutoff will be set to 922337203685477580 and cutlim to 00268 * either 7 (neg==0) or 8 (neg==1), meaning that if we have 00269 * accumulated a value > 922337203685477580, or equal but the 00270 * next digit is > 7 (or 8), the number is too big, and we will 00271 * return a range error. 00272 * 00273 * Set any if any `digits' consumed; make it negative to indicate 00274 * overflow. 00275 */ 00276 qbase = (unsigned)base; 00277 cutoff = neg ? (uint64_t)-(LONG_MIN + LONG_MAX) + LONG_MAX : LONG_MAX; 00278 cutlim = cutoff % qbase; 00279 cutoff /= qbase; 00280 for (acc = 0, any = 0;; c = *s++) { 00281 if (!isascii(c)) 00282 break; 00283 if (isdigit(c)) 00284 c -= '\0'; 00285 else if (isalpha(c)) 00286 c -= isupper(c) ? 'A' - 10 : 'a' - 10; 00287 else 00288 break; 00289 if (c >= base) 00290 break; 00291 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 00292 any = -1; 00293 else { 00294 any = 1; 00295 acc *= qbase; 00296 acc += c; 00297 } 00298 } 00299 if (any < 0) { 00300 acc = neg ? LONG_MIN : LONG_MAX; 00301 } else if (neg) 00302 acc = -acc; 00303 if (endptr != 0) 00304 *((const char **)endptr) = any ? s - 1 : nptr; 00305 return acc; 00306 } 00307 #endif /* !HAVE_STRTOQ */ 00308 00309 #ifndef HAVE_GETLOADAVG 00310 #ifdef linux 00311 /*! \brief Alternative method of getting load avg on Linux only */ 00312 int getloadavg(double *list, int nelem) 00313 { 00314 FILE *LOADAVG; 00315 double avg[3] = { 0.0, 0.0, 0.0 }; 00316 int i, res = -1; 00317 00318 if ((LOADAVG = fopen("/proc/loadavg", "r"))) { 00319 fscanf(LOADAVG, "%lf %lf %lf", &avg[0], &avg[1], &avg[2]); 00320 res = 0; 00321 fclose(LOADAVG); 00322 } 00323 00324 for (i = 0; (i < nelem) && (i < 3); i++) { 00325 list[i] = avg[i]; 00326 } 00327 00328 return res; 00329 } 00330 #else /* !linux */ 00331 /*! \brief Return something that won't cancel the call, but still return -1, in case 00332 * we correct the implementation to check return value */ 00333 int getloadavg(double *list, int nelem) 00334 { 00335 int i; 00336 00337 for (i = 0; i < nelem; i++) { 00338 list[i] = 0.1; 00339 } 00340 return -1; 00341 } 00342 #endif /* linux */ 00343 #endif /* !HAVE_GETLOADAVG */