2 * "THE BEER-WARE LICENSE" (Revision 42):
3 * <tobias.rehbein@web.de> wrote this file. As long as you retain this notice
4 * you can do whatever you want with this stuff. If we meet some day, and you
5 * think this stuff is worth it, you can buy me a beer in return.
19 #include <sys/types.h>
26 static void fork_you(struct opt_options
*opts
, struct chk_context
*ctx
);
27 static void free_conditions(struct chk_conditions
*cond
);
28 static struct chk_conditions
*get_conditions(struct opt_options
*opts
);
29 static void process_loop(struct opt_options
*opts
, struct chk_context
*ctx
, bool doflush
);
30 static void remove_trailing_slashes(char *path
);
31 static int use_pipe(int *p
);
32 static void wait_for_childs(void);
35 main(int argc
, char **argv
)
38 if (setlocale(LC_ALL
, "") == NULL
)
39 errx(EXIT_FAILURE
, "setlocale LC_ALL");
41 /* setup environment */
42 struct opt_options
*opts
= opt_get_options(argc
, argv
);
44 err(EXIT_FAILURE
, "opt_get_options");
45 struct chk_conditions
*cond
= get_conditions(opts
);
47 err(EXIT_FAILURE
, "get_conditions");
48 struct chk_context
*ctx
= chk_context_open(cond
);
50 err(EXIT_FAILURE
, "chk_context_open");
52 /* enter main loop or fork away */
53 if (opts
->processes
<= 1)
54 process_loop(opts
, ctx
, false);
58 /* free all resources */
59 chk_context_close(ctx
);
60 free_conditions(cond
);
61 opt_free_options(opts
);
66 static struct chk_conditions
*
67 get_conditions(struct opt_options
*opts
)
71 struct chk_conditions
*cond
= malloc(sizeof(*cond
));
75 chk_init_conditions(cond
);
77 cond
->min_length
= opts
->min_length
;
78 cond
->max_length
= opts
->max_length
;
79 cond
->min_bitrate
= opts
->min_bitrate
;
80 cond
->max_bitrate
= opts
->max_bitrate
;
81 cond
->noignorecase
= opts
->noignorecase
;
83 for (struct element
*oe
= opts
->expressionlist
; oe
!= NULL
; oe
= oe
->next
) {
84 struct chk_expression
*cx
= malloc(sizeof(*cx
));
86 err(EXIT_FAILURE
, "malloc chk_expression");
88 struct opt_expression
*ox
= oe
->payload
;
89 cx
->expression
= ox
->expression
;
90 cx
->invert
= ox
->invert
;
93 if ((ce
= create_element(cx
)) == NULL
)
94 err(EXIT_FAILURE
, "create_element");
96 cond
->regexlist
= prepend_element(ce
, cond
->regexlist
);
103 free_conditions(struct chk_conditions
*cond
)
105 assert(cond
!= NULL
);
107 for (struct element
*e
= cond
->regexlist
; e
!= NULL
; e
= destroy_element(e
))
114 process_loop(struct opt_options
*opts
, struct chk_context
*ctx
, bool doflush
)
116 assert(opts
!= NULL
);
119 char pathread
[LINE_MAX
];
120 while (fgets(pathread
, LINE_MAX
, stdin
) != NULL
) {
121 char *newline
= NULL
;
122 if ((newline
= strchr(pathread
, '\n')) != NULL
)
125 char *path
= malloc(LINE_MAX
);
127 err(EXIT_FAILURE
, "malloc path");
129 char *pathprefix
= NULL
;
130 if (opts
->pathprefix
!= NULL
) {
131 pathprefix
= strdup(opts
->pathprefix
);
132 if (pathprefix
== NULL
)
133 err(EXIT_FAILURE
, "strdup pathprefix");
134 remove_trailing_slashes(pathprefix
);
136 if (pathprefix
!= NULL
&& pathread
[0] != '/')
137 snprintf(path
, LINE_MAX
, "%s/%s", pathprefix
, pathread
);
139 strncpy(path
, pathread
, LINE_MAX
- 2);
140 path
[LINE_MAX
- 1] = '\0';
144 bool check_result
= chk_check_file(path
, ctx
);
145 if (check_result
^ opts
->invert
) {
158 err(EXIT_FAILURE
, "fgets stdin");
162 remove_trailing_slashes(char *path
)
164 assert(path
!= NULL
);
166 char *n
= strchr(path
, (int)'\0');
168 while (*n
!= path
[0] && *(--n
) == '/')
173 fork_you(struct opt_options
*opts
, struct chk_context
*ctx
)
175 assert(opts
!= NULL
);
178 int *fds
= malloc(opts
->processes
* sizeof(int));
180 err(EXIT_FAILURE
, "malloc fds");
182 for (int i
= 0; i
< opts
->processes
; i
++) {
185 err(EXIT_FAILURE
, "pipe %d", i
);
190 err(EXIT_FAILURE
, "fork %d", i
);
193 /* close all write ends opened until now */
194 for (int j
= 0; j
< i
; j
++)
195 if (close(fds
[j
]) == -1)
196 warn("close %d, %d", i
, j
);
199 if (use_pipe(p
) == -1)
200 errx(EXIT_FAILURE
, "use_pipe %d", i
);
202 process_loop(opts
, ctx
, true);
207 * close the read end of pipe and store write end for
210 if (close(p
[0]) == -1)
216 char pathread
[LINE_MAX
];
218 while (fgets(pathread
, LINE_MAX
, stdin
) != NULL
)
219 if (write(fds
[fd
++ % opts
->processes
], pathread
, strlen(pathread
)) == -1)
222 err(EXIT_FAILURE
, "fgets stdin");
224 for (int i
= 0; i
< opts
->processes
; i
++)
225 if (close(fds
[i
]) == -1)
238 /* close write end of pipe and stdin of process */
239 if (close(p
[1]) == -1)
241 if (fclose(stdin
) == EOF
)
244 /* use the read end of pipe as stdin */
245 if ((dup2(p
[0], STDIN_FILENO
)) == -1)
247 if ((stdin
= fdopen(STDIN_FILENO
, "r")) == NULL
)
258 while ((pid
= wait(&sts
)) != -1)
259 if (WIFEXITED(sts
) && WEXITSTATUS(sts
) != 0)
260 warn("child process %d exited abnormally: %d", pid
, sts
);