#include #include #include #include #include #include #include struct file { FILE *file; char *filename; } file_t; bool show_filenames = false; bool invert_match = false; bool line_number = false; bool ignore_case = false; bool extended_regex = false; int usage() { printf("Usage: %s [OPTION]... PATTERNS [FILE]...\n", "grep"); printf("Try '%s --help' for more information.\n", "grep"); return 2; } int main(int argc, char *argv[]) { struct file **infiles = malloc(sizeof(FILE)); infiles[0] = malloc(sizeof(FILE)); infiles[0]->file = stdin; int files_index = 0; char **regex = malloc(sizeof(char*)); regex[0] = NULL; int regex_index = 0; int opt; char line[256]; if (argc < 2) { return usage(); } else { while ((opt = getopt(argc, argv, "::e:vniyE")) != -1) { switch (opt) { case 'v': invert_match = true; break; case 'n': line_number = true; break; case 'i': case 'y': ignore_case = true; break; case 'E': extended_regex = true; break; case 'e': regex[regex_index] = malloc(strlen(optarg)); regex[regex_index] = optarg; regex_index++; break; case '?': printf("%s: invalid option -- '%c'\n", "grep", optopt); return usage(); } } for (; optind < argc; optind++) { if (regex[0] == NULL) { regex[0] = malloc(strlen(argv[optind])); regex[0] = argv[optind]; regex_index++; } else { if (strcmp(argv[optind], "-")) { infiles[files_index] = malloc(sizeof(FILE) + strlen(argv[optind])); infiles[files_index]->file = fopen(argv[optind], "r"); infiles[files_index]->filename = argv[optind]; if (infiles[files_index]->file == NULL) { perror(argv[optind]); return -1; } } else { infiles[files_index] = malloc(sizeof(FILE) + strlen("(standard input)")); infiles[files_index]->file = stdin; infiles[files_index]->filename = "(standard input)"; } files_index++; } } } if (files_index > 1) { show_filenames = true; } int curline = 1; int i = 0; int j = 0; int cur_line_has_regex = 1; int regflags = 0; if (extended_regex) { regflags |= REG_EXTENDED; } if (ignore_case) { regflags |= REG_ICASE; } regex_t exp; regmatch_t matches[1]; do { while (fgets(line, sizeof line, infiles[i]->file) != NULL) { do { regcomp(&exp, regex[j], regflags); cur_line_has_regex = regexec(&exp, line, 1, matches, 0); if (cur_line_has_regex == 0 && !invert_match) { curline++; if (line_number) printf("%d:", curline); if (show_filenames) { printf("%s:%s", infiles[i]->filename, line); } else { printf("%s", line); } } else if (cur_line_has_regex != 0 && invert_match) { curline++; if (line_number) printf("%d:", curline); if (show_filenames) { printf("%s:%s", infiles[i]->filename, line); } else { printf("%s", line); } } j++; regfree(&exp); } while (j < regex_index); j = 0; } i++; } while (i < files_index); free(infiles); }