strnsubst.c revision 95898
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: head/usr.bin/xargs/strnsubst.c 95898 2002-05-02 02:06:03Z jmallett $");
13
14#include <err.h>
15#include <stdlib.h>
16#include <string.h>
17#include <unistd.h>
18
19void	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 * No value is returned.
28 */
29void
30strnsubst(char **str, const char *match, const char *replstr, size_t maxsize)
31{
32	char *s1, *s2;
33
34	s1 = *str;
35	if (s1 == NULL)
36		return;
37	s2 = calloc(maxsize, 1);
38	if (s2 == NULL)
39		err(1, "calloc");
40
41	if (match == NULL || replstr == NULL || maxsize == strlen(*str)) {
42		strlcpy(s2, s1, maxsize);
43		goto done;
44	}
45
46	for (;;) {
47		char *this;
48
49		this = strstr(s1, match);
50		if (this == NULL)
51			break;
52		if ((strlen(s2) + ((uintptr_t)this - (uintptr_t)s1) +
53		    (strlen(replstr) - 1)) > maxsize) {
54			strlcat(s2, s1, maxsize);
55			goto done;
56		}
57		strncat(s2, s1, (uintptr_t)this - (uintptr_t)s1);
58		strcat(s2, replstr);
59		s1 = this + strlen(match);
60	}
61	strcat(s2, s1);
62done:
63	*str = s2;
64	return;
65}
66
67#ifdef TEST
68#include <stdio.h>
69
70int
71main(void)
72{
73	char *x, *y;
74
75	y = x = "{}{}{}";
76	strnsubst(&x, "{}", "v ybir whyv! ", 12);
77	if (strcmp(x, "v ybir whyv! ") == 0)
78		printf("strnsubst() seems to work as expected.\n");
79	printf("x: %s\ny: %s\n", x, y);
80	free(x);
81	return 0;
82}
83#endif
84