diff --git a/Userland/chroot.cpp b/Userland/chroot.cpp index 890d18ac02..6cb867fc4b 100644 --- a/Userland/chroot.cpp +++ b/Userland/chroot.cpp @@ -1,14 +1,79 @@ +#include +#include #include #include -int main(int argc, char** argv) +struct Options { + const char* path; + const char* program { "/bin/Shell" }; + int flags { -1 }; +}; + +void print_usage(const char* argv0) { - if (argc != 2) { - printf("usage: chroot \n"); - return 0; + fprintf( + stderr, + "Usage:\n" + "\t%s [program] [-o options]\n", + argv0 + ); +} + +Options parse_options(int argc, char** argv) +{ + Options options; + + if (argc < 2) { + print_usage(argv[0]); + exit(1); } - if (chroot(argv[1]) < 0) { + options.path = argv[1]; + int i = 2; + if (i < argc && argv[i][0] != '-') + options.program = argv[i++]; + + if (i >= argc) + return options; + + if (strcmp(argv[i], "-o") != 0) { + print_usage(argv[0]); + exit(1); + } + i++; + if (i >= argc) { + print_usage(argv[0]); + exit(1); + } + + options.flags = 0; + + StringView arg = argv[i]; + Vector parts = arg.split_view(','); + for (auto& part : parts) { + if (part == "defaults") + continue; + else if (part == "nodev") + options.flags |= MS_NODEV; + else if (part == "noexec") + options.flags |= MS_NOEXEC; + else if (part == "nosuid") + options.flags |= MS_NOSUID; + else if (part == "bind") + fprintf(stderr, "Ignoring -o bind, as it doesn't make sense for chroot"); + else + fprintf(stderr, "Ignoring invalid option: %s\n", String(part).characters()); + } + + return options; +} + +int main(int argc, char** argv) +{ + + Options options = parse_options(argc, argv); + + if (chroot_with_mount_flags(options.path, options.flags) < 0) { perror("chroot"); return 1; } @@ -18,10 +83,7 @@ int main(int argc, char** argv) return 1; } - if (execl("/bin/Shell", "Shell", nullptr) < 0) { - perror("execl"); - return 1; - } - - return 0; + execl(options.program, options.program, nullptr); + perror("execl"); + return 1; }