vfs: check userland buffers before reading them.
[haiku.git] / src / bin / getarch.cpp
blob47a7fe6221648ad2f59e61168adc0b8db41ee58a
1 /*
2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include <getopt.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
12 #include <Architecture.h>
13 #include <Path.h>
14 #include <PathFinder.h>
15 #include <StringList.h>
18 extern const char* __progname;
19 const char* kCommandName = __progname;
22 static const char* kUsage =
23 "Usage: %s [ <options> ] [ <path> ]\n"
24 "Prints the architecture currently set via the PATH environment variable,\n"
25 "when no arguments are given. When <path> is specified, the architecture\n"
26 "associated with that path is printed. The options allow to print the\n"
27 "primary architecture or the secondary architectures.\n"
28 "\n"
29 "Options:\n"
30 " -h, --help\n"
31 " Print this usage info.\n"
32 " -p, --primary\n"
33 " Print the primary architecture.\n"
34 " -s, --secondary\n"
35 " Print all secondary architectures for which support is installed.\n"
39 static void
40 print_usage_and_exit(bool error)
42 fprintf(error ? stderr : stdout, kUsage, kCommandName);
43 exit(error ? 1 : 0);
47 static BString
48 get_current_architecture()
50 // get the system installation location path
51 BPath systemPath;
52 if (find_directory(B_SYSTEM_DIRECTORY, &systemPath) != B_OK)
53 return BString();
55 // get all architectures
56 BStringList architectures;
57 get_architectures(architectures);
58 if (architectures.CountStrings() < 2)
59 return BString();
61 // get the system bin directory for each architecture
62 BStringList binDirectories;
63 BPathFinder pathFinder(systemPath.Path());
64 int32 architectureCount = architectures.CountStrings();
65 for (int32 i = 0; i < architectureCount; i++) {
66 BPath path;
67 if (pathFinder.FindPath(architectures.StringAt(i),
68 B_FIND_PATH_BIN_DIRECTORY, NULL, 0, path) != B_OK
69 || !binDirectories.Add(path.Path())) {
70 return BString();
74 // Get and split the PATH environmental variable value. The first system
75 // bin path we encounter implies the architecture.
76 char* pathVariableValue = getenv("PATH");
77 BStringList paths;
78 if (pathVariableValue != NULL
79 && BString(pathVariableValue).Split(":", true, paths)) {
80 int32 count = paths.CountStrings();
81 for (int32 i = 0; i < count; i++) {
82 // normalize the path, but skip a relative one
83 BPath path;
84 if (paths.StringAt(i)[0] != '/'
85 || path.SetTo(paths.StringAt(i), NULL, true) != B_OK) {
86 continue;
89 int32 index = binDirectories.IndexOf(path.Path());
90 if (index >= 0)
91 return architectures.StringAt(index);
95 return BString();
99 int
100 main(int argc, const char* const* argv)
102 bool printPrimary = false;
103 bool printSecondary = false;
105 while (true) {
106 static struct option sLongOptions[] = {
107 { "help", no_argument, 0, 'h' },
108 { "primary", no_argument, 0, 'p' },
109 { "secondary", no_argument, 0, 's' },
110 { 0, 0, 0, 0 }
113 opterr = 0; // don't print errors
114 int c = getopt_long(argc, (char**)argv, "+hps",
115 sLongOptions, NULL);
116 if (c == -1)
117 break;
119 switch (c) {
120 case 'h':
121 print_usage_and_exit(false);
122 break;
124 case 'p':
125 printPrimary = true;
126 break;
128 case 's':
129 printSecondary = true;
130 break;
132 default:
133 print_usage_and_exit(true);
134 break;
138 // The remaining argument is the optional path.
139 const char* path = optind < argc ? argv[optind++] : NULL;
140 if (optind < argc)
141 print_usage_and_exit(true);
143 // only one of path, printPrimary, printSecondary may be specified
144 if (int(path != NULL) + int(printPrimary) + int(printSecondary) > 1)
145 print_usage_and_exit(true);
147 if (path != NULL) {
148 // architecture for given path
149 printf("%s\n", guess_architecture_for_path(path));
150 } else if (printPrimary) {
151 // primary architecture
152 printf("%s\n", get_primary_architecture());
153 } else if (printSecondary) {
154 // secondary architectures
155 BStringList architectures;
156 get_secondary_architectures(architectures);
157 int32 count = architectures.CountStrings();
158 for (int32 i = 0; i < count; i++)
159 printf("%s\n", architectures.StringAt(i).String());
160 } else {
161 // current architecture as implied by PATH
162 BString architecture = get_current_architecture();
163 printf("%s\n",
164 architecture.IsEmpty()
165 ? get_primary_architecture() : architecture.String());
168 return 0;