/* * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #include #include #include #include #include #include #include #include extern const char* __progname; const char* kCommandName = __progname; static const char* kUsage = "Usage: %s [ ] [ ]\n" "Prints the architecture currently set via the PATH environment variable,\n" "when no arguments are given. When is specified, the architecture\n" "associated with that path is printed. The options allow to print the\n" "primary architecture or the secondary architectures.\n" "\n" "Options:\n" " -h, --help\n" " Print this usage info.\n" " -p, --primary\n" " Print the primary architecture.\n" " -s, --secondary\n" " Print all secondary architectures for which support is installed.\n" ; static void print_usage_and_exit(bool error) { fprintf(error ? stderr : stdout, kUsage, kCommandName); exit(error ? 1 : 0); } static BString get_current_architecture() { // get the system installation location path BPath systemPath; if (find_directory(B_SYSTEM_DIRECTORY, &systemPath) != B_OK) return BString(); // get all architectures BStringList architectures; get_architectures(architectures); if (architectures.CountStrings() < 2) return BString(); // get the system bin directory for each architecture BStringList binDirectories; BPathFinder pathFinder(systemPath.Path()); int32 architectureCount = architectures.CountStrings(); for (int32 i = 0; i < architectureCount; i++) { BPath path; if (pathFinder.FindPath(architectures.StringAt(i), B_FIND_PATH_BIN_DIRECTORY, NULL, 0, path) != B_OK || !binDirectories.Add(path.Path())) { return BString(); } } // Get and split the PATH environmental variable value. The first system // bin path we encounter implies the architecture. char* pathVariableValue = getenv("PATH"); BStringList paths; if (pathVariableValue != NULL && BString(pathVariableValue).Split(":", true, paths)) { int32 count = paths.CountStrings(); for (int32 i = 0; i < count; i++) { // normalize the path, but skip a relative one BPath path; if (paths.StringAt(i)[0] != '/' || path.SetTo(paths.StringAt(i), NULL, true) != B_OK) { continue; } int32 index = binDirectories.IndexOf(path.Path()); if (index >= 0) return architectures.StringAt(index); } } return BString(); } int main(int argc, const char* const* argv) { bool printPrimary = false; bool printSecondary = false; while (true) { static struct option sLongOptions[] = { { "help", no_argument, 0, 'h' }, { "primary", no_argument, 0, 'p' }, { "secondary", no_argument, 0, 's' }, { 0, 0, 0, 0 } }; opterr = 0; // don't print errors int c = getopt_long(argc, (char**)argv, "+hps", sLongOptions, NULL); if (c == -1) break; switch (c) { case 'h': print_usage_and_exit(false); break; case 'p': printPrimary = true; break; case 's': printSecondary = true; break; default: print_usage_and_exit(true); break; } } // The remaining argument is the optional path. const char* path = optind < argc ? argv[optind++] : NULL; if (optind < argc) print_usage_and_exit(true); // only one of path, printPrimary, printSecondary may be specified if (int(path != NULL) + int(printPrimary) + int(printSecondary) > 1) print_usage_and_exit(true); if (path != NULL) { // architecture for given path printf("%s\n", guess_architecture_for_path(path)); } else if (printPrimary) { // primary architecture printf("%s\n", get_primary_architecture()); } else if (printSecondary) { // secondary architectures BStringList architectures; get_secondary_architectures(architectures); int32 count = architectures.CountStrings(); for (int32 i = 0; i < count; i++) printf("%s\n", architectures.StringAt(i).String()); } else { // current architecture as implied by PATH BString architecture = get_current_architecture(); printf("%s\n", architecture.IsEmpty() ? get_primary_architecture() : architecture.String()); } return 0; }