1*de284403Schristos /* $NetBSD: expandm.c,v 1.1 2019/01/11 20:37:30 christos Exp $ */ 2*de284403Schristos 3*de284403Schristos /*- 4*de284403Schristos * Copyright (c) 2018 The NetBSD Foundation, Inc. 5*de284403Schristos * All rights reserved. 6*de284403Schristos * 7*de284403Schristos * This code is derived from software contributed to The NetBSD Foundation 8*de284403Schristos * by Christos Zoulas. 9*de284403Schristos * 10*de284403Schristos * Redistribution and use in source and binary forms, with or without 11*de284403Schristos * modification, are permitted provided that the following conditions 12*de284403Schristos * are met: 13*de284403Schristos * 1. Redistributions of source code must retain the above copyright 14*de284403Schristos * notice, this list of conditions and the following disclaimer. 15*de284403Schristos * 2. Redistributions in binary form must reproduce the above copyright 16*de284403Schristos * notice, this list of conditions and the following disclaimer in the 17*de284403Schristos * documentation and/or other materials provided with the distribution. 18*de284403Schristos * 19*de284403Schristos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20*de284403Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21*de284403Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22*de284403Schristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23*de284403Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24*de284403Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25*de284403Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26*de284403Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27*de284403Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28*de284403Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29*de284403Schristos * POSSIBILITY OF SUCH DAMAGE. 30*de284403Schristos */ 31*de284403Schristos #include <sys/cdefs.h> 32*de284403Schristos __RCSID("$NetBSD: expandm.c,v 1.1 2019/01/11 20:37:30 christos Exp $"); 33*de284403Schristos 34*de284403Schristos #include <stdio.h> 35*de284403Schristos #include <string.h> 36*de284403Schristos #include <stdlib.h> 37*de284403Schristos #include <errno.h> 38*de284403Schristos 39*de284403Schristos #include "expandm.h" 40*de284403Schristos 41*de284403Schristos char * __attribute__((__format_arg__(1))) 42*de284403Schristos expandm(const char *fmt, const char *sf) 43*de284403Schristos { 44*de284403Schristos const char *e = strerror(errno); 45*de284403Schristos char *buf, *m, *nbuf; 46*de284403Schristos const char *ptr; 47*de284403Schristos 48*de284403Schristos for (ptr = fmt, buf = NULL; (m = strstr(ptr, "%m")); ptr = m + 2) { 49*de284403Schristos size_t cnt = 0; 50*de284403Schristos for (char *p = m; p >= ptr && *p == '%'; p--) 51*de284403Schristos cnt++; 52*de284403Schristos if (asprintf(&nbuf, "%s%.*s%s", buf ? buf : "", 53*de284403Schristos (int)(m - ptr), ptr, (cnt & 1) ? e : "%%m") == -1) 54*de284403Schristos goto out; 55*de284403Schristos free(buf); 56*de284403Schristos buf = nbuf; 57*de284403Schristos } 58*de284403Schristos 59*de284403Schristos if (asprintf(&nbuf, "%s%s%s", buf ? buf : "", ptr, sf ? sf : "") == -1) 60*de284403Schristos goto out; 61*de284403Schristos 62*de284403Schristos free(buf); 63*de284403Schristos return nbuf; 64*de284403Schristos out: 65*de284403Schristos free(buf); 66*de284403Schristos return __UNCONST(fmt); 67*de284403Schristos } 68*de284403Schristos 69*de284403Schristos #ifdef TEST 70*de284403Schristos int 71*de284403Schristos main(int argc, char *argv[]) 72*de284403Schristos { 73*de284403Schristos errno = ERANGE; 74*de284403Schristos printf("%s\n", expandm(argv[1])); 75*de284403Schristos return 0; 76*de284403Schristos } 77*de284403Schristos #endif 78