| /* --COPYRIGHT--,EPL |
| * Copyright (c) 2008-2015 Texas Instruments Incorporated |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Texas Instruments - initial implementation |
| * |
| * --/COPYRIGHT--*/ |
| /* |
| * ======== xe.c ======== |
| * XDC host command tool |
| * |
| * This command runs command found along the package path. |
| * |
| * usage: xe [-n] cmd [arg ...] |
| * |
| * Options: |
| * -h - display this message |
| * -n - don't do build just echo build commands |
| */ |
| #include <xdc/std.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "host.h" |
| |
| #include <xdc/services/host/lib/xutl.h> |
| #include <sys/stat.h> |
| |
| #ifndef TISB_TREENAME |
| #define TISB_TREENAME "xdc-o17" |
| #endif |
| |
| #define PNAME "/packages/xdc/bin" |
| #define PNAMELEN (sizeof(PNAME) - 1) |
| |
| #define MAXNAME 512 |
| #define MAXARG (2 * MAXNAME) |
| #define MAXARGS 128 |
| #define MAXNEW 16 |
| |
| #if defined(xdc_target__os_Linux) |
| #include <unistd.h> |
| #define HOSTOS "HOSTOS=Linux" |
| #endif |
| |
| #if defined(xdc_target__os_Windows) |
| |
| #define HOSTOS "HOSTOS=Windows" |
| #define DIRSTR "\\" |
| #define PATHSTR ";" |
| #define MAKE "bin" DIRSTR "gmake.exe" |
| |
| #include <windows.h> /* GetModuleFileName */ |
| #include <io.h> |
| |
| #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) |
| |
| #else /* Unix */ |
| |
| #define DIRSTR "/" |
| #define PATHSTR ":" |
| #define MAKE "bin" DIRSTR "gmake" |
| #endif |
| |
| #define PACKPREFIX "PACKAGES=" |
| #define PACKSUFFIX "" |
| |
| #define XDCTOPMAKE (DIRSTR "packages" DIRSTR "xdc" DIRSTR "bld" DIRSTR "xdc_top.mak") |
| #define XDCMAKE (DIRSTR "packages" DIRSTR "xdc" DIRSTR "bld" DIRSTR "xdc.mak") |
| |
| static Bool nflag = FALSE; |
| static Int verbose = 0; |
| |
| static String xdcRoot; /* root path; i.e., $(XDCROOT) */ |
| static Char rootDef[MAXARG]; /* XDCROOT=$(XDCROOT) */ |
| |
| static String xdcPathDef = NULL;/* XDCPATH= definition on command line */ |
| static String packagePath; /* full expanded package path */ |
| |
| static String makeArgv[MAXARGS]; |
| static Int makeArgc = 0; |
| |
| static String progName; |
| static String usage = \ |
| "usage: %s [-h] [-n] cmd [arg ...]\n" \ |
| " -h - display this message and exit\n" \ |
| " -n - show the make command but don't execute it\n"; |
| |
| static String optsUsage = \ |
| " XDC_VERBOSE a number indicating 'degree' of verbosity; 0 => quiet\n"; |
| |
| static Void d2u(String buf); |
| static String findFile(String file, String path); |
| static char **genEnvp(String root, char *envp[]); |
| static String getPackagePath(String xdcPath); |
| static Bool isFile(String name); |
| static Void printSetEnv(String env); |
| static Void printVers(String progName); |
| |
| /* |
| * ======== main ======== |
| */ |
| int main(int argc, char *argv[], char *envp[]) |
| { |
| Int status = 0; |
| Int i; |
| Int len; |
| String tmp, err; |
| |
| progName = argv[0]; |
| |
| XUTL_init(); |
| argv = XUTL_expandArgv(argc, argv, &argc, &err); |
| if (argv == NULL) { |
| fprintf(stderr, "%s: unable to expand command line arguments: %s\n", |
| progName, err); |
| exit(1); |
| } |
| |
| if ((tmp = getenv("XDC_VERBOSE")) != NULL) { |
| verbose = atoi(tmp); |
| } |
| |
| /* compute xdc root based on where this executable is installed */ |
| xdcRoot = XUTL_getProgPath(progName); |
| d2u(xdcRoot); |
| len = strlen(xdcRoot); |
| tmp = xdcRoot + (len - PNAMELEN); |
| if (strcmp(tmp, PNAME) == 0) { |
| *tmp = '\0'; |
| } |
| |
| /* parse options */ |
| for (i = 1; i < argc; i++) { |
| if (makeArgc >= MAXARGS) { |
| fprintf(stderr, "%s: out of memory.\n", progName); |
| exit(1); |
| } |
| if (argv[i][0] == '-') { |
| switch (argv[i][1]) { |
| case 'n': { |
| nflag = TRUE; |
| break; |
| } |
| |
| case 'h': { |
| fprintf(stderr, usage, progName); |
| fprintf(stderr, "\nEnvironment Variables\n"); |
| fprintf(stderr, optsUsage); |
| exit(0); |
| break; |
| } |
| |
| case '-': { |
| if (strncmp("ver", argv[i] + 2, 3) == 0) { |
| printVers(progName); |
| printf("\n"); |
| if (makeArgc == 0) { |
| if (i >= (argc - 1)) { |
| exit(0); |
| } |
| /* eat this opt if cmd isn't specified yet */ |
| break; |
| } |
| } |
| /* FALL THROUGH */ |
| } |
| default: { |
| makeArgv[makeArgc++] = argv[i]; |
| break; |
| } |
| } |
| } |
| else { |
| if (strncmp("XDCPATH=", argv[i], 8) == 0) { |
| xdcPathDef = argv[i]; |
| } |
| makeArgv[makeArgc++] = argv[i]; |
| } |
| } |
| |
| if (makeArgv[0] == NULL) { |
| fprintf(stderr, usage, progName); |
| exit(1); |
| } |
| |
| /* compute expanded package path */ |
| packagePath = getPackagePath(xdcPathDef); |
| |
| /* if we can't find make in XDCROOT/bin, try alternatives */ |
| if (access(makeArgv[0], 00) != 0) { |
| String cmd = findFile(makeArgv[0], packagePath); |
| if (cmd == NULL) { |
| fprintf(stderr, "%s: can't find '%s' along the path %s\n", |
| progName, makeArgv[0], packagePath); |
| exit(1); |
| } |
| } |
| |
| /* set PATH in environment before executing or displaying command */ |
| envp = genEnvp(xdcRoot, envp); |
| |
| /* if verbose flag is set, display the commands to be executed */ |
| if (nflag == TRUE || verbose >= 1) { |
| if (verbose >= 2) { |
| for (i = 0; envp[i] != NULL; i++) { |
| printf("%s\n", envp[i]); |
| } |
| printf("\n"); |
| } |
| |
| /* display the make command */ |
| for (i = 0; i < makeArgc; i++) { |
| if (i > 0 && strpbrk(makeArgv[i], " \t") != NULL) { |
| printf("\"%s\" ", makeArgv[i]); |
| } |
| else { |
| printf("%s ", makeArgv[i]); |
| } |
| } |
| printf("\n"); |
| } |
| |
| if (nflag == FALSE) { |
| /* execute make command */ |
| if ((status = XUTL_run(makeArgv[0], makeArgv, envp))) { |
| fprintf(stderr, "%s: can't execute '%s' ", progName, makeArgv[0]); |
| perror("because"); |
| } |
| } |
| |
| /* if the exec failed, return its error status */ |
| return (status); |
| } |
| |
| /* |
| * ======== d2u ======== |
| * Convert DOS path string into unix path string |
| */ |
| static Void d2u(String buf) |
| { |
| Char *cp; |
| |
| for (cp = buf; *cp != '\0'; cp++) { |
| if (*cp == '\\') { |
| *cp = '/'; |
| } |
| } |
| } |
| |
| /* |
| * ======== findFile ======== |
| */ |
| static String findFile(String file, String path) |
| { |
| static Char nameBuf[MAXNAME + 1]; |
| String pathBuf = NULL; |
| String tmp; |
| Int len; |
| |
| /* if the nameBuf is too small we fail */ |
| if (file == NULL || (len = strlen(file)) > MAXNAME) { |
| return (NULL); |
| } |
| |
| /* if file is a full path name, test it unadorned */ |
| if (file[0] == DIRSTR[0] || file[1] == ':') { |
| if (isFile(nameBuf)) { |
| strcpy(nameBuf, file); |
| return (nameBuf); |
| } |
| } |
| |
| if (path == NULL) { |
| return (NULL); |
| } |
| |
| /* otherwise, try every prefix in path */ |
| if ((pathBuf = (Char *)malloc(strlen(path) + 1)) != NULL) { |
| strcpy(pathBuf, path); |
| |
| tmp = strtok(pathBuf, PATHSTR); |
| for (; tmp != NULL; tmp = strtok(NULL, PATHSTR)) { |
| if ((len + 1 + strlen(tmp)) <= MAXNAME) { |
| sprintf(nameBuf, "%s%s%s", tmp, DIRSTR, file); |
| if (isFile(nameBuf)) { |
| free(pathBuf); |
| return (nameBuf); |
| } |
| } |
| } |
| free(pathBuf); |
| } |
| |
| return (NULL); |
| } |
| |
| /* |
| * ======== genEnvp ======== |
| * Generates environment for build tools: |
| * o Add xdcRoot to the beginning of PATH environment variable to ensure |
| * that our build tools are used within make. |
| * o remove CLASSPATH from environment to avoid in appropriate |
| * versions of Java or Java classes. |
| * o remove ENV to prevent shell from executing commands in the |
| * file named by $ENV for every shell use by gmake. It is for |
| * performance purposes only. |
| * o remove MAKEFLAGS to prevent xdc's make from reading make options |
| * set by a make calling xdc; e.g., the silent flag will prevent |
| * XDCOPTIONS=v from doing what is expected. |
| * o remove MAKELEVEL to prevent xdc's make from getting confused |
| * by a make calling xdc; e.g., a non-zero MAKELEVEL triggers |
| * the "print directories" feature (unless explicitly disabled) |
| */ |
| static char **genEnvp(String xdcRoot, char *envp[]) |
| { |
| Int i, j; |
| Int envc; |
| char **newEnvp = NULL; |
| |
| /* re-define selected environment variables */ |
| for (i = 0; envp[i] != NULL; i++) { |
| /* redefine XDCROOT (if necessary) */ |
| if (strncmp("XDCROOT=", envp[i], 8) == 0) { |
| envp[i] = rootDef; |
| if (nflag) { |
| printSetEnv(envp[i]); |
| } |
| } |
| else if (xdcPathDef != NULL && strncmp("XDCPATH=", envp[i], 8) == 0) { |
| /* we need to put XDCPATH in the environment because GNU make |
| * does not set the environment for commands run via $(shell ...) |
| * and we want all such commands to see the path specified in |
| * the command line |
| */ |
| envp[i] = xdcPathDef; |
| xdcPathDef = NULL; |
| if (nflag) { |
| printSetEnv(envp[i]); |
| } |
| } |
| else { |
| /* redefine PATH */ |
| String prefix[] = {"PATH=", "Path="}; |
| for (j = 0; j < (sizeof(prefix) / sizeof(String)); j++) { |
| if (strncmp(prefix[j], envp[i], strlen(prefix[j])) == 0) { |
| String path; |
| String mach; |
| Int len = strlen(envp[i]) + strlen(xdcRoot) + 32; |
| |
| if ((path = (String)malloc(len)) == NULL) { |
| fprintf(stderr, "%s: out of memory\n", progName); |
| exit(1); |
| } |
| if ((mach = getenv("_M")) != NULL) { |
| sprintf(path, "%s" DIRSTR "bin%s", xdcRoot, mach); |
| if (access(path, 00) != 0) { |
| mach = ""; |
| } |
| } |
| else { |
| mach = ""; |
| } |
| |
| sprintf(path, "%s%s" DIRSTR "bin%s" PATHSTR "%s", |
| prefix[j], xdcRoot, mach, envp[i] + strlen(prefix[j])); |
| envp[i] = path; |
| if (nflag) { |
| printSetEnv(envp[i]); |
| } |
| } |
| } |
| } |
| } |
| |
| /* remove undesirable environment variables */ |
| for (envc = i = 0; envp[i] != NULL; i++) { |
| String removeTab[] = { |
| "CLASSPATH=", |
| "ENV=", |
| "MAKELEVEL=", "MAKEFLAGS=" |
| }; |
| for (j = 0; j < (sizeof(removeTab) / sizeof(String)); j++) { |
| if (strncmp(removeTab[j], envp[i], strlen(removeTab[j])) == 0) { |
| if (nflag) { |
| printSetEnv(removeTab[j]); |
| } |
| break; |
| } |
| } |
| |
| /* if envp[i] is not in the undesirable list, add it to the env */ |
| if (j >= (sizeof(removeTab) / sizeof(String))) { |
| envp[envc++] = envp[i]; |
| } |
| } |
| |
| /* create a new environment array (so we can add new definitions) */ |
| if ((newEnvp = malloc((envc + MAXNEW + 1) * sizeof(String))) == NULL) { |
| fprintf(stderr, "%s: out of memory\n", progName); |
| exit(1); |
| } |
| memcpy(newEnvp, envp, envc * sizeof(String)); |
| |
| /* add XDCPATH definition, if necessary */ |
| if (xdcPathDef != NULL) { |
| newEnvp[envc++] = xdcPathDef; |
| } |
| |
| /* NULL terminate and return new environment array */ |
| newEnvp[envc] = NULL; |
| return (newEnvp); |
| } |
| |
| #if 0 |
| /* |
| * ======== getHostName ======== |
| */ |
| static String getHostName(Void) |
| { |
| static Char name[MAXNAME + 1]; |
| #if defined(xdc_target__os_Windows) |
| static Bool init = FALSE; |
| if (init == FALSE) { |
| WSADATA wsaData; |
| init = TRUE; |
| if ( WSAStartup( MAKEWORD( 1, 1 ), &wsaData) != 0 ) { |
| /* we could not find a usable WinSock DLL. */ |
| return(""); |
| } |
| } |
| #endif |
| |
| if (gethostname(name, MAXNAME) != 0) { |
| return(""); |
| } |
| name[MAXNAME] = '\0'; |
| |
| return (name); |
| } |
| #endif |
| |
| /* |
| * ======== getPackagePath ======== |
| */ |
| static String getPackagePath(String xdcPath) |
| { |
| String result = NULL; |
| String fullPath; |
| Int len; |
| |
| if (xdcPath == NULL) { |
| xdcPath = ""; |
| } |
| |
| len = strlen(xdcPath) + strlen(xdcRoot) + 32; |
| |
| if ((fullPath = (String)malloc(len * sizeof (char))) != NULL) { |
| sprintf(fullPath, "%s;%s;^", xdcPath, xdcRoot); |
| result = XUTL_expandPath(fullPath, ".", TRUE); |
| free(fullPath); |
| } |
| |
| return (result); |
| } |
| |
| /* |
| * ======== isFile ======== |
| * Return TRUE iff name exists and is not a directory |
| */ |
| static Bool isFile(String name) |
| { |
| struct stat buf; |
| |
| if (stat(name, &buf) == 0 && !S_ISDIR(buf.st_mode)) { |
| return (TRUE); |
| } |
| |
| return (FALSE); |
| } |
| |
| /* |
| * ======== printSetEnv ======== |
| */ |
| static Void printSetEnv(String env) |
| { |
| printf("set %s\n", env); |
| } |
| |
| /* |
| * ======== printVers ======== |
| */ |
| static Void printVers(String progName) |
| { |
| fprintf(stderr, "%s: version %s, %s\n", progName, |
| TISB_TREENAME, __DATE__); |
| } |