xref: /minix3/libexec/ld.elf_so/expand.c (revision d2532d3d42d764c9ef9816851cdb17eda7e08d36)
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