1*6f661f3bSchristos /* $NetBSD: expand.c,v 1.7 2023/01/04 01:37:00 christos Exp $ */
204ee85adSchristos
304ee85adSchristos /*-
404ee85adSchristos * Copyright (c) 2007 The NetBSD Foundation, Inc.
504ee85adSchristos * All rights reserved.
604ee85adSchristos *
704ee85adSchristos * This code is derived from software contributed to The NetBSD Foundation
804ee85adSchristos * by Christos Zoulas.
904ee85adSchristos *
1004ee85adSchristos * Redistribution and use in source and binary forms, with or without
1104ee85adSchristos * modification, are permitted provided that the following conditions
1204ee85adSchristos * are met:
1304ee85adSchristos * 1. Redistributions of source code must retain the above copyright
1404ee85adSchristos * notice, this list of conditions and the following disclaimer.
1504ee85adSchristos * 2. Redistributions in binary form must reproduce the above copyright
1604ee85adSchristos * notice, this list of conditions and the following disclaimer in the
1704ee85adSchristos * documentation and/or other materials provided with the distribution.
1804ee85adSchristos *
1904ee85adSchristos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2004ee85adSchristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2104ee85adSchristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2204ee85adSchristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2304ee85adSchristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2404ee85adSchristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2504ee85adSchristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2604ee85adSchristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2704ee85adSchristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2804ee85adSchristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2904ee85adSchristos * POSSIBILITY OF SUCH DAMAGE.
3004ee85adSchristos */
3104ee85adSchristos #include <sys/cdefs.h>
3204ee85adSchristos #ifndef lint
33*6f661f3bSchristos __RCSID("$NetBSD: expand.c,v 1.7 2023/01/04 01:37:00 christos Exp $");
3404ee85adSchristos #endif /* not lint */
3504ee85adSchristos
3604ee85adSchristos #include <ctype.h>
3704ee85adSchristos #include <string.h>
3804ee85adSchristos #include <sys/sysctl.h>
3904ee85adSchristos
4004ee85adSchristos #ifdef DEBUG_EXPAND
4104ee85adSchristos #include <stdio.h>
4204ee85adSchristos #include <err.h>
4304ee85adSchristos #define xwarn warn
446eac1155Schristos #define xerr err
4504ee85adSchristos size_t _rtld_expand_path(char *, size_t, const char *, const char *,
4604ee85adSchristos const char *);
4704ee85adSchristos #else
4804ee85adSchristos #include <sys/stat.h>
4904ee85adSchristos #include "rtld.h"
5004ee85adSchristos #endif
5104ee85adSchristos
5204ee85adSchristos static const struct {
5304ee85adSchristos const char *name;
5404ee85adSchristos size_t namelen;
5504ee85adSchristos } bltn[] = {
5604ee85adSchristos #define ADD(a) { #a, sizeof(#a) - 1 },
5704ee85adSchristos ADD(HWCAP) /* SSE, MMX, etc */
583b320420Schristos ADD(ISALIST) /* XXX */
5904ee85adSchristos ADD(ORIGIN) /* dirname argv[0] */
6004ee85adSchristos ADD(OSNAME) /* uname -s */
6104ee85adSchristos ADD(OSREL) /* uname -r */
623b320420Schristos ADD(PLATFORM) /* uname -p */
6304ee85adSchristos };
6404ee85adSchristos
6504ee85adSchristos static int mib[3][2] = {
6604ee85adSchristos { CTL_KERN, KERN_OSTYPE },
6704ee85adSchristos { CTL_KERN, KERN_OSRELEASE },
6804ee85adSchristos { CTL_HW, HW_MACHINE_ARCH },
6904ee85adSchristos };
7004ee85adSchristos
7104ee85adSchristos static size_t
expand(char * buf,const char * execname,size_t what,size_t bl)72*6f661f3bSchristos expand(char *buf, const char *execname, size_t what, size_t bl)
7304ee85adSchristos {
7404ee85adSchristos const char *p, *ep;
7504ee85adSchristos char *bp = buf;
7604ee85adSchristos size_t len;
7704ee85adSchristos char name[32];
7804ee85adSchristos
7904ee85adSchristos switch (what) {
8004ee85adSchristos case 0: /* HWCAP XXX: Not yet */
8104ee85adSchristos case 1: /* ISALIST XXX: Not yet */
8204ee85adSchristos return 0;
8304ee85adSchristos
8404ee85adSchristos case 2: /* ORIGIN */
8540cfdb5eSchristos if (execname == NULL)
8640cfdb5eSchristos xerr(1, "execname not specified in AUX vector");
8740cfdb5eSchristos if ((ep = strrchr(p = execname, '/')) == NULL)
8840cfdb5eSchristos xerr(1, "bad execname `%s' in AUX vector", execname);
8904ee85adSchristos break;
9004ee85adSchristos
9104ee85adSchristos case 3: /* OSNAME */
9204ee85adSchristos case 4: /* OSREL */
9304ee85adSchristos case 5: /* PLATFORM */
9404ee85adSchristos len = sizeof(name);
9504ee85adSchristos if (sysctl(mib[what - 3], 2, name, &len, NULL, 0) == -1) {
9604ee85adSchristos xwarn("sysctl");
9704ee85adSchristos return 0;
9804ee85adSchristos }
9904ee85adSchristos ep = (p = name) + len - 1;
10004ee85adSchristos break;
10104ee85adSchristos default:
10204ee85adSchristos return 0;
10304ee85adSchristos }
10404ee85adSchristos
10504ee85adSchristos while (p != ep && bl)
10604ee85adSchristos *bp++ = *p++, bl--;
10704ee85adSchristos
10804ee85adSchristos return bp - buf;
10904ee85adSchristos }
11004ee85adSchristos
11104ee85adSchristos
11204ee85adSchristos size_t
_rtld_expand_path(char * buf,size_t bufsize,const char * execname,const char * bp,const char * ep)11340cfdb5eSchristos _rtld_expand_path(char *buf, size_t bufsize, const char *execname,
11440cfdb5eSchristos const char *bp, const char *ep)
11504ee85adSchristos {
11604ee85adSchristos size_t i, ds = bufsize;
11704ee85adSchristos char *dp = buf;
11804ee85adSchristos const char *p;
11904ee85adSchristos int br;
12004ee85adSchristos
12104ee85adSchristos for (p = bp; p < ep;) {
12204ee85adSchristos if (*p == '$') {
12304ee85adSchristos br = *++p == '{';
12404ee85adSchristos
12504ee85adSchristos if (br)
12604ee85adSchristos p++;
12704ee85adSchristos
12804ee85adSchristos for (i = 0; i < sizeof(bltn) / sizeof(bltn[0]); i++) {
12904ee85adSchristos size_t s = bltn[i].namelen;
13004ee85adSchristos const char *es = p + s;
13104ee85adSchristos
13204ee85adSchristos if ((br && *es != '}') ||
13304ee85adSchristos (!br && (es != ep &&
13404ee85adSchristos isalpha((unsigned char)*es))))
13504ee85adSchristos continue;
13604ee85adSchristos
13704ee85adSchristos if (strncmp(bltn[i].name, p, s) == 0) {
13840cfdb5eSchristos size_t ls = expand(dp, execname, i, ds);
13904ee85adSchristos if (ls >= ds)
14004ee85adSchristos return bufsize;
14104ee85adSchristos ds -= ls;
14204ee85adSchristos dp += ls;
14304ee85adSchristos p = es + br;
14404ee85adSchristos goto done;
14504ee85adSchristos }
14604ee85adSchristos }
14704ee85adSchristos p -= br + 1;
14804ee85adSchristos
14904ee85adSchristos }
15004ee85adSchristos *dp++ = *p++;
15104ee85adSchristos ds--;
15204ee85adSchristos done:;
15304ee85adSchristos }
15404ee85adSchristos *dp = '\0';
15504ee85adSchristos return dp - buf;
15604ee85adSchristos }
15704ee85adSchristos
15804ee85adSchristos #ifdef DEBUG_EXPAND
15904ee85adSchristos int
main(int argc,char * argv[])16004ee85adSchristos main(int argc, char *argv[])
16104ee85adSchristos {
16204ee85adSchristos char buf[1024];
16304ee85adSchristos size_t i;
16404ee85adSchristos
16504ee85adSchristos for (i = 1; i < argc; i++) {
16604ee85adSchristos char *p = argv[i], *ep = argv[i] + strlen(p);
16704ee85adSchristos size_t n = _rtld_expand_path(buf, sizeof(buf), argv[0], p, ep);
16804ee85adSchristos printf("%s\n", buf);
16904ee85adSchristos }
17004ee85adSchristos return 0;
17104ee85adSchristos }
17204ee85adSchristos #endif
173