1 1.1 christos /* $xMach: strnsubst.c,v 1.3 2002/02/23 02:10:24 jmallett Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (c) 2002 J. Mallett. All rights reserved. 5 1.1 christos * You may do whatever you want with this file as long as 6 1.1 christos * the above copyright and this notice remain intact, along 7 1.1 christos * with the following statement: 8 1.1 christos * For the man who taught me vi, and who got too old, too young. 9 1.1 christos */ 10 1.1 christos 11 1.1 christos #include <sys/cdefs.h> 12 1.1 christos #ifndef lint 13 1.1 christos #if 0 14 1.1 christos __FBSDID("$FreeBSD: src/usr.bin/xargs/strnsubst.c,v 1.8 2005/12/30 23:22:50 jmallett Exp $"); 15 1.1 christos #endif 16 1.1 christos __RCSID("$NetBSD: strnsubst.c,v 1.1 2007/04/18 15:56:07 christos Exp $"); 17 1.1 christos #endif /* not lint */ 18 1.1 christos 19 1.1 christos #include <err.h> 20 1.1 christos #include <stdlib.h> 21 1.1 christos #include <string.h> 22 1.1 christos #include <unistd.h> 23 1.1 christos #include <stdint.h> 24 1.1 christos 25 1.1 christos void strnsubst(char **, const char *, const char *, size_t); 26 1.1 christos 27 1.1 christos /* 28 1.1 christos * Replaces str with a string consisting of str with match replaced with 29 1.1 christos * replstr as many times as can be done before the constructed string is 30 1.1 christos * maxsize bytes large. It does not free the string pointed to by str, it 31 1.1 christos * is up to the calling program to be sure that the original contents of 32 1.1 christos * str as well as the new contents are handled in an appropriate manner. 33 1.1 christos * If replstr is NULL, then that internally is changed to a nil-string, so 34 1.1 christos * that we can still pretend to do somewhat meaningful substitution. 35 1.1 christos * No value is returned. 36 1.1 christos */ 37 1.1 christos void 38 1.1 christos strnsubst(char **str, const char *match, const char *replstr, size_t maxsize) 39 1.1 christos { 40 1.1 christos char *s1, *s2, *this; 41 1.1 christos 42 1.1 christos s1 = *str; 43 1.1 christos if (s1 == NULL) 44 1.1 christos return; 45 1.1 christos /* 46 1.1 christos * If maxsize is 0 then set it to to the length of s1, because we have 47 1.1 christos * to duplicate s1. XXX we maybe should double-check whether the match 48 1.1 christos * appears in s1. If it doesn't, then we also have to set the length 49 1.1 christos * to the length of s1, to avoid modifying the argument. It may make 50 1.1 christos * sense to check if maxsize is <= strlen(s1), because in that case we 51 1.1 christos * want to return the unmodified string, too. 52 1.1 christos */ 53 1.1 christos if (maxsize == 0) { 54 1.1 christos match = NULL; 55 1.1 christos maxsize = strlen(s1) + 1; 56 1.1 christos } 57 1.1 christos s2 = calloc(maxsize, 1); 58 1.1 christos if (s2 == NULL) 59 1.1 christos err(1, "calloc"); 60 1.1 christos 61 1.1 christos if (replstr == NULL) 62 1.1 christos replstr = ""; 63 1.1 christos 64 1.1 christos if (match == NULL || replstr == NULL || maxsize == strlen(s1)) { 65 1.1 christos (void)strlcpy(s2, s1, maxsize); 66 1.1 christos goto done; 67 1.1 christos } 68 1.1 christos 69 1.1 christos for (;;) { 70 1.1 christos this = strstr(s1, match); 71 1.1 christos if (this == NULL) 72 1.1 christos break; 73 1.1 christos if ((strlen(s2) + strlen(s1) + strlen(replstr) - 74 1.1 christos strlen(match) + 1) > maxsize) { 75 1.1 christos (void)strlcat(s2, s1, maxsize); 76 1.1 christos goto done; 77 1.1 christos } 78 1.1 christos (void)strncat(s2, s1, (uintptr_t)this - (uintptr_t)s1); 79 1.1 christos (void)strcat(s2, replstr); 80 1.1 christos s1 = this + strlen(match); 81 1.1 christos } 82 1.1 christos (void)strcat(s2, s1); 83 1.1 christos done: 84 1.1 christos *str = s2; 85 1.1 christos return; 86 1.1 christos } 87 1.1 christos 88 1.1 christos #ifdef TEST 89 1.1 christos #include <stdio.h> 90 1.1 christos 91 1.1 christos int 92 1.1 christos main(void) 93 1.1 christos { 94 1.1 christos char *x, *y, *z, *za; 95 1.1 christos 96 1.1 christos x = "{}%$"; 97 1.1 christos strnsubst(&x, "%$", "{} enpury!", 255); 98 1.1 christos y = x; 99 1.1 christos strnsubst(&y, "}{}", "ybir", 255); 100 1.1 christos z = y; 101 1.1 christos strnsubst(&z, "{", "v ", 255); 102 1.1 christos za = z; 103 1.1 christos strnsubst(&z, NULL, za, 255); 104 1.1 christos if (strcmp(z, "v ybir enpury!") == 0) 105 1.1 christos (void)printf("strnsubst() seems to work!\n"); 106 1.1 christos else 107 1.1 christos (void)printf("strnsubst() is broken.\n"); 108 1.1 christos (void)printf("%s\n", z); 109 1.1 christos free(x); 110 1.1 christos free(y); 111 1.1 christos free(z); 112 1.1 christos free(za); 113 1.1 christos return 0; 114 1.1 christos } 115 1.1 christos #endif 116