]>
git.gir.st - forkaftergrep.git/blob - fag.c
1 /* forkaftergrep (C) 2017 Tobias Girstmair, GPLv3 */
3 #define _XOPEN_SOURCE 500
4 #define _DEFAULT_SOURCE
16 struct opt opts
= {0, 0, 0, NULL
, NULL
, STDOUT_FILENO
};
18 int main (int argc
, char** argv
) {
22 /* the `+' forces getopt to stop at the first non-option */
23 while ((opt
= getopt (argc
, argv
, "+t:k::eVhv")) != -1) {
26 opts
.timeout
= atoi (optarg
);
29 opts
.kill_sig
= optarg
? atoi (optarg
) : SIGTERM
;
32 opts
.stream
= STDERR_FILENO
;
38 fprintf (stderr
, VERTEXT USAGE
40 "\t-t N\ttimeout after N seconds\n"
41 "\t-k [M]\tsend signal M to child after timeout (default: 15/SIGTERM)\n"
42 "\t-e\tgrep on stderr instead of stdout\n", argv
[0]);
45 fprintf (stderr
, VERTEXT
);
48 fprintf (stderr
, "Unrecognized option: %c\n" USAGE
, optopt
, argv
[0]);
53 /* the first non-option argument is the search string */
55 opts
.pattern
= argv
[optind
++];
57 fprintf (stderr
, USAGE
"(Missing PATTERN)\n", argv
[0]);
61 /* the remaining are the program to be run */
63 opts
.argv
= &(argv
[optind
]);
65 fprintf (stderr
, USAGE
"(Missing PROGRAM)\n", argv
[0]);
69 int retval
= fork_after_grep (opts
);
74 int fork_after_grep (struct opt opts
) {
82 struct timeval begin
, now
, diff
;
84 if (pipe(pipefd
) == -1) {
85 fprintf (stderr
, "pipe error\n");
89 if ((cpid
= fork()) == -1) {
90 fprintf (stderr
, "fork error: %s", strerror (errno
));
98 dup2 (pipefd
[1], opts
.stream
);
100 close (opts
.stream
==STDOUT_FILENO
?STDERR_FILENO
:STDOUT_FILENO
);
102 if (setsid () == -1) {
103 fprintf (stderr
, "setsid error: %s", strerror (errno
));
107 execvp (opts
.argv
[0], opts
.argv
);
108 fprintf (stderr
, "exec error: %s", strerror (errno
));
109 _exit (EX_UNAVAILABLE
);
113 //char grep_buf[BUF_SIZE];
115 //char* grepargv[] = {"cat", NULL};
116 char* grepargv
[] = {"grep", opts
.pattern
, NULL
};//"-E", //TODO: supply params (-E, -P, etc.) to grep from command line
119 fcntl (pipefd
[0], F_SETFL
, fcntl (pipefd
[0], F_GETFL
, 0) | O_NONBLOCK
);
121 gettimeofday (&begin
, NULL
);
123 if (pipe(grep_pipefd
) == -1) {
124 fprintf (stderr
, "mygrep - pipe error\n");
127 if ((grep_cpid
= fork()) == -1) {
128 fprintf (stderr
, "mygrep - fork error: %s", strerror (errno
));
133 if (grep_cpid
== 0) {
134 close(grep_pipefd
[1]);
135 dup2(grep_pipefd
[0], STDIN_FILENO
);
136 close(grep_pipefd
[0]);
137 close(STDERR_FILENO
);
138 execvp (grepargv
[0], grepargv
);
139 fprintf (stderr
, "mygrep - exec error: %s", strerror (errno
));
140 _exit (EX_UNAVAILABLE
);
144 memset (buf
, 0, BUF_SIZE
);
145 nbytes
= read (pipefd
[0], buf
, BUF_SIZE
);
151 fprintf (stderr
, "read error: %s", strerror (errno
));
156 } else if (nbytes
== 0) {
157 fprintf (stderr
, "Child program exited prematurely.\n");
160 if (waitpid (cpid
, &status
, WNOHANG
) > 0 && WIFEXITED (status
)) {
161 return WEXITSTATUS (status
);
163 return EX_UNAVAILABLE
;
166 fputs (buf
, opts
.stream
==STDERR_FILENO
?stderr
:stdout
);
168 write(grep_pipefd
[1], buf
, strlen(buf
));/*************/
169 if (strstr (buf
, opts
.pattern
) != NULL
) {
170 printf ("%d\n", cpid
);
171 /* create a new child to keep pipe alive (will exit with exec'd program) */
173 while (kill(cpid
, 0) != -1 && errno
!= ESRCH
) sleep (1);
183 if (opts
.timeout
> 0) {
184 gettimeofday (&now
, NULL
);
185 timersub (&now
, &begin
, &diff
);
186 if (diff
.tv_sec
>= opts
.timeout
) {
187 fprintf (stderr
, "Timeout reached. \n");
188 if (opts
.kill_sig
> 0) kill (cpid
, opts
.kill_sig
);
191 return EX_UNAVAILABLE
;