1 /* $xMach: strnsubst.c,v 1.3 2002/02/23 02:10:24 jmallett Exp $ */ 2 3 /* 4 * Copyright (c) 2002 J. Mallett. All rights reserved. 5 * You may do whatever you want with this file as long as 6 * the above copyright and this notice remain intact, along 7 * with the following statement: 8 * For the man who taught me vi, and who got too old, too young. 9 */ 10 11 #include <sys/cdefs.h> 12 __FBSDID("$FreeBSD$"); 13 14 #include <err.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <unistd.h> 18 19 void strnsubst(char **, const char *, const char *, size_t); 20 21 /* 22 * Replaces str with a string consisting of str with match replaced with 23 * replstr as many times as can be done before the constructed string is 24 * maxsize bytes large. It does not free the string pointed to by str, it 25 * is up to the calling program to be sure that the original contents of 26 * str as well as the new contents are handled in an appropriate manner. 27 * If replstr is NULL, then that internally is changed to a nil-string, so 28 * that we can still pretend to do somewhat meaningful substitution. 29 * No value is returned. 30 */ 31 void 32 strnsubst(char **str, const char *match, const char *replstr, size_t maxsize) 33 { 34 char *s1, *s2, *this; 35 36 s1 = *str; 37 if (s1 == NULL) 38 return; 39 s2 = calloc(maxsize, 1); 40 if (s2 == NULL) 41 err(1, "calloc"); 42 43 if (replstr == NULL) 44 replstr = ""; 45 46 if (match == NULL || replstr == NULL || maxsize == strlen(s1)) { 47 strlcpy(s2, s1, maxsize); 48 goto done; 49 } 50 51 for (;;) { 52 this = strstr(s1, match); 53 if (this == NULL) 54 break; 55 if ((strlen(s2) + ((uintptr_t)this - (uintptr_t)s1) + 56 (strlen(replstr) - 1)) > maxsize && *replstr != '\0') { 57 strlcat(s2, s1, maxsize); 58 goto done; 59 } 60 strncat(s2, s1, (uintptr_t)this - (uintptr_t)s1); 61 strcat(s2, replstr); 62 s1 = this + strlen(match); 63 } 64 strcat(s2, s1); 65 done: 66 *str = s2; 67 return; 68 } 69 70 #ifdef TEST 71 #include <stdio.h> 72 73 int 74 main(void) 75 { 76 char *x, *y; 77 78 y = x = "{}{}{}"; 79 strnsubst(&x, "{}", "v ybir whyv! ", 12); 80 if (strcmp(x, "v ybir whyv! ") == 0) 81 printf("strnsubst() seems to work as expected.\n"); 82 printf("x: %s\ny: %s\n", x, y); 83 free(x); 84 return 0; 85 } 86 #endif 87