strnsubst.c revision 95900
195080Sjmallett/* $xMach: strnsubst.c,v 1.3 2002/02/23 02:10:24 jmallett Exp $ */
295080Sjmallett
395080Sjmallett/*
495080Sjmallett * Copyright (c) 2002 J. Mallett.  All rights reserved.
595080Sjmallett * You may do whatever you want with this file as long as
695080Sjmallett * the above copyright and this notice remain intact, along
795080Sjmallett * with the following statement:
895080Sjmallett * 	For the man who taught me vi, and who got too old, too young.
995080Sjmallett */
1095080Sjmallett
1195080Sjmallett#include <sys/cdefs.h>
1295080Sjmallett__FBSDID("$FreeBSD: head/usr.bin/xargs/strnsubst.c 95900 2002-05-02 02:15:06Z jmallett $");
1395080Sjmallett
1495080Sjmallett#include <err.h>
1595080Sjmallett#include <stdlib.h>
1695080Sjmallett#include <string.h>
1795080Sjmallett#include <unistd.h>
1895080Sjmallett
1995080Sjmallettvoid	strnsubst(char **, const char *, const char *, size_t);
2095080Sjmallett
2195080Sjmallett/*
2295080Sjmallett * Replaces str with a string consisting of str with match replaced with
2395080Sjmallett * replstr as many times as can be done before the constructed string is
2495080Sjmallett * maxsize bytes large.  It does not free the string pointed to by str, it
2595080Sjmallett * is up to the calling program to be sure that the original contents of
2695080Sjmallett * str as well as the new contents are handled in an appropriate manner.
2795080Sjmallett * No value is returned.
2895080Sjmallett */
2995080Sjmallettvoid
3095080Sjmallettstrnsubst(char **str, const char *match, const char *replstr, size_t maxsize)
3195080Sjmallett{
3295900Sjmallett	char *s1, *s2, *this;
3395080Sjmallett
3495080Sjmallett	s1 = *str;
3595080Sjmallett	if (s1 == NULL)
3695080Sjmallett		return;
3795080Sjmallett	s2 = calloc(maxsize, 1);
3895080Sjmallett	if (s2 == NULL)
3995080Sjmallett		err(1, "calloc");
4095080Sjmallett
4195900Sjmallett	if (match == NULL || replstr == NULL || maxsize == strlen(s1)) {
4295898Sjmallett		strlcpy(s2, s1, maxsize);
4395898Sjmallett		goto done;
4495898Sjmallett	}
4595898Sjmallett
4695080Sjmallett	for (;;) {
4795080Sjmallett		this = strstr(s1, match);
4895080Sjmallett		if (this == NULL)
4995080Sjmallett			break;
5095080Sjmallett		if ((strlen(s2) + ((uintptr_t)this - (uintptr_t)s1) +
5195080Sjmallett		    (strlen(replstr) - 1)) > maxsize) {
5295080Sjmallett			strlcat(s2, s1, maxsize);
5395080Sjmallett			goto done;
5495080Sjmallett		}
5595080Sjmallett		strncat(s2, s1, (uintptr_t)this - (uintptr_t)s1);
5695080Sjmallett		strcat(s2, replstr);
5795080Sjmallett		s1 = this + strlen(match);
5895080Sjmallett	}
5995080Sjmallett	strcat(s2, s1);
6095080Sjmallettdone:
6195080Sjmallett	*str = s2;
6295080Sjmallett	return;
6395080Sjmallett}
6495080Sjmallett
6595080Sjmallett#ifdef TEST
6695080Sjmallett#include <stdio.h>
6795080Sjmallett
6895080Sjmallettint
6995080Sjmallettmain(void)
7095080Sjmallett{
7195080Sjmallett	char *x, *y;
7295080Sjmallett
7395080Sjmallett	y = x = "{}{}{}";
7495080Sjmallett	strnsubst(&x, "{}", "v ybir whyv! ", 12);
7595080Sjmallett	if (strcmp(x, "v ybir whyv! ") == 0)
7695080Sjmallett		printf("strnsubst() seems to work as expected.\n");
7795080Sjmallett	printf("x: %s\ny: %s\n", x, y);
7895080Sjmallett	free(x);
7995080Sjmallett	return 0;
8095080Sjmallett}
8195080Sjmallett#endif
82