From 1e23aa5bddb1459a172367bf363b105f2f0e3bac Mon Sep 17 00:00:00 2001 From: girst Date: Fri, 28 Jul 2017 03:11:39 +0200 Subject: [PATCH] grep now accepts some arguments 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 | 72 ++++++++++++++++++++++++++++++++++++++--------------------- fag.h | 16 ++++++++++++- 2 files changed, 62 insertions(+), 26 deletions(-) diff --git a/fag.c b/fag.c index 80f5c2a..725722a 100644 --- 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 @@ -15,14 +14,14 @@ #include #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 80d0118..374dd26 100644 --- 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 -- 2.39.3