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