Skip to content

Commit

Permalink
preliminary <sh> implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
flammie committed Oct 2, 2024
1 parent b6a1388 commit 315f488
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 10 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ For more details see the git log.

* package name is now libdivvun
* normaliser doesn't add subreadings
* pipeline supports sh

## Notable changes in 0.3.10

Expand Down
84 changes: 76 additions & 8 deletions src/pipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,62 @@ const MsgMap& SuggestCmd::getMsgs() {
return suggest->msgs;
}

ShCmd::ShCmd(
const string& prog, const std::vector<string>& args, bool verbose) {
argv = (char**)malloc(sizeof(char*) * (args.size() * 2 + 2));
size_t i = 0;
for (auto arg : args) {
argv[i++] = strdup(arg.c_str());
}
argv[i] = NULL;
}


ShCmd::~ShCmd() {
size_t i = 0;
while (argv[i] != NULL) {
free(argv[i++]);
}
free(argv);
}

void ShCmd::run(stringstream& input, stringstream& output) const {
int fds[2];
if (pipe(fds) == -1) {
throw std::runtime_error("pipe failed ");
}
pid_t pid = fork();
if (pid == -1) {
throw std::runtime_error("fork failed ");
}
else if (pid == 0) {
close(fds[1]); // close write
dup2(fds[0], STDIN_FILENO); // redirect
close(fds[0]); // close read
if (execvp(argv[0], argv) < 0) {
throw std::runtime_error("exec failed ");
}
throw std::runtime_error("child process failed ");
}
else {
close(fds[0]); // close read
char buffin[8192];
while (input.getline(buffin, sizeof(buffin))) {
size_t readn = input.gcount();
if (write(fds[1], buffin, readn) == -1) {
throw std::runtime_error("write failed");
}
}
close(fds[1]); // close write
char buffout[8192];
ssize_t count;
while ((count = read(fds[1], buffout, sizeof(buffout))) > 0) {
output.write(buffout, count);
}
}
//wait(0); // wait
}


Pipeline::Pipeline(LocalisedPrefs prefs_, vector<unique_ptr<PipeCmd>> cmds_,
SuggestCmd* suggestcmd_, bool verbose_, bool trace_)
Expand Down Expand Up @@ -333,8 +389,14 @@ Pipeline Pipeline::mkPipeline(const unique_ptr<ArPipeSpec>& ar_spec,
suggestcmd = s;
}
else if (name == u"sh") {
// const auto& prog = fromUtf8(cmd.attribute("prog").value());
// cmds.emplace_back(new ShCmd(prog, args, verbose));
const auto& prog = cmd.attribute("prog").value();
std::vector<string> argv;
for (const pugi::xml_node& arg : cmd.children()) {
if (strcmp(arg.name(), "arg") == 0) {
argv.push_back(arg.text().get());
}
}
cmds.emplace_back(new ShCmd(prog, argv, verbose));
}
else if (name == u"prefs") {
parsePrefs(prefs, cmd);
Expand Down Expand Up @@ -383,9 +445,9 @@ Pipeline Pipeline::mkPipeline(const unique_ptr<PipeSpec>& spec,
cmd.attribute("max-weight").as_float(5000.0),
cmd.attribute("max-unknown-rate").as_float(0.4), verbose));
#else
throw std::runtime_error(
"libdivvun: ERROR: Tried to run pipeline with cgspell, but was "
"compiled without cgspell support!");
throw std::runtime_error("libdivvun: ERROR: Tried to run "
"pipeline with cgspell, but was "
"compiled without cgspell support!");
#endif
}
else if ((name == u"normalise") || (name == u"normalize")) {
Expand Down Expand Up @@ -423,8 +485,15 @@ Pipeline Pipeline::mkPipeline(const unique_ptr<PipeSpec>& spec,
suggestcmd = s;
}
else if (name == u"sh") {
// const auto& prog = fromUtf8(cmd.attribute("prog").value());
// cmds.emplace_back(new ShCmd(prog, args, verbose));
const auto& prog = cmd.attribute("prog").value();
std::vector<string> argv;
argv.push_back(prog);
for (const pugi::xml_node& arg : cmd.children()) {
if (strcmp(arg.name(), "arg") == 0) {
argv.push_back(arg.text().get());
}
}
cmds.emplace_back(new ShCmd(prog, argv, verbose));
}
else if (name == u"prefs") {
parsePrefs(prefs, cmd);
Expand Down Expand Up @@ -491,5 +560,4 @@ void Pipeline::setIncludes(const std::set<ErrId>& includes) {
"a SuggestCmd");
}
}

}
9 changes: 9 additions & 0 deletions src/pipeline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,15 @@ class SuggestCmd : public PipeCmd {
unique_ptr<Suggest> suggest;
};

class ShCmd : public PipeCmd {
public:
ShCmd(const string& prog, const std::vector<string>& args, bool verbose);
void run(stringstream& input, stringstream& output) const override;
~ShCmd() override;

private:
char** argv;
};

inline void parsePrefs(LocalisedPrefs& prefs, const pugi::xml_node& cmd) {
for (const pugi::xml_node& pref : cmd.children()) {
Expand Down
9 changes: 7 additions & 2 deletions src/pipespec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,13 @@ void validatePipespecCmd(
}
}
else if (name == "sh") {
throw std::runtime_error("<sh> command not implemented yet!");
// const auto& prog = fromUtf8(cmd.attribute("prog").value());
string prog = cmd.attribute("prog").value();
// should also hard code list of acceptable commands for security
int rv = std::system((string("which ") + prog + ">/dev/null").c_str());
if (rv != 0) {
throw std::runtime_error(
"OS is missing a program needed by pipe: " + prog);
}
}
else if (name == "prefs") {
// pass
Expand Down

0 comments on commit 315f488

Please sign in to comment.