1 /* $OpenBSD: str.c,v 1.14 2008/10/03 19:45:34 deraadt Exp $ */ 2 /* $NetBSD: str.c,v 1.6 1995/03/21 09:03:24 cgd Exp $ */ 3 4 /*- 5 * Copyright (c) 1991, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "@(#)str.c 8.1 (Berkeley) 5/31/93"; 36 #else 37 static char rcsid[] = "$OpenBSD: str.c,v 1.14 2008/10/03 19:45:34 deraadt Exp $"; 38 #endif 39 #endif /* not lint */ 40 41 #define MALLOC_INCR 128 42 43 /* 44 * tc.str.c: Short string package 45 * This has been a lesson of how to write buggy code! 46 */ 47 48 #include <sys/types.h> 49 #include <stdarg.h> 50 #include <vis.h> 51 52 #include "csh.h" 53 #include "extern.h" 54 55 #ifdef SHORT_STRINGS 56 57 Char ** 58 blk2short(char **src) 59 { 60 size_t n; 61 Char **sdst, **dst; 62 63 /* 64 * Count 65 */ 66 for (n = 0; src[n] != NULL; n++) 67 continue; 68 sdst = dst = (Char **) xmalloc((size_t) ((n + 1) * sizeof(Char *))); 69 70 for (; *src != NULL; src++) 71 *dst++ = SAVE(*src); 72 *dst = NULL; 73 return (sdst); 74 } 75 76 char ** 77 short2blk(Char **src) 78 { 79 size_t n; 80 char **sdst, **dst; 81 82 /* 83 * Count 84 */ 85 for (n = 0; src[n] != NULL; n++) 86 continue; 87 sdst = dst = (char **) xmalloc((size_t) ((n + 1) * sizeof(char *))); 88 89 for (; *src != NULL; src++) 90 *dst++ = strsave(short2str(*src)); 91 *dst = NULL; 92 return (sdst); 93 } 94 95 Char * 96 str2short(char *src) 97 { 98 static Char *sdst; 99 static size_t dstsize = 0; 100 Char *dst, *edst; 101 102 if (src == NULL) 103 return (NULL); 104 105 if (sdst == (NULL)) { 106 dstsize = MALLOC_INCR; 107 sdst = (Char *) xmalloc((size_t) dstsize * sizeof(Char)); 108 } 109 110 dst = sdst; 111 edst = &dst[dstsize]; 112 while (*src) { 113 *dst++ = (Char) ((unsigned char) *src++); 114 if (dst == edst) { 115 dstsize += MALLOC_INCR; 116 sdst = (Char *) xrealloc((ptr_t) sdst, 117 (size_t) dstsize * sizeof(Char)); 118 edst = &sdst[dstsize]; 119 dst = &edst[-MALLOC_INCR]; 120 } 121 } 122 *dst = 0; 123 return (sdst); 124 } 125 126 char * 127 short2str(Char *src) 128 { 129 static char *sdst = NULL; 130 static size_t dstsize = 0; 131 char *dst, *edst; 132 133 if (src == NULL) 134 return (NULL); 135 136 if (sdst == NULL) { 137 dstsize = MALLOC_INCR; 138 sdst = (char *) xmalloc((size_t) dstsize * sizeof(char)); 139 } 140 dst = sdst; 141 edst = &dst[dstsize]; 142 while (*src) { 143 *dst++ = (char) *src++; 144 if (dst == edst) { 145 dstsize += MALLOC_INCR; 146 sdst = (char *) xrealloc((ptr_t) sdst, 147 (size_t) dstsize * sizeof(char)); 148 edst = &sdst[dstsize]; 149 dst = &edst[-MALLOC_INCR]; 150 } 151 } 152 *dst = 0; 153 return (sdst); 154 } 155 156 size_t 157 s_strlcpy(Char *dst, const Char *src, size_t siz) 158 { 159 Char *d = dst; 160 const Char *s = src; 161 size_t n = siz; 162 163 /* Copy as many bytes as will fit */ 164 if (n != 0 && --n != 0) { 165 do { 166 if ((*d++ = *s++) == 0) 167 break; 168 } while (--n != 0); 169 } 170 171 /* Not enough room in dst, add NUL and traverse rest of src */ 172 if (n == 0) { 173 if (siz != 0) 174 *d = '\0'; /* NUL-terminate dst */ 175 while (*s++) 176 ; 177 } 178 179 return(s - src - 1); /* count does not include NUL */ 180 } 181 182 size_t 183 s_strlcat(Char *dst, const Char *src, size_t siz) 184 { 185 Char *d = dst; 186 const Char *s = src; 187 size_t n = siz; 188 size_t dlen; 189 190 /* Find the end of dst and adjust bytes left but don't go past end */ 191 while (n-- != 0 && *d != '\0') 192 d++; 193 dlen = d - dst; 194 n = siz - dlen; 195 196 if (n == 0) 197 return(dlen + s_strlen((Char *)s)); 198 while (*s != '\0') { 199 if (n != 1) { 200 *d++ = *s; 201 n--; 202 } 203 s++; 204 } 205 *d = '\0'; 206 207 return(dlen + (s - src)); /* count does not include NUL */ 208 } 209 210 Char * 211 s_strchr(Char *str, int ch) 212 { 213 do 214 if (*str == ch) 215 return (str); 216 while (*str++) 217 ; 218 return (NULL); 219 } 220 221 Char * 222 s_strrchr(Char *str, int ch) 223 { 224 Char *rstr; 225 226 rstr = NULL; 227 do 228 if (*str == ch) 229 rstr = str; 230 while (*str++) 231 ; 232 return (rstr); 233 } 234 235 size_t 236 s_strlen(Char *str) 237 { 238 size_t n; 239 240 for (n = 0; *str++; n++) 241 continue; 242 return (n); 243 } 244 245 int 246 s_strcmp(Char *str1, Char *str2) 247 { 248 for (; *str1 && *str1 == *str2; str1++, str2++) 249 continue; 250 /* 251 * The following case analysis is necessary so that characters which look 252 * negative collate low against normal characters but high against the 253 * end-of-string NUL. 254 */ 255 if (*str1 == '\0' && *str2 == '\0') 256 return (0); 257 else if (*str1 == '\0') 258 return (-1); 259 else if (*str2 == '\0') 260 return (1); 261 else 262 return (*str1 - *str2); 263 } 264 265 int 266 s_strncmp(Char *str1, Char *str2, size_t n) 267 { 268 if (n == 0) 269 return (0); 270 do { 271 if (*str1 != *str2) { 272 /* 273 * The following case analysis is necessary so that characters 274 * which look negative collate low against normal characters 275 * but high against the end-of-string NUL. 276 */ 277 if (*str1 == '\0') 278 return (-1); 279 else if (*str2 == '\0') 280 return (1); 281 else 282 return (*str1 - *str2); 283 break; 284 } 285 if (*str1 == '\0') 286 return(0); 287 str1++, str2++; 288 } while (--n != 0); 289 return(0); 290 } 291 292 Char * 293 s_strsave(Char *s) 294 { 295 Char *n; 296 Char *p; 297 298 if (s == 0) 299 s = STRNULL; 300 for (p = s; *p++;) 301 continue; 302 n = p = (Char *) xmalloc((size_t) ((p - s) * sizeof(Char))); 303 while ((*p++ = *s++) != '\0') 304 continue; 305 return (n); 306 } 307 308 Char * 309 s_strspl(Char *cp, Char *dp) 310 { 311 Char *ep; 312 Char *p, *q; 313 314 if (!cp) 315 cp = STRNULL; 316 if (!dp) 317 dp = STRNULL; 318 for (p = cp; *p++;) 319 continue; 320 for (q = dp; *q++;) 321 continue; 322 ep = (Char *) xmalloc((size_t) 323 (((p - cp) + (q - dp) - 1) * sizeof(Char))); 324 for (p = ep, q = cp; (*p++ = *q++) != '\0';) 325 continue; 326 for (p--, q = dp; (*p++ = *q++) != '\0';) 327 continue; 328 return (ep); 329 } 330 331 Char * 332 s_strend(Char *cp) 333 { 334 if (!cp) 335 return (cp); 336 while (*cp) 337 cp++; 338 return (cp); 339 } 340 341 Char * 342 s_strstr(Char *s, Char *t) 343 { 344 do { 345 Char *ss = s; 346 Char *tt = t; 347 348 do 349 if (*tt == '\0') 350 return (s); 351 while (*ss++ == *tt++); 352 } while (*s++ != '\0'); 353 return (NULL); 354 } 355 #endif /* SHORT_STRINGS */ 356 357 char * 358 short2qstr(Char *src) 359 { 360 static char *sdst = NULL; 361 static size_t dstsize = 0; 362 char *dst, *edst; 363 364 if (src == NULL) 365 return (NULL); 366 367 if (sdst == NULL) { 368 dstsize = MALLOC_INCR; 369 sdst = (char *) xmalloc((size_t) dstsize * sizeof(char)); 370 } 371 dst = sdst; 372 edst = &dst[dstsize]; 373 while (*src) { 374 if (*src & QUOTE) { 375 *dst++ = '\\'; 376 if (dst == edst) { 377 dstsize += MALLOC_INCR; 378 sdst = (char *) xrealloc((ptr_t) sdst, 379 (size_t) dstsize * sizeof(char)); 380 edst = &sdst[dstsize]; 381 dst = &edst[-MALLOC_INCR]; 382 } 383 } 384 *dst++ = (char) *src++; 385 if (dst == edst) { 386 dstsize += MALLOC_INCR; 387 sdst = (char *) xrealloc((ptr_t) sdst, 388 (size_t) dstsize * sizeof(char)); 389 edst = &sdst[dstsize]; 390 dst = &edst[-MALLOC_INCR]; 391 } 392 } 393 *dst = 0; 394 return (sdst); 395 } 396 397 /* 398 * XXX: Should we worry about QUOTE'd chars? 399 */ 400 char * 401 vis_str(Char *cp) 402 { 403 static char *sdst = NULL; 404 static size_t dstsize = 0; 405 size_t n; 406 Char *dp; 407 408 if (cp == NULL) 409 return (NULL); 410 411 for (dp = cp; *dp++;) 412 continue; 413 n = ((dp - cp) << 2) + 1; /* 4 times + NUL */ 414 if (dstsize < n) { 415 sdst = (char *) (dstsize ? 416 xrealloc(sdst, (size_t) n * sizeof(char)) : 417 xmalloc((size_t) n * sizeof(char))); 418 dstsize = n; 419 } 420 /* 421 * XXX: When we are in AsciiOnly we want all characters >= 0200 to 422 * be encoded, but currently there is no way in vis to do that. 423 */ 424 (void) strnvis(sdst, short2str(cp), dstsize, VIS_NOSLASH); 425 return (sdst); 426 } 427 428