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