xref: /dflybsd-src/usr.bin/objformat/objformat.c (revision 984168ecb35d019fe548687d99cac4e6d148a299)
1 /*-
2  * Copyright (c) 1998, Peter Wemm <peter@netplex.com.au>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/usr.bin/objformat/objformat.c,v 1.6 1998/10/24 02:01:30 jdp Exp $
27  * $DragonFly: src/usr.bin/objformat/objformat.c,v 1.10 2004/01/31 09:14:24 dillon Exp $
28  */
29 
30 #include <err.h>
31 #include <objformat.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 
37 /*
38  * System default compiler is still gcc2 for the IA32 architecture,
39  * unless overriden.  For other architectures we have to use gcc3.
40  */
41 #ifndef CCVER_DEFAULT
42 #ifdef __i386__
43 #define CCVER_DEFAULT "gcc2"
44 #else
45 #define CCVER_DEFAULT "gcc3"
46 #endif
47 #endif
48 #ifndef BINUTILSVER_DEFAULT
49 #define BINUTILSVER_DEFAULT "binutils212"
50 #endif
51 
52 #define OBJFORMAT	0
53 #define COMPILER	1
54 #define BINUTILS1	2
55 #define BINUTILS2	3
56 
57 #define arysize(ary)	(sizeof(ary)/sizeof((ary)[0]))
58 
59 struct command {
60 	const char *cmd;
61 	int type;
62 };
63 
64 static struct command commands[] = {
65 	{"CC",		COMPILER},
66 	{"c++",		COMPILER},
67 	{"c++filt",	COMPILER},
68 	{"cc",		COMPILER},
69 	{"cpp",		COMPILER},
70 	{"f77",		COMPILER},
71 	{"g++",		COMPILER},
72 	{"gcc",		COMPILER},
73 	{"gcov",	COMPILER},
74 	{"addr2line",	BINUTILS2},
75 	{"ar",		BINUTILS2},
76 	{"as",		BINUTILS2},
77 	{"gasp",	BINUTILS2},
78 	{"gdb",		BINUTILS2},
79 	{"ld",		BINUTILS2},
80 	{"nm",		BINUTILS2},
81 	{"objcopy",	BINUTILS2},
82 	{"objdump",	BINUTILS2},
83 	{"ranlib",	BINUTILS2},
84 	{"size",	BINUTILS2},
85 	{"strings",	BINUTILS2},
86 	{"strip",	BINUTILS2},
87 	{"objformat",	OBJFORMAT}
88 };
89 
90 int
91 main(int argc, char **argv)
92 {
93 	struct command *cmds;
94 	char objformat[32];
95 	char *path, *chunk;
96 	char *cmd, *newcmd = NULL;
97 	char *objformat_path;
98 	char *ccver;
99 	char *buver;
100 	const char *env_value = NULL;
101 	const char *base_path = NULL;
102 	int use_objformat = 0;
103 
104 	if (getobjformat(objformat, sizeof objformat, &argc, argv) == -1)
105 		errx(1, "Invalid object format");
106 
107 	/*
108 	 * Get the last path elemenet of the program name being executed
109 	 */
110 	cmd = strrchr(argv[0], '/');
111 	if (cmd != NULL)
112 		cmd++;
113 	else
114 		cmd = argv[0];
115 
116 	for (cmds = commands; cmds < &commands[arysize(commands)]; ++cmds) {
117 		if (strcmp(cmd, cmds->cmd) == 0)
118 			break;
119 	}
120 
121 	if ((ccver = getenv("CCVER")) == NULL)
122 		ccver = CCVER_DEFAULT;
123 	if ((buver = getenv("BINUTILSVER")) == NULL) {
124 		buver = BINUTILSVER_DEFAULT;
125 		/*
126 		 * XXX auto-select buver based on ccver if buver is
127 		 * not otherwise specified
128 		 */
129 	}
130 
131 	if (cmds) {
132 		switch (cmds->type) {
133 		case COMPILER:
134 			base_path = "/usr/bin";
135 			use_objformat = 0;
136 			env_value = ccver;
137 			break;
138 		case BINUTILS2:
139 			use_objformat = 1;
140 			/* fall through */
141 		case BINUTILS1:
142 			env_value = buver;
143 			base_path = "/usr/libexec";
144 			break;
145 		case OBJFORMAT:
146 			break;
147 		default:
148 			err(1, "unknown command type");
149 			break;
150 		}
151 	}
152 
153 	/*
154 	 * The objformat command itself doesn't need another exec
155 	 */
156 	if (cmds->type == OBJFORMAT) {
157 		if (argc != 1) {
158 			fprintf(stderr, "Usage: objformat\n");
159 			exit(1);
160 		}
161 
162 		printf("%s\n", objformat);
163 		exit(0);
164 	}
165 
166 	/*
167 	 * make buildworld glue and CCVER overrides.
168 	 */
169 	objformat_path = getenv("OBJFORMAT_PATH");
170 	if (objformat_path == NULL)
171 		objformat_path = "";
172 
173 	path = strdup(objformat_path);
174 
175 	setenv("OBJFORMAT", objformat, 1);
176 
177 	/*
178 	 * objformat_path could be sequence of colon-separated paths.
179 	 */
180 	while ((chunk = strsep(&path, ":")) != NULL) {
181 		if (newcmd != NULL) {
182 			free(newcmd);
183 			newcmd = NULL;
184 		}
185 		if (use_objformat) {
186 			asprintf(&newcmd, "%s%s/%s/%s/%s",
187 				chunk, base_path, env_value, objformat, cmd);
188 		} else {
189 			asprintf(&newcmd, "%s%s/%s/%s",
190 				chunk, base_path, env_value, cmd);
191 		}
192 		if (newcmd == NULL)
193 			err(1, "cannot allocate memory");
194 
195 		argv[0] = newcmd;
196 		execv(newcmd, argv);
197 	}
198 	if (use_objformat) {
199 		err(1, "in path [%s]%s/%s/%s/%s",
200 			objformat_path, base_path, env_value, objformat, cmd);
201 	} else {
202 		err(1, "in path [%s]%s/%s/%s",
203 			objformat_path, base_path, env_value, cmd);
204 	}
205 }
206 
207