/* * This source code is released into the public domain. */ module; /* * Exec providers, mostly used for spawn(). */ #include export module nihil:exec; import :argv; import :fd; import :find_in_path; import :generic_error; namespace nihil { /* * Generic error, what() should be descriptive. */ export struct exec_error : generic_error { exec_error(std::string what); }; /* * We tried to execute a path or filename and the file was not found. */ export struct executable_not_found : exec_error { executable_not_found(std::string_view filename); auto filename(this executable_not_found const &self) -> std::string_view; private: std::string _filename; }; /* * A concept to mark spawn executors. */ export struct exec_tag{}; export template concept executor = requires (T e) { std::same_as; { e.exec() }; }; /* * fexecv: use a file descriptor and an argument vector to call ::fexecve(). * This is the lowest-level executor which all others are implemented * in terms of. * * TODO: Should have a way to pass the environment (envp). */ export struct fexecv final { using tag = exec_tag; fexecv(fd &&execfd, argv &&args) noexcept; [[noreturn]] auto exec(this fexecv &self) noexcept -> void; // Movable fexecv(fexecv &&) noexcept; auto operator=(this fexecv &, fexecv &&) noexcept -> fexecv&; // Not copyable (because we hold the open fd object) fexecv(fexecv const &) = delete; auto operator=(this fexecv &, fexecv const &) -> fexecv& = delete; private: fd _execfd; argv _args; }; /* * execv: equivalent to fexecv(), except the command is passed as * a pathname instead of a file descriptor. Does not search $PATH. */ export auto execv(std::string_view path, argv &&argv) -> fexecv; /* * execvp: equivalent to fexecv(), except the command is passed as * a filename instead of a file descriptor. If the filename is not * an absolute path, it will be searched for in $PATH. */ export auto execvp(std::string_view file, argv &&argv) -> fexecv; /* * execl: equivalent to execv, except the arguments are passed as a * variadic pack of string-like objects. */ export auto execl(std::string_view path, auto &&...args) -> fexecv { return execv(path, argv::from_args({std::string_view(args)...})); } /* * execlp: equivalent to execvp, except the arguments are passed as a * variadic pack of string-like objects. */ export auto execlp(std::string_view file, auto &&...args) -> fexecv { return execvp(file, argv::from_args({std::string_view(args)...})); } /* * shell: run the process by invoking /bin/sh -c with the single argument, * equivalent to system(3). */ export auto shell(std::string_view const &command) -> fexecv; } // namespace nihil