Viewing: tail.c
📄 tail.c (Read Only) ⬅ To go back
/* AdrOS tail utility */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define TAIL_BUFSZ 8192

static void tail_fd(int fd, int nlines) {
    /* Read entire file into buffer, then print last N lines */
    char buf[TAIL_BUFSZ];
    int total = 0;
    int r;
    while ((r = read(fd, buf + total, (size_t)(TAIL_BUFSZ - total))) > 0) {
        total += r;
        if (total >= TAIL_BUFSZ) break;
    }

    /* Count newlines from end; skip trailing newline */
    int count = 0;
    int pos = total;
    if (pos > 0 && buf[pos - 1] == '\n') pos--;
    while (pos > 0 && count < nlines) {
        pos--;
        if (buf[pos] == '\n') count++;
    }
    if (pos > 0 || (pos == 0 && buf[0] == '\n')) pos++;

    write(STDOUT_FILENO, buf + pos, (size_t)(total - pos));
}

int main(int argc, char** argv) {
    int nlines = 10;
    int start = 1;

    if (argc > 1 && argv[1][0] == '-' && argv[1][1] == 'n' && argc > 2) {
        nlines = atoi(argv[2]);
        start = 3;
    } else if (argc > 1 && argv[1][0] == '-' && argv[1][1] >= '0' && argv[1][1] <= '9') {
        nlines = atoi(argv[1] + 1);
        start = 2;
    }

    if (start >= argc) {
        tail_fd(STDIN_FILENO, nlines);
    } else {
        for (int i = start; i < argc; i++) {
            if (argc - start > 1) printf("==> %s <==\n", argv[i]);
            int fd = open(argv[i], O_RDONLY);
            if (fd < 0) {
                fprintf(stderr, "tail: cannot open '%s'\n", argv[i]);
                continue;
            }
            tail_fd(fd, nlines);
            close(fd);
        }
    }
    return 0;
}