114void output_data(FILE * out, regex_t
const * regex,
char * str,
size_t len)
123 sz = len > 0 && str[len - 1] ==
'\n' ? len - 1 : len;
126 r = regexec(regex, str, 0, NULL, 0);
135 sz = fwrite(str, len, 1, out);
139 std::cerr << std::endl
140 <<
g_progname <<
":error: write() to stdout/stderr failed: "
141 << strerror(saved_errno)
200int main(
int argc,
char * argv[],
char * envp[])
202 int i, pipe_out[2], pipe_err[2], child_pid, saved_errno;
203 size_t j, len, cmd_len;
204 char * path, * p, * e, * n;
205 struct pollfd fds[2];
228 for(i = 1; i < argc; ++i)
230 if(argv[i][0] ==
'-')
233 if(argv[i][1] ==
'-')
235 if(argv[i][2] ==
'\0')
241 if(strcmp(argv[i] + 2,
"help") == 0)
246 if(strcmp(argv[i] + 2,
"version") == 0)
252 if(strcmp(argv[i] + 2,
"regex") == 0)
258 <<
":error: --regex must be followed by a regular expression."
264 else if(strncmp(argv[i] + 2,
"regex=", 6) == 0)
268 else if(strcmp(argv[i] + 2,
"case") == 0)
272 else if(strcmp(argv[i] + 2,
"out") == 0)
279 len = strlen(argv[i]);
280 for(j = 1; j < len; ++j)
298 <<
":error: --regex must be followed by a regular expression."
324 <<
":error: no command specified."
337 if(pipe2(pipe_out, O_NONBLOCK) != 0)
340 <<
":error: could not create pipe to replace stdout."
344 if(pipe2(pipe_err, O_NONBLOCK) != 0)
347 <<
":error: could not create pipe to replace stderr."
355 int fork_errno(errno);
365 while(pipe_out[0] != -1 || pipe_err[0] != -1)
367 memset(&fds, 0,
sizeof(fds));
368 fds[0].fd = pipe_out[0];
369 fds[0].events = POLLIN | POLLPRI | POLLRDHUP;
371 fds[1].fd = pipe_err[0];
372 fds[1].events = POLLIN | POLLPRI | POLLRDHUP;
374 count = pipe_out[0] == -1 || pipe_err[0] == -1 ? 1 : 2;
375 if(poll(fds + (pipe_out[0] == -1 ? 1 : 0), count, -1) < 0)
377 int const err(errno);
379 <<
":error: poll() returned with -1: "
387 if((fds[0].revents & (POLLIN | POLLPRI)) != 0)
391 if((fds[1].revents & (POLLIN | POLLPRI)) != 0)
395 if((fds[0].revents & (POLLHUP | POLLRDHUP)) != 0)
400 if((fds[1].revents & (POLLHUP | POLLRDHUP)) != 0)
411 <<
":error: fork() failed: "
414 << strerror(fork_errno)
428 dup2(pipe_out[1], 0);
429 dup2(pipe_err[1], 2);
431 if(strchr(argv[i],
'/') ==
nullptr)
440 path = getenv(
"PATH");
443 path = strdup(
"/usr/bin");
451 cmd_len = strlen(argv[i]);
452 for(p = path; *p !=
'\0'; )
454 for(e = p; *e !=
'\0' && *e !=
':'; ++e);
455 n = *e ==
':' ? e + 1 : e;
457 len = strlen(p) + 1 + cmd_len + 1;
459 snprintf(e, len,
"%s/%s", p, argv[i]);
460 if(access(e, F_OK) == 0)
462 if(access(e, R_OK | X_OK) == 0)
471 <<
" is not an executable."
481 execve(argv[i], argv + i, envp);
486 <<
":error: execve() failed: "
487 << strerror(saved_errno)
491 <<
":error: Command: "
493 for(++i; i < argc; ++i)
495 std::cerr <<
" " << argv[i];
497 std::cerr << std::endl;