1*84d9c625SLionel Sambuc /* $NetBSD: expand.c,v 1.6 2013/05/06 08:02:20 skrll Exp $ */
2e83f7ba2SBen Gras
3e83f7ba2SBen Gras /*-
4e83f7ba2SBen Gras * Copyright (c) 2007 The NetBSD Foundation, Inc.
5e83f7ba2SBen Gras * All rights reserved.
6e83f7ba2SBen Gras *
7e83f7ba2SBen Gras * This code is derived from software contributed to The NetBSD Foundation
8e83f7ba2SBen Gras * by Christos Zoulas.
9e83f7ba2SBen Gras *
10e83f7ba2SBen Gras * Redistribution and use in source and binary forms, with or without
11e83f7ba2SBen Gras * modification, are permitted provided that the following conditions
12e83f7ba2SBen Gras * are met:
13e83f7ba2SBen Gras * 1. Redistributions of source code must retain the above copyright
14e83f7ba2SBen Gras * notice, this list of conditions and the following disclaimer.
15e83f7ba2SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
16e83f7ba2SBen Gras * notice, this list of conditions and the following disclaimer in the
17e83f7ba2SBen Gras * documentation and/or other materials provided with the distribution.
18e83f7ba2SBen Gras *
19e83f7ba2SBen Gras * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20e83f7ba2SBen Gras * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21e83f7ba2SBen Gras * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22e83f7ba2SBen Gras * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23e83f7ba2SBen Gras * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24e83f7ba2SBen Gras * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25e83f7ba2SBen Gras * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26e83f7ba2SBen Gras * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27e83f7ba2SBen Gras * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28e83f7ba2SBen Gras * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29e83f7ba2SBen Gras * POSSIBILITY OF SUCH DAMAGE.
30e83f7ba2SBen Gras */
31e83f7ba2SBen Gras #include <sys/cdefs.h>
32e83f7ba2SBen Gras #ifndef lint
33*84d9c625SLionel Sambuc __RCSID("$NetBSD: expand.c,v 1.6 2013/05/06 08:02:20 skrll Exp $");
34e83f7ba2SBen Gras #endif /* not lint */
35e83f7ba2SBen Gras
36e83f7ba2SBen Gras #include <ctype.h>
37e83f7ba2SBen Gras #include <string.h>
38e83f7ba2SBen Gras #include <sys/sysctl.h>
39e83f7ba2SBen Gras
40e83f7ba2SBen Gras #ifdef DEBUG_EXPAND
41e83f7ba2SBen Gras #include <stdio.h>
42e83f7ba2SBen Gras #include <err.h>
43e83f7ba2SBen Gras #define xwarn warn
44e83f7ba2SBen Gras #define xerr err
45e83f7ba2SBen Gras size_t _rtld_expand_path(char *, size_t, const char *, const char *,
46e83f7ba2SBen Gras const char *);
47e83f7ba2SBen Gras #else
48e83f7ba2SBen Gras #include <sys/stat.h>
49e83f7ba2SBen Gras #include "rtld.h"
50e83f7ba2SBen Gras #endif
51e83f7ba2SBen Gras
52e83f7ba2SBen Gras static const struct {
53e83f7ba2SBen Gras const char *name;
54e83f7ba2SBen Gras size_t namelen;
55e83f7ba2SBen Gras } bltn[] = {
56e83f7ba2SBen Gras #define ADD(a) { #a, sizeof(#a) - 1 },
57e83f7ba2SBen Gras ADD(HWCAP) /* SSE, MMX, etc */
58e83f7ba2SBen Gras ADD(ISALIST) /* XXX */
59e83f7ba2SBen Gras ADD(ORIGIN) /* dirname argv[0] */
60e83f7ba2SBen Gras ADD(OSNAME) /* uname -s */
61e83f7ba2SBen Gras ADD(OSREL) /* uname -r */
62e83f7ba2SBen Gras ADD(PLATFORM) /* uname -p */
63e83f7ba2SBen Gras };
64e83f7ba2SBen Gras
65e83f7ba2SBen Gras static int mib[3][2] = {
66e83f7ba2SBen Gras { CTL_KERN, KERN_OSTYPE },
67e83f7ba2SBen Gras { CTL_KERN, KERN_OSRELEASE },
68e83f7ba2SBen Gras { CTL_HW, HW_MACHINE_ARCH },
69e83f7ba2SBen Gras };
70e83f7ba2SBen Gras
71e83f7ba2SBen Gras static size_t
expand(char * buf,const char * execname,int what,size_t bl)72e83f7ba2SBen Gras expand(char *buf, const char *execname, int what, size_t bl)
73e83f7ba2SBen Gras {
74e83f7ba2SBen Gras const char *p, *ep;
75e83f7ba2SBen Gras char *bp = buf;
76e83f7ba2SBen Gras size_t len;
77e83f7ba2SBen Gras char name[32];
78e83f7ba2SBen Gras
79e83f7ba2SBen Gras switch (what) {
80e83f7ba2SBen Gras case 0: /* HWCAP XXX: Not yet */
81e83f7ba2SBen Gras case 1: /* ISALIST XXX: Not yet */
82e83f7ba2SBen Gras return 0;
83e83f7ba2SBen Gras
84e83f7ba2SBen Gras case 2: /* ORIGIN */
85e83f7ba2SBen Gras if (execname == NULL)
86e83f7ba2SBen Gras xerr(1, "execname not specified in AUX vector");
87e83f7ba2SBen Gras if ((ep = strrchr(p = execname, '/')) == NULL)
88e83f7ba2SBen Gras xerr(1, "bad execname `%s' in AUX vector", execname);
89e83f7ba2SBen Gras break;
90e83f7ba2SBen Gras
91e83f7ba2SBen Gras case 3: /* OSNAME */
92e83f7ba2SBen Gras case 4: /* OSREL */
93e83f7ba2SBen Gras case 5: /* PLATFORM */
94e83f7ba2SBen Gras len = sizeof(name);
95e83f7ba2SBen Gras if (sysctl(mib[what - 3], 2, name, &len, NULL, 0) == -1) {
96e83f7ba2SBen Gras xwarn("sysctl");
97e83f7ba2SBen Gras return 0;
98e83f7ba2SBen Gras }
99e83f7ba2SBen Gras ep = (p = name) + len - 1;
100e83f7ba2SBen Gras break;
101e83f7ba2SBen Gras default:
102e83f7ba2SBen Gras return 0;
103e83f7ba2SBen Gras }
104e83f7ba2SBen Gras
105e83f7ba2SBen Gras while (p != ep && bl)
106e83f7ba2SBen Gras *bp++ = *p++, bl--;
107e83f7ba2SBen Gras
108e83f7ba2SBen Gras return bp - buf;
109e83f7ba2SBen Gras }
110e83f7ba2SBen Gras
111e83f7ba2SBen Gras
112e83f7ba2SBen Gras size_t
_rtld_expand_path(char * buf,size_t bufsize,const char * execname,const char * bp,const char * ep)113e83f7ba2SBen Gras _rtld_expand_path(char *buf, size_t bufsize, const char *execname,
114e83f7ba2SBen Gras const char *bp, const char *ep)
115e83f7ba2SBen Gras {
116e83f7ba2SBen Gras size_t i, ds = bufsize;
117e83f7ba2SBen Gras char *dp = buf;
118e83f7ba2SBen Gras const char *p;
119e83f7ba2SBen Gras int br;
120e83f7ba2SBen Gras
121e83f7ba2SBen Gras for (p = bp; p < ep;) {
122e83f7ba2SBen Gras if (*p == '$') {
123e83f7ba2SBen Gras br = *++p == '{';
124e83f7ba2SBen Gras
125e83f7ba2SBen Gras if (br)
126e83f7ba2SBen Gras p++;
127e83f7ba2SBen Gras
128e83f7ba2SBen Gras for (i = 0; i < sizeof(bltn) / sizeof(bltn[0]); i++) {
129e83f7ba2SBen Gras size_t s = bltn[i].namelen;
130e83f7ba2SBen Gras const char *es = p + s;
131e83f7ba2SBen Gras
132e83f7ba2SBen Gras if ((br && *es != '}') ||
133e83f7ba2SBen Gras (!br && (es != ep &&
134e83f7ba2SBen Gras isalpha((unsigned char)*es))))
135e83f7ba2SBen Gras continue;
136e83f7ba2SBen Gras
137e83f7ba2SBen Gras if (strncmp(bltn[i].name, p, s) == 0) {
138e83f7ba2SBen Gras size_t ls = expand(dp, execname, i, ds);
139e83f7ba2SBen Gras if (ls >= ds)
140e83f7ba2SBen Gras return bufsize;
141e83f7ba2SBen Gras ds -= ls;
142e83f7ba2SBen Gras dp += ls;
143e83f7ba2SBen Gras p = es + br;
144e83f7ba2SBen Gras goto done;
145e83f7ba2SBen Gras }
146e83f7ba2SBen Gras }
147e83f7ba2SBen Gras p -= br + 1;
148e83f7ba2SBen Gras
149e83f7ba2SBen Gras }
150e83f7ba2SBen Gras *dp++ = *p++;
151e83f7ba2SBen Gras ds--;
152e83f7ba2SBen Gras done:;
153e83f7ba2SBen Gras }
154e83f7ba2SBen Gras *dp = '\0';
155e83f7ba2SBen Gras return dp - buf;
156e83f7ba2SBen Gras }
157e83f7ba2SBen Gras
158e83f7ba2SBen Gras #ifdef DEBUG_EXPAND
159e83f7ba2SBen Gras int
main(int argc,char * argv[])160e83f7ba2SBen Gras main(int argc, char *argv[])
161e83f7ba2SBen Gras {
162e83f7ba2SBen Gras char buf[1024];
163e83f7ba2SBen Gras size_t i;
164e83f7ba2SBen Gras
165e83f7ba2SBen Gras for (i = 1; i < argc; i++) {
166e83f7ba2SBen Gras char *p = argv[i], *ep = argv[i] + strlen(p);
167e83f7ba2SBen Gras size_t n = _rtld_expand_path(buf, sizeof(buf), argv[0], p, ep);
168e83f7ba2SBen Gras printf("%s\n", buf);
169e83f7ba2SBen Gras }
170e83f7ba2SBen Gras return 0;
171e83f7ba2SBen Gras }
172e83f7ba2SBen Gras #endif
173