Add setarch and getarch commands
This commit is contained in:
parent
c39c9283aa
commit
4f5e938576
@ -14,7 +14,7 @@ SYSTEM_BIN = [ FFilterByBuildFeatures
|
||||
echo eject env error expand expr
|
||||
factor false fdinfo ffm filepanel find finddir findpaths FirstBootPrompt fmt
|
||||
fold fortune frcode fstrim ftp ftpd funzip fwcontrol@x86
|
||||
gawk gdb@x86 getlimits groupadd groupdel groupmod groups gzip gzexe
|
||||
gawk gdb@x86 getarch getlimits groupadd groupdel groupmod groups gzip gzexe
|
||||
hd head hey hostname
|
||||
id ident ifconfig <bin>install installsound iroster isvolume
|
||||
ideinfo@ide idestatus@ide
|
||||
@ -31,9 +31,9 @@ SYSTEM_BIN = [ FFilterByBuildFeatures
|
||||
query quit
|
||||
rc readlink reindex release renice rlog rm rmattr rmindex rmdir roster
|
||||
route
|
||||
safemode screen_blanker screenmode screenshot sdiff setdecor setmime settype
|
||||
setversion setvolume seq sha1sum sha256sum shar shred shuf shutdown sleep
|
||||
sort spamdbm split stat strace stty su sum sync sysinfo
|
||||
safemode screen_blanker screenmode screenshot sdiff setarch setdecor setmime
|
||||
settype setversion setvolume seq sha1sum sha256sum shar shred shuf shutdown
|
||||
sleep sort spamdbm split stat strace stty su sum sync sysinfo
|
||||
tac tail tcpdump tcptester tee telnet telnetd test timeout top touch
|
||||
tr traceroute translate trash true truncate tsort tty
|
||||
uname unchop unexpand unmount uniq unlink unshar unzip unzipsfx
|
||||
|
@ -14,7 +14,7 @@ SYSTEM_BIN = [ FFilterByBuildFeatures
|
||||
echo eject env error expand expr
|
||||
factor false fdinfo ffm filepanel find finddir findpaths fmt fold
|
||||
fortune frcode ftp ftpd funzip
|
||||
gawk gdb@x86 getlimits groupadd groupdel groupmod groups gzip gzexe
|
||||
gawk gdb@x86 getarch getlimits groupadd groupdel groupmod groups gzip gzexe
|
||||
hd head hey hostname
|
||||
id ident ifconfig <bin>install isvolume
|
||||
ideinfo@ide idestatus@ide
|
||||
@ -31,7 +31,7 @@ SYSTEM_BIN = [ FFilterByBuildFeatures
|
||||
query quit
|
||||
rc readlink reindex release renice rlog rm rmattr rmindex rmdir roster
|
||||
route
|
||||
safemode screen_blanker screenmode sdiff setmime settype
|
||||
safemode screen_blanker screenmode sdiff setarch setmime settype
|
||||
setversion setvolume seq sha1sum sha256sum shar shred shuf shutdown sleep
|
||||
sort split stat strace stty su sum sync sysinfo
|
||||
tac tail tcpdump tcptester tee telnet telnetd test timeout top touch
|
||||
|
@ -116,9 +116,11 @@ StdBinCommands
|
||||
alert.cpp
|
||||
eject.cpp
|
||||
findpaths.cpp
|
||||
getarch.cpp
|
||||
hey.cpp
|
||||
reindex.cpp
|
||||
resattr.cpp
|
||||
setarch.cpp
|
||||
setdecor.cpp
|
||||
settype.cpp
|
||||
spybmessage.cpp
|
||||
|
169
src/bin/getarch.cpp
Normal file
169
src/bin/getarch.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Architecture.h>
|
||||
#include <Path.h>
|
||||
#include <PathFinder.h>
|
||||
#include <StringList.h>
|
||||
|
||||
|
||||
extern const char* __progname;
|
||||
const char* kCommandName = __progname;
|
||||
|
||||
|
||||
static const char* kUsage =
|
||||
"Usage: %s [ <options> ] [ <path> ]\n"
|
||||
"Prints the architecture currently set via the PATH environment variable,\n"
|
||||
"when no arguments are given. When <path> 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;
|
||||
}
|
230
src/bin/setarch.cpp
Normal file
230
src/bin/setarch.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <Architecture.h>
|
||||
#include <Path.h>
|
||||
#include <PathFinder.h>
|
||||
#include <StringList.h>
|
||||
|
||||
|
||||
extern const char* __progname;
|
||||
const char* kCommandName = __progname;
|
||||
|
||||
|
||||
static const char* kUsage =
|
||||
"Usage: %s [ <options> ] <architecture> [ <command> ... ]\n"
|
||||
"Executes the given command or, by default, a shell with a PATH\n"
|
||||
"environment variable modified such that commands for the given\n"
|
||||
"architecture will be preferred, respectively used exclusively in case of\n"
|
||||
"the primary architecture.\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -h, --help\n"
|
||||
" Print this usage info.\n"
|
||||
" -p, --print-path\n"
|
||||
" Only print the modified PATH variable value; don't execute any\n"
|
||||
" command.\n"
|
||||
;
|
||||
|
||||
|
||||
static void
|
||||
print_usage_and_exit(bool error)
|
||||
{
|
||||
fprintf(error ? stderr : stdout, kUsage, kCommandName);
|
||||
exit(error ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
is_primary_architecture(const char* architecture)
|
||||
{
|
||||
return strcmp(architecture, get_primary_architecture()) == 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
get_bin_directories(const char* architecture, BStringList& _directories)
|
||||
{
|
||||
status_t error = BPathFinder::FindPaths(architecture,
|
||||
B_FIND_PATH_BIN_DIRECTORY, NULL, 0, _directories);
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "Error: Failed to get bin directories for architecture "
|
||||
"%s: %s\n", architecture, strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
compute_new_paths(const char* architecture, BStringList& _paths)
|
||||
{
|
||||
// get the primary architecture bin paths
|
||||
BStringList primaryBinDirectories;
|
||||
get_bin_directories(get_primary_architecture(), primaryBinDirectories);
|
||||
|
||||
// get the bin paths to insert
|
||||
BStringList binDirectoriesToInsert;
|
||||
if (!is_primary_architecture(architecture))
|
||||
get_bin_directories(architecture, binDirectoriesToInsert);
|
||||
|
||||
// split the PATH variable
|
||||
char* pathVariableValue = getenv("PATH");
|
||||
BStringList paths;
|
||||
if (pathVariableValue != NULL
|
||||
&& !BString(pathVariableValue).Split(":", true, paths)) {
|
||||
fprintf(stderr, "Error: Out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Filter the paths, removing any path that isn't associated with the
|
||||
// primary architecture. Also find the insertion index for the architecture
|
||||
// bin paths.
|
||||
int32 insertionIndex = -1;
|
||||
int32 count = paths.CountStrings();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
// We always keep relative paths. Filter absolute ones only.
|
||||
const char* path = paths.StringAt(i);
|
||||
if (path[0] == '/') {
|
||||
// try to normalize the path
|
||||
BPath normalizedPath;
|
||||
if (normalizedPath.SetTo(path, NULL, true) == B_OK)
|
||||
path = normalizedPath.Path();
|
||||
|
||||
// Check, if this is a primary bin directory. If not, determine the
|
||||
// path's architecture.
|
||||
int32 index = primaryBinDirectories.IndexOf(path);
|
||||
if (index >= 0) {
|
||||
if (insertionIndex < 0)
|
||||
insertionIndex = i;
|
||||
} else if (!is_primary_architecture(
|
||||
guess_architecture_for_path(path))) {
|
||||
// a non-primary architecture path -- skip
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_paths.Add(paths.StringAt(i))) {
|
||||
fprintf(stderr, "Error: Out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the paths for the specified architecture, if any.
|
||||
if (!binDirectoriesToInsert.IsEmpty()) {
|
||||
if (!(insertionIndex < 0
|
||||
? _paths.Add(binDirectoriesToInsert)
|
||||
: _paths.Add(binDirectoriesToInsert, insertionIndex))) {
|
||||
fprintf(stderr, "Error: Out of memory!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, const char* const* argv)
|
||||
{
|
||||
bool printPath = false;
|
||||
|
||||
while (true) {
|
||||
static struct option sLongOptions[] = {
|
||||
{ "help", no_argument, 0, 'h' },
|
||||
{ "print-path", no_argument, 0, 'p' },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
opterr = 0; // don't print errors
|
||||
int c = getopt_long(argc, (char**)argv, "+hp",
|
||||
sLongOptions, NULL);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'h':
|
||||
print_usage_and_exit(false);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
printPath = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
print_usage_and_exit(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The remaining arguments are the architecture and optionally the command
|
||||
// to execute.
|
||||
if (optind >= argc)
|
||||
print_usage_and_exit(true);
|
||||
const char* architecture = optind < argc ? argv[optind++] : NULL;
|
||||
|
||||
int commandArgCount = argc - optind;
|
||||
const char* const* commandArgs = commandArgCount > 0 ? argv + optind : NULL;
|
||||
|
||||
if (printPath && commandArgs != NULL)
|
||||
print_usage_and_exit(true);
|
||||
|
||||
// check the architecture
|
||||
BStringList architectures;
|
||||
status_t error = get_architectures(architectures);
|
||||
if (error != B_OK) {
|
||||
fprintf(stderr, "Error: Failed to get architectures: %s\n",
|
||||
strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!architectures.HasString(architecture)) {
|
||||
fprintf(stderr, "Error: Unsupported architecture \"%s\"\n",
|
||||
architecture);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// get the new paths
|
||||
BStringList paths;
|
||||
compute_new_paths(architecture, paths);
|
||||
|
||||
BString pathVariableValue = paths.Join(":");
|
||||
if (!paths.IsEmpty() && pathVariableValue.IsEmpty())
|
||||
fprintf(stderr, "Error: Out of memory!\n");
|
||||
|
||||
if (printPath) {
|
||||
printf("%s\n", pathVariableValue.String());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// set PATH
|
||||
if (setenv("PATH", pathVariableValue, 1) != 0) {
|
||||
fprintf(stderr, "Error: Failed to set PATH: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// if no command is given, get the user's shell
|
||||
const char* shellCommand[2];
|
||||
if (commandArgs == NULL) {
|
||||
struct passwd* pwd = getpwuid(geteuid());
|
||||
shellCommand[0] = pwd != NULL ? pwd->pw_shell : "/bin/sh";
|
||||
shellCommand[1] = NULL;
|
||||
commandArgs = shellCommand;
|
||||
commandArgCount = 1;
|
||||
}
|
||||
|
||||
// exec the command
|
||||
execvp(commandArgs[0], (char* const*)commandArgs);
|
||||
|
||||
fprintf(stderr, "Error: Executing \"%s\" failed: %s\n", commandArgs[0],
|
||||
strerror(errno));
|
||||
return 1;
|
||||
}
|
Loading…
Reference in New Issue
Block a user