Viewing: grep.c
📄 grep.c (Read Only) ⬅ To go back
/* AdrOS grep utility — search for pattern in files */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>

static int match_simple(const char* text, const char* pat) {
    /* Simple substring match (no regex) */
    return strstr(text, pat) != NULL;
}

static int grep_fd(int fd, const char* pattern, const char* fname, int show_name, int invert, int count_only, int line_num) {
    char buf[4096];
    int pos = 0, n, matches = 0, lnum = 0;
    while ((n = read(fd, buf + pos, (size_t)(sizeof(buf) - 1 - pos))) > 0) {
        pos += n;
        buf[pos] = '\0';
        char* start = buf;
        char* nl;
        while ((nl = strchr(start, '\n')) != NULL) {
            *nl = '\0';
            lnum++;
            int m = match_simple(start, pattern);
            if (invert) m = !m;
            if (m) {
                matches++;
                if (!count_only) {
                    if (show_name) printf("%s:", fname);
                    if (line_num) printf("%d:", lnum);
                    printf("%s\n", start);
                }
            }
            start = nl + 1;
        }
        int rem = (int)(buf + pos - start);
        if (rem > 0) memmove(buf, start, (size_t)rem);
        pos = rem;
    }
    if (pos > 0) {
        buf[pos] = '\0';
        lnum++;
        int m = match_simple(buf, pattern);
        if (invert) m = !m;
        if (m) {
            matches++;
            if (!count_only) {
                if (show_name) printf("%s:", fname);
                if (line_num) printf("%d:", lnum);
                printf("%s\n", buf);
            }
        }
    }
    if (count_only) printf("%s%s%d\n", show_name ? fname : "", show_name ? ":" : "", matches);
    return matches > 0 ? 0 : 1;
}

int main(int argc, char** argv) {
    int invert = 0, count_only = 0, line_num = 0;
    int i = 1;
    while (i < argc && argv[i][0] == '-') {
        for (int j = 1; argv[i][j]; j++) {
            if (argv[i][j] == 'v') invert = 1;
            else if (argv[i][j] == 'c') count_only = 1;
            else if (argv[i][j] == 'n') line_num = 1;
        }
        i++;
    }
    if (i >= argc) { fprintf(stderr, "usage: grep [-vcn] PATTERN [FILE...]\n"); return 2; }
    const char* pattern = argv[i++];
    if (i >= argc) return grep_fd(STDIN_FILENO, pattern, "(stdin)", 0, invert, count_only, line_num);
    int rc = 1, nfiles = argc - i;
    for (; i < argc; i++) {
        int fd = open(argv[i], O_RDONLY);
        if (fd < 0) { fprintf(stderr, "grep: %s: No such file or directory\n", argv[i]); continue; }
        if (grep_fd(fd, pattern, argv[i], nfiles > 1, invert, count_only, line_num) == 0) rc = 0;
        close(fd);
    }
    return rc;
}