Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Allow pipes in commands #7

Closed
wants to merge 2 commits into from

2 participants

@theomega

The current implementation does not allow to specify pipes as commands.

So watch 'ls | grep txt' fails, even worse without a clear error-message:

waitpid(): No child processes
exit: 1

This comes from the fact that the old watch implementation uses the system function to execute the commands. This function uses a shell which handles the pipes. execvp does not support pipes in its commands, you would have to set them up by yourself.

The following patch changes some things:

  • Per default execute thru system
  • Add a -x/--exec flag which switches back to the old behaviour
  • Output a correct error-message on execvp errors.

This makes watch more usable and more compliant to the original implementation.

@tj
Owner
tj commented

haha good call with system, I didn't even think about pipelines for some reason. I'll check it out tomorrow

@tj tj closed this pull request from a commit
@tj Added sh -c support. Closes #7 be22d2a
@tj tj closed this in be22d2a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 48 additions and 6 deletions.
  1. +1 −1  Makefile
  2. +47 −5 src/watch.c
View
2  Makefile
@@ -1,5 +1,5 @@
-CFLAGS = -std=c99 -D_POSIX_C_SOURCE=199309L -Wall -pedantic
+CFLAGS = -std=c99 -D_POSIX_C_SOURCE=200809L -Wall -pedantic
PREFIX = /usr/local
watch: src/watch.c
View
52 src/watch.c
@@ -38,6 +38,12 @@
static int quiet = 0;
/*
+ * Use exec instead of system
+ */
+
+static int exec = 0;
+
+/*
* Output command usage.
*/
@@ -51,6 +57,7 @@ usage() {
"\n"
" -q, --quiet only output stderr\n"
" -i, --interval <n> interval in seconds or ms defaulting to 1\n"
+ " -x, --exec use exec instead of giving the cmd to 'sh -x'\n"
" -V, --version output version number\n"
" -h, --help output this help information\n"
"\n"
@@ -116,27 +123,29 @@ main(int argc, const char **argv){
int len = 0;
char *args[ARGS_MAX];
+ unsigned int parseOptions = 1;
+
for (int i = 1; i < argc; ++i) {
const char *arg = argv[i];
// -h, --help
- if (option("-h", "--help", arg)) usage();
+ if (parseOptions && option("-h", "--help", arg)) usage();
// -q, --quiet
- if (option("-q", "--quiet", arg)) {
+ if (parseOptions && option("-q", "--quiet", arg)) {
quiet = 1;
continue;
}
// -V, --version
- if (option("-v", "--version", arg)) {
+ if (parseOptions && option("-v", "--version", arg)) {
printf("%s\n", VERSION);
exit(1);
}
// -i, --interval <n>
- if (option("-i", "--interval", arg)) {
+ if (parseOptions && option("-i", "--interval", arg)) {
if (argc-1 == i) {
fprintf(stderr, "\n --interval requires an argument\n\n");
exit(1);
@@ -150,6 +159,12 @@ main(int argc, const char **argv){
continue;
}
+ // -x, --exec
+ if (parseOptions && option("-x", "--exec", arg)) {
+ exec = 1;
+ continue;
+ }
+
// cmd args
if (len == ARGS_MAX) {
fprintf(stderr, "number of arguments exceeded %d\n", len);
@@ -157,6 +172,7 @@ main(int argc, const char **argv){
}
args[len++] = (char *) arg;
+ parseOptions = 0;
}
// <cmd>
@@ -168,6 +184,19 @@ main(int argc, const char **argv){
// null
args[len] = 0;
+ // Assemble command
+ char *command = strdup(args[0]);
+ int command_length = strlen(command);
+ for (int i=1; i < len; i++) {
+ int plen = strlen(args[i]);
+ command = realloc(command, command_length + plen + 2);
+ char *endp = command + command_length;
+ *endp = ' ';
+ memcpy(endp + 1, args[i], plen);
+ command_length += 1 + plen;
+ command[command_length] = '\0';
+ }
+
// exec loop
loop: {
pid_t pid;
@@ -180,7 +209,20 @@ main(int argc, const char **argv){
// child
case 0:
if (quiet) redirect_stdout("/dev/null");
- execvp(args[0], args);
+ if (exec) {
+ if(execvp(args[0], args)==-1) {
+ perror("exec");
+ exit(4);
+ }
+ } else {
+ int sysresult=system(command);
+ if (!WIFEXITED(sysresult)) { /* child exits nonzero if command does */
+ exit(1);
+ } else {
+ exit(WEXITSTATUS(sysresult));
+ }
+ }
+
// parent
default:
if (waitpid(pid, &status, 0) < 0) {
Something went wrong with that request. Please try again.