grep now accepts some arguments
authorgirst <girst@users.noreply.github.com>
Fri, 28 Jul 2017 01:11:39 +0000 (03:11 +0200)
committergirst <girst@users.noreply.github.com>
Fri, 28 Jul 2017 01:11:39 +0000 (03:11 +0200)
you can use grep options -E, -F, -G, -P, -i, -w, -x, -y, and -U now.
these are the only ones that make sense (to me at least) to include
besides -e (multiple patterns) and -f (patterns from file).

fag.c
fag.h

diff --git a/fag.c b/fag.c
index 80f5c2a1b11e209fc463356843b3aacc7f55ea1e..725722a40a08a52f0886a6faf2dfaca5c0d78a3d 100644 (file)
--- a/fag.c
+++ b/fag.c
@@ -1,6 +1,5 @@
 /* forkaftergrep (C) 2017 Tobias Girstmair, GPLv3 */
-//TODO: supply user arguments to grep
-//demo: ./fag -e -V "MPD server running at" mopidy
+//TODO: EX_UNAVAILABLE is wrongly used three times
 
 #define _XOPEN_SOURCE 500
 #define _DEFAULT_SOURCE
 #include <unistd.h>
 #include "fag.h"
 
-struct opt opts = {0, 0, 0, NULL, NULL, STDOUT_FILENO};
-
 int main (int argc, char** argv) {
+       struct opt opts = {0, 0, 0, NULL, NULL, STDOUT_FILENO};
+       struct grepopt optg = {basic_regexp, 0, 0, 0, 0};
        int opt;
        opterr = 0;
 
        /* the `+' forces getopt to stop at the first non-option */
-       while ((opt = getopt (argc, argv, "+t:k::eVhv")) != -1) {
+       while ((opt = getopt (argc, argv, "+t:k::eVhvEFGPiwxyU")) != -1) {
                switch (opt) {
                case 't':
                        opts.timeout = atoi (optarg);
@@ -47,6 +46,17 @@ int main (int argc, char** argv) {
                case 'v':
                        fprintf (stderr, VERTEXT);
                        return EX_OK;
+               /* `grep' options (Note: missing `-e:', `-f:') */
+               case 'E': optg.regex = extended_regexp; break;
+               case 'F': optg.regex = fixed_strings  ; break;
+               case 'G': optg.regex = basic_regexp   ; break; /* default */
+               case 'P': optg.regex = perl_regexp    ; break;
+               case 'i': /* fall thru */
+               case 'y': optg.ignore_case = 1; break;
+               case 'w': optg.word_regexp = 1; break;
+               case 'x': optg.line_regexp = 1; break;
+               case 'U': optg.binary      = 1; break;
+
                default: 
                        fprintf (stderr, "Unrecognized option: %c\n" USAGE, optopt, argv[0]);
                        return EX_USAGE;
@@ -69,12 +79,12 @@ int main (int argc, char** argv) {
                return EX_USAGE;
        }
 
-       int retval = fork_after_grep (opts);
+       int retval = fork_after_grep (opts, optg);
 
        return retval;
 }
 
-int fork_after_grep (struct opt opts) {
+int fork_after_grep (struct opt opts, struct grepopt optg) {
        int pipefd[2];
        pid_t cpid;
        int status;
@@ -112,17 +122,15 @@ int fork_after_grep (struct opt opts) {
                _exit (EX_UNAVAILABLE);
        } else {
                pid_t grep_cpid;
-               int pipefd_togrep[2];
+               int grep_pipefd[2];
                int grep_status;
-               /* `-q': don't print anything; exit with 0 on match; with 1 on error */
-               char* grepargv[] = {"grep", "-q", opts.pattern, NULL};
 
                close (pipefd[1]);
                fcntl (pipefd[0], F_SETFL, fcntl (pipefd[0], F_GETFL, 0) | O_NONBLOCK);
 
                gettimeofday (&begin, NULL); /* for timeout */
 
-               if (pipe(pipefd_togrep) == -1) {
+               if (pipe(grep_pipefd) == -1) {
                        fprintf (stderr, "pipe error (grep)\n");
                        close (pipefd[0]);
                        close (pipefd[1]);
@@ -133,27 +141,40 @@ int fork_after_grep (struct opt opts) {
                        fprintf (stderr, "fork error (grep): %s", strerror (errno));
                        close (pipefd[0]);
                        close (pipefd[1]);
-                       close (pipefd_togrep[0]);
-                       close (pipefd_togrep[1]);
+                       close (grep_pipefd[0]);
+                       close (grep_pipefd[1]);
                        return EX_OSERR;
                }
 
                if (grep_cpid == 0) {
-                       close (pipefd_togrep[1]);
-                       dup2 (pipefd_togrep[0], STDIN_FILENO);
-                       close (pipefd_togrep[0]);
+                       close (grep_pipefd[1]);
+                       dup2 (grep_pipefd[0], STDIN_FILENO);
+                       close (grep_pipefd[0]);
 
                        close (STDERR_FILENO);
                        close (STDOUT_FILENO);
 
-                       execvp (grepargv[0], grepargv);
+                       /* generate argument list on the fly (TODO: ugly) */
+                       /* `-q': don't print anything; exit with 0 on match; with 1 on error */
+                       char grep_options[16] = "-q";
+                       char* p = grep_options+2;
+                       if (optg.regex == extended_regexp) *(p++)='E';
+                       if (optg.regex == fixed_strings)   *(p++)='F';
+                       if (optg.regex == basic_regexp)    *(p++)='G';
+                       if (optg.regex == perl_regexp)     *(p++)='P';
+                       if (optg.ignore_case)              *(p++)='i';
+                       if (optg.word_regexp)              *(p++)='w';
+                       if (optg.line_regexp)              *(p++)='x';
+                       if (optg.binary)                   *(p++)='U';
+                       *p = '\0';
+
+                       execlp ("grep", "grep", grep_options, opts.pattern, NULL);
                        fprintf (stderr, "exec error (grep): %s", strerror (errno));
                        _exit (EX_UNAVAILABLE);
                } else {
-                       close (pipefd_togrep[0]);
+                       close (grep_pipefd[0]);
                        for (;;) {
                                usleep (20000);
-                               memset (buf, 0, BUF_SIZE); /* necessary for opts.verbose */
                                nbytes = read (pipefd[0], buf, BUF_SIZE);
                                if (nbytes == -1) {
                                        switch (errno) {
@@ -163,7 +184,7 @@ int fork_after_grep (struct opt opts) {
                                                fprintf (stderr, "read error (userprog): %s", strerror (errno));
                                                close (pipefd[0]);
                                                close (pipefd[1]);
-                                               close (pipefd_togrep[1]);
+                                               close (grep_pipefd[1]);
                                                //TODO: kill grep?
                                                return EX_IOERR;
                                        }
@@ -171,7 +192,7 @@ int fork_after_grep (struct opt opts) {
                                        fprintf (stderr, "Child program exited prematurely (userprog).\n");
                                        close (pipefd[0]);
                                        close (pipefd[1]);
-                                       close (pipefd_togrep[1]);
+                                       close (grep_pipefd[1]);
                                        //TODO: kill grep?
                                        if (waitpid (cpid, &status, WNOHANG) > 0 && WIFEXITED (status)) {
                                                return WEXITSTATUS (status);
@@ -181,13 +202,14 @@ int fork_after_grep (struct opt opts) {
                                        /* have new userprog-data, send it to grep */
                                        if (opts.verbose) {
                                                fputs (buf, stderr);
+                                               write(STDERR_FILENO, buf, nbytes);
                                        }
 
-                                       write(pipefd_togrep[1], buf, strlen(buf));
+                                       write(grep_pipefd[1], buf, nbytes);
                                }
 
                                if (waitpid (grep_cpid, &grep_status, WNOHANG) > 0 && WIFEXITED (grep_status)) {
-                                       close (pipefd_togrep[1]);
+                                       close (grep_pipefd[1]);
 
                                        if (WEXITSTATUS(grep_status) == 0) {
                                                /* grep exited with match found */
@@ -208,7 +230,7 @@ int fork_after_grep (struct opt opts) {
                                                fprintf (stderr, "grep exited due to an error.");
                                                close (pipefd[0]);
                                                close (pipefd[1]);
-                                               close (pipefd_togrep[1]);
+                                               close (grep_pipefd[1]);
                                                return EX_IOERR;
                                        }
                                }
@@ -221,7 +243,7 @@ int fork_after_grep (struct opt opts) {
                                                if (opts.kill_sig > 0) kill (cpid, opts.kill_sig);
                                                close (pipefd[0]);
                                                close (pipefd[1]);
-                                               close (pipefd_togrep[1]);
+                                               close (grep_pipefd[1]);
                                                //TODO: kill grep?
                                                return EX_UNAVAILABLE;
                                        }
diff --git a/fag.h b/fag.h
index 80d0118d3d728e864b21ac693a98f449b5f098d1..374dd263dcc5b864d2bb3417e0e847c9adae842d 100644 (file)
--- a/fag.h
+++ b/fag.h
@@ -21,6 +21,20 @@ struct opt {
        int stream;
 };
 
-int fork_after_grep (struct opt opts);
+enum grep_regex {
+       basic_regexp,
+       extended_regexp,
+       fixed_strings,
+       perl_regexp,
+};
+struct grepopt {
+       enum grep_regex regex;
+       int ignore_case;
+       int word_regexp;
+       int line_regexp;
+       int binary;
+};
+
+int fork_after_grep (struct opt opts, struct grepopt optg);
 
 #endif
Imprint / Impressum