summaryrefslogtreecommitdiff
path: root/Shell/main.cpp
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-05-16 03:44:47 +0430
committerAndreas Kling <kling@serenityos.org>2020-05-17 11:58:08 +0200
commit172df68666dbfb9770cff6ab472b7fe1eea80a6b (patch)
tree1b3780958085a5a1e00cbf2bbbce79cc4a25390d /Shell/main.cpp
parente630d8363307408439c4a12eeef475f64fef77f4 (diff)
downloadserenity-172df68666dbfb9770cff6ab472b7fe1eea80a6b.zip
Shell: Patch most of the builtins to use Core::ArgsParser
The remaining one is 'pushd', which seems to have relatively complex logic with regards to its arguments.
Diffstat (limited to 'Shell/main.cpp')
-rw-r--r--Shell/main.cpp216
1 files changed, 128 insertions, 88 deletions
diff --git a/Shell/main.cpp b/Shell/main.cpp
index db1993e16e..38cf360a8e 100644
--- a/Shell/main.cpp
+++ b/Shell/main.cpp
@@ -194,33 +194,57 @@ static int sh_exit(int, const char**)
static int sh_export(int argc, const char** argv)
{
- if (argc == 1) {
+ Vector<const char*> vars;
+
+ Core::ArgsParser parser;
+ parser.add_positional_argument(vars, "List of variable[=value]'s", "values", Core::ArgsParser::Required::No);
+
+ if (!parser.parse(argc, const_cast<char**>(argv), false))
+ return 1;
+
+ if (vars.size() == 0) {
for (int i = 0; environ[i]; ++i)
puts(environ[i]);
return 0;
}
- auto parts = String(argv[1]).split('=');
- if (parts.size() != 2) {
- fprintf(stderr, "usage: export variable=value\n");
- return 1;
- }
- int setenv_return = setenv(parts[0].characters(), parts[1].characters(), 1);
+ int return_value = 0;
+
+ for (auto& value : vars) {
+ auto parts = String { value }.split_limit('=', 2);
- if (setenv_return == 0 && parts[0] == "PATH")
- cache_path();
+ if (parts.size() == 1) {
+ parts.append("");
+ }
- return setenv_return;
+ int setenv_return = setenv(parts[0].characters(), parts[1].characters(), 1);
+
+ if (setenv_return != 0) {
+ perror("setenv");
+ return_value = 1;
+ break;
+ }
+
+ if (parts[0] == "PATH")
+ cache_path();
+ }
+
+ return return_value;
}
static int sh_unset(int argc, const char** argv)
{
- if (argc != 2) {
- fprintf(stderr, "usage: unset variable\n");
+ Vector<const char*> vars;
+
+ Core::ArgsParser parser;
+ parser.add_positional_argument(vars, "List of variables", "variables", Core::ArgsParser::Required::Yes);
+
+ if (!parser.parse(argc, const_cast<char**>(argv), false))
return 1;
- }
- unsetenv(argv[1]);
+ for (auto& value : vars)
+ unsetenv(value);
+
return 0;
}
@@ -262,32 +286,35 @@ static String expand_tilde(const String& expression)
static int sh_cd(int argc, const char** argv)
{
- if (argc > 2) {
- fprintf(stderr, "cd: too many arguments\n");
+ const char* arg_path = nullptr;
+
+ Core::ArgsParser parser;
+ parser.add_positional_argument(arg_path, "Path to change to", "path", Core::ArgsParser::Required::No);
+
+ if (!parser.parse(argc, const_cast<char**>(argv), false))
return 1;
- }
String new_path;
- if (argc == 1) {
+ if (!arg_path) {
new_path = g.home;
if (g.cd_history.is_empty() || g.cd_history.last() != g.home)
g.cd_history.enqueue(g.home);
} else {
- if (g.cd_history.is_empty() || g.cd_history.last() != argv[1])
- g.cd_history.enqueue(argv[1]);
+ if (g.cd_history.is_empty() || g.cd_history.last() != arg_path)
+ g.cd_history.enqueue(arg_path);
if (strcmp(argv[1], "-") == 0) {
char* oldpwd = getenv("OLDPWD");
if (oldpwd == nullptr)
return 1;
new_path = oldpwd;
- } else if (argv[1][0] == '/') {
+ } else if (arg_path[0] == '/') {
new_path = argv[1];
} else {
StringBuilder builder;
builder.append(g.cwd);
builder.append('/');
- builder.append(argv[1]);
+ builder.append(arg_path);
new_path = builder.to_string();
}
}
@@ -322,12 +349,15 @@ static int sh_cd(int argc, const char** argv)
static int sh_cdh(int argc, const char** argv)
{
- if (argc > 2) {
- fprintf(stderr, "usage: cdh [index]\n");
+ int index = -1;
+
+ Core::ArgsParser parser;
+ parser.add_positional_argument(index, "Index of the cd history entry (leave out for a list)", "index", Core::ArgsParser::Required::No);
+
+ if (!parser.parse(argc, const_cast<char**>(argv), false))
return 1;
- }
- if (argc == 1) {
+ if (index == -1) {
if (g.cd_history.size() == 0) {
printf("cdh: no history available\n");
return 0;
@@ -338,15 +368,12 @@ static int sh_cdh(int argc, const char** argv)
return 0;
}
- bool ok;
- size_t cd_history_index = String(argv[1]).to_uint(ok);
-
- if (!ok || cd_history_index < 1 || cd_history_index > g.cd_history.size()) {
- fprintf(stderr, "usage: cdh [index]\n");
+ if (index < 1 || (size_t)index > g.cd_history.size()) {
+ fprintf(stderr, "cdh: history index out of bounds: %d not in (0, %zu)\n", index, g.cd_history.size());
return 1;
}
- const char* path = g.cd_history.at(g.cd_history.size() - cd_history_index).characters();
+ const char* path = g.cd_history.at(g.cd_history.size() - index).characters();
const char* cd_args[] = { "cd", path };
return sh_cd(2, cd_args);
}
@@ -361,16 +388,17 @@ static int sh_history(int, const char**)
static int sh_time(int argc, const char** argv)
{
- if (argc == 1) {
- printf("usage: time <command>\n");
- return 0;
- }
+ Vector<const char*> args;
+
+ Core::ArgsParser parser;
+ parser.add_positional_argument(args, "Command to execute with arguments", "command", Core::ArgsParser::Required::Yes);
+
+ if (!parser.parse(argc, const_cast<char**>(argv), false))
+ return 1;
+
StringBuilder builder;
- for (int i = 1; i < argc; ++i) {
- builder.append(argv[i]);
- if (i != argc - 1)
- builder.append(' ');
- }
+ builder.join(' ', args);
+
Core::ElapsedTimer timer;
timer.start();
auto exit_code = run_command(builder.string_view());
@@ -447,7 +475,7 @@ static int sh_fg(int argc, const char** argv)
int job_id = -1;
Core::ArgsParser parser;
- parser.add_positional_argument(job_id, "job id to bring to foreground", "job_id", Core::ArgsParser::Required::No);
+ parser.add_positional_argument(job_id, "Job id to bring to foreground", "job_id", Core::ArgsParser::Required::No);
if (!parser.parse(argc, const_cast<char**>(argv), false))
return 1;
@@ -504,7 +532,7 @@ static int sh_bg(int argc, const char** argv)
int job_id = -1;
Core::ArgsParser parser;
- parser.add_positional_argument(job_id, "job id to run in background", "job_id", Core::ArgsParser::Required::No);
+ parser.add_positional_argument(job_id, "Job id to run in background", "job_id", Core::ArgsParser::Required::No);
if (!parser.parse(argc, const_cast<char**>(argv), false))
return 1;
@@ -542,21 +570,28 @@ static int sh_bg(int argc, const char** argv)
static int sh_umask(int argc, const char** argv)
{
- if (argc == 1) {
+ const char* mask_text = nullptr;
+
+ Core::ArgsParser parser;
+ parser.add_positional_argument(mask_text, "New mask (omit to get current mask)", "octal-mask", Core::ArgsParser::Required::No);
+
+ if (!parser.parse(argc, const_cast<char**>(argv), false))
+ return 1;
+
+ if (!mask_text) {
mode_t old_mask = umask(0);
printf("%#o\n", old_mask);
umask(old_mask);
return 0;
}
- if (argc == 2) {
- unsigned mask;
- int matches = sscanf(argv[1], "%o", &mask);
- if (matches == 1) {
- umask(mask);
- return 0;
- }
+
+ unsigned mask;
+ int matches = sscanf(mask_text, "%o", &mask);
+ if (matches == 1) {
+ umask(mask);
+ return 0;
}
- printf("usage: umask <octal-mask>\n");
+
return 0;
}
@@ -567,14 +602,22 @@ static int sh_popd(int argc, const char** argv)
return 1;
}
- bool should_switch = true;
+ bool should_not_switch = false;
String path = g.directory_stack.take_last();
+ Core::ArgsParser parser;
+ parser.add_option(should_not_switch, "Do not switch dirs", "no-switch", 'n');
+
+ if (!parser.parse(argc, const_cast<char**>(argv), false))
+ return 1;
+
+ bool should_switch = !should_not_switch;
+
// When no arguments are given, popd removes the top directory from the stack and performs a cd to the new top directory.
if (argc == 1) {
int rc = chdir(path.characters());
if (rc < 0) {
- fprintf(stderr, "chdir(%s) failed: %s", path.characters(), strerror(errno));
+ fprintf(stderr, "chdir(%s) failed: %s\n", path.characters(), strerror(errno));
return 1;
}
@@ -582,13 +625,6 @@ static int sh_popd(int argc, const char** argv)
return 0;
}
- for (int i = 1; i < argc; i++) {
- const char* arg = argv[i];
- if (!strcmp(arg, "-n")) {
- should_switch = false;
- }
- }
-
FileSystemPath canonical_path(path.characters());
if (!canonical_path.is_valid()) {
fprintf(stderr, "FileSystemPath failed to canonicalize '%s'\n", path.characters());
@@ -642,7 +678,7 @@ static int sh_pushd(int argc, const char** argv)
int rc = chdir(dir2.characters());
if (rc < 0) {
- fprintf(stderr, "chdir(%s) failed: %s", dir2.characters(), strerror(errno));
+ fprintf(stderr, "chdir(%s) failed: %s\n", dir2.characters(), strerror(errno));
return 1;
}
@@ -724,35 +760,39 @@ static int sh_dirs(int argc, const char** argv)
return 0;
}
- bool printed = false;
- for (int i = 0; i < argc; i++) {
- const char* arg = argv[i];
- if (!strcmp(arg, "-c")) {
- for (size_t i = 1; i < g.directory_stack.size(); i++)
- g.directory_stack.remove(i);
+ bool clear = false;
+ bool print = false;
+ bool number_when_printing = false;
- printed = true;
- continue;
- }
- if (!strcmp(arg, "-p") && !printed) {
- for (auto& directory : g.directory_stack) {
- print_path(directory);
- fputc('\n', stdout);
- }
+ Vector<const char*> paths;
- printed = true;
- continue;
- }
- if (!strcmp(arg, "-v") && !printed) {
- int idx = 0;
- for (auto& directory : g.directory_stack) {
- printf("%d ", idx++);
- print_path(directory);
- fputc('\n', stdout);
- }
+ Core::ArgsParser parser;
+ parser.add_option(clear, "Clear the directory stack", "clear", 'c');
+ parser.add_option(print, "Print directory entries", "print", 'p');
+ parser.add_option(number_when_printing, "Number the directories in the stack when printing", "number", 'v');
+ parser.add_positional_argument(paths, "Extra paths to put on the stack", "paths", Core::ArgsParser::Required::No);
- printed = true;
- continue;
+ if (!parser.parse(argc, const_cast<char**>(argv), false))
+ return 1;
+
+ // -v implies -p
+ print = print || number_when_printing;
+
+ if (clear) {
+ for (size_t i = 1; i < g.directory_stack.size(); i++)
+ g.directory_stack.remove(i);
+ }
+
+ for (auto& path : paths)
+ g.directory_stack.append(path);
+
+ if (print) {
+ auto idx = 0;
+ for (auto& directory : g.directory_stack) {
+ if (number_when_printing)
+ printf("%d ", idx++);
+ print_path(directory);
+ fputc('\n', stdout);
}
}