@@ -179,6 +179,62 @@ const MsgMap& SuggestCmd::getMsgs() {
179
179
return suggest->msgs ;
180
180
}
181
181
182
+ ShCmd::ShCmd (
183
+ const string& prog, const std::vector<string>& args, bool verbose) {
184
+ argv = (char **)malloc (sizeof (char *) * (args.size () * 2 + 2 ));
185
+ size_t i = 0 ;
186
+ for (auto arg : args) {
187
+ argv[i++] = strdup (arg.c_str ());
188
+ }
189
+ argv[i] = NULL ;
190
+ }
191
+
192
+
193
+ ShCmd::~ShCmd () {
194
+ size_t i = 0 ;
195
+ while (argv[i] != NULL ) {
196
+ free (argv[i++]);
197
+ }
198
+ free (argv);
199
+ }
200
+
201
+ void ShCmd::run (stringstream& input, stringstream& output) const {
202
+ int fds[2 ];
203
+ if (pipe (fds) == -1 ) {
204
+ throw std::runtime_error (" pipe failed " );
205
+ }
206
+ pid_t pid = fork ();
207
+ if (pid == -1 ) {
208
+ throw std::runtime_error (" fork failed " );
209
+ }
210
+ else if (pid == 0 ) {
211
+ close (fds[1 ]); // close write
212
+ dup2 (fds[0 ], STDIN_FILENO); // redirect
213
+ close (fds[0 ]); // close read
214
+ if (execvp (argv[0 ], argv) < 0 ) {
215
+ throw std::runtime_error (" exec failed " );
216
+ }
217
+ throw std::runtime_error (" child process failed " );
218
+ }
219
+ else {
220
+ close (fds[0 ]); // close read
221
+ char buffin[8192 ];
222
+ while (input.getline (buffin, sizeof (buffin))) {
223
+ size_t readn = input.gcount ();
224
+ if (write (fds[1 ], buffin, readn) == -1 ) {
225
+ throw std::runtime_error (" write failed" );
226
+ }
227
+ }
228
+ close (fds[1 ]); // close write
229
+ char buffout[8192 ];
230
+ ssize_t count;
231
+ while ((count = read (fds[1 ], buffout, sizeof (buffout))) > 0 ) {
232
+ output.write (buffout, count);
233
+ }
234
+ }
235
+ // wait(0); // wait
236
+ }
237
+
182
238
183
239
Pipeline::Pipeline (LocalisedPrefs prefs_, vector<unique_ptr<PipeCmd>> cmds_,
184
240
SuggestCmd* suggestcmd_, bool verbose_, bool trace_)
@@ -333,8 +389,14 @@ Pipeline Pipeline::mkPipeline(const unique_ptr<ArPipeSpec>& ar_spec,
333
389
suggestcmd = s;
334
390
}
335
391
else if (name == u" sh" ) {
336
- // const auto& prog = fromUtf8(cmd.attribute("prog").value());
337
- // cmds.emplace_back(new ShCmd(prog, args, verbose));
392
+ const auto & prog = cmd.attribute (" prog" ).value ();
393
+ std::vector<string> argv;
394
+ for (const pugi::xml_node& arg : cmd.children ()) {
395
+ if (strcmp (arg.name (), " arg" ) == 0 ) {
396
+ argv.push_back (arg.text ().get ());
397
+ }
398
+ }
399
+ cmds.emplace_back (new ShCmd (prog, argv, verbose));
338
400
}
339
401
else if (name == u" prefs" ) {
340
402
parsePrefs (prefs, cmd);
@@ -383,9 +445,9 @@ Pipeline Pipeline::mkPipeline(const unique_ptr<PipeSpec>& spec,
383
445
cmd.attribute (" max-weight" ).as_float (5000.0 ),
384
446
cmd.attribute (" max-unknown-rate" ).as_float (0.4 ), verbose));
385
447
#else
386
- throw std::runtime_error (
387
- " libdivvun: ERROR: Tried to run pipeline with cgspell, but was "
388
- " compiled without cgspell support!" );
448
+ throw std::runtime_error (" libdivvun: ERROR: Tried to run "
449
+ " pipeline with cgspell, but was "
450
+ " compiled without cgspell support!" );
389
451
#endif
390
452
}
391
453
else if ((name == u" normalise" ) || (name == u" normalize" )) {
@@ -423,8 +485,15 @@ Pipeline Pipeline::mkPipeline(const unique_ptr<PipeSpec>& spec,
423
485
suggestcmd = s;
424
486
}
425
487
else if (name == u" sh" ) {
426
- // const auto& prog = fromUtf8(cmd.attribute("prog").value());
427
- // cmds.emplace_back(new ShCmd(prog, args, verbose));
488
+ const auto & prog = cmd.attribute (" prog" ).value ();
489
+ std::vector<string> argv;
490
+ argv.push_back (prog);
491
+ for (const pugi::xml_node& arg : cmd.children ()) {
492
+ if (strcmp (arg.name (), " arg" ) == 0 ) {
493
+ argv.push_back (arg.text ().get ());
494
+ }
495
+ }
496
+ cmds.emplace_back (new ShCmd (prog, argv, verbose));
428
497
}
429
498
else if (name == u" prefs" ) {
430
499
parsePrefs (prefs, cmd);
@@ -491,5 +560,4 @@ void Pipeline::setIncludes(const std::set<ErrId>& includes) {
491
560
" a SuggestCmd" );
492
561
}
493
562
}
494
-
495
563
}
0 commit comments