/* * Run a predicate command on data read from standard * input; print only the data for which the predicate * returns true. * * Dan Cross */ #include #include #include #include #include #include #include static void usage(char *progname); static void process(FILE *in, int argc, char *argv[]); static int probe(char *filename, int argc, char *argv[]); int seperator; int main(int argc, char *argv[]) { char **nargv; int ch, i; seperator = '\n'; while ((ch = getopt(argc, argv, "0?")) != -1) { switch (ch) { case '0': seperator = '\0'; break; case '?': default: usage(argv[0]); break; } } argc -= optind; argv += optind; nargv = malloc((argc + 2) * sizeof(char *)); memset(nargv, 0, (argc + 2) * sizeof(char *)); for (i = 0; i <= argc; i++) nargv[i] = argv[i]; nargv[argc + 1] = NULL; process(stdin, argc + 1, nargv); return(EXIT_SUCCESS); } static void process(FILE *in, int argc, char *argv[]) { char *s; char buffer[65536]; int ch; memset(buffer, 0, sizeof(buffer)); s = buffer; while ((ch = fgetc(in)) != EOF) { if ((s - buffer) >= sizeof(buffer)) { memset(buffer, 0, sizeof(buffer)); while ((ch = fgetc(in)) != EOF && ch != seperator); continue; } if (ch == seperator) { *s = '\0'; if (probe(buffer, argc, argv)) { write(STDOUT_FILENO, buffer, s - buffer); write(STDOUT_FILENO, &seperator, 1); } memset(buffer, 0, sizeof(buffer)); s = buffer; } else *s++ = ch; } if (ferror(in)) perror("read"); } static int probe(char *s, int argc, char *argv[]) { pid_t pid; int status; status = 0; argv[argc - 1] = s; pid = vfork(); if (pid < 0) { perror("fork"); exit(EXIT_FAILURE); } else if (pid == 0) { execvp(*argv, argv); perror("execvp"); _exit(EXIT_FAILURE); } else { if (waitpid(pid, &status, 0) < 0) perror("waitpid"); } return(status == 0); } static void usage(char *progname) { fprintf(stderr, "Usage: %s [ -0 ].\n", progname); exit(EXIT_FAILURE); }