diff --git a/TODO b/TODO index e3a87da..8f9e382 100644 --- a/TODO +++ b/TODO @@ -50,6 +50,5 @@ BUGS: FIX: ps - head echo (escape) que (unicode) diff --git a/src/coreutils/head/head.c b/src/coreutils/head/head.c index 92110a8..3a8d776 100644 --- a/src/coreutils/head/head.c +++ b/src/coreutils/head/head.c @@ -10,46 +10,102 @@ char v_flag; char c_flag; +char n_flag; long parse_long(const char *str) { char *ptr; long ret = strtol(str, &ptr, 0); if (*ptr) { - fprintf(stderr, "head: %s invalid number\n", ptr); + fprintf(stderr, "head: invalid number %s\n", ptr); exit(1); } return ret; } -void print(const char *file, FILE *fp, long lines, long bytes) { +int print(const char *file, FILE *fp, long lines, long bytes) { if (v_flag) printf(HEAD_FMT, file); long lcount = 0; long bcount = 0; - while (1) { - int c = getc(fp); - bcount++; - if (c == '\n') - lcount++; + /* If lines or bytes < 0 */ + if (lines < 0 || bytes < 0) { + long lmax = 0; + long bmax = 0; - if (c == EOF || lcount == lines || (c_flag && bcount == bytes)) - break; + size_t buf_size = 0; + char *buf = malloc(1); + if (buf == NULL) { + fprintf(stderr, "head: malloc: %s\n", strerror(errno)); + return 1; + } - putchar(c); + while (1) { + int c = getc(fp); + if (c == EOF) + break; + + char *tmp = realloc(buf, buf_size + 2); + if (tmp == NULL) { + fprintf(stderr, "head: realloc: %s\n", strerror(errno)); + + free(buf); + return 1; + } + + buf = tmp; + buf[buf_size] = c; + if (c == '\n') + lmax++; + bmax++; + buf_size++; + } + + buf[buf_size] = '\0'; + + for (size_t i = 0; i < buf_size; i++) { + if (buf[i] == '\n') + lcount++; + + bcount++; + putchar(buf[i]); + if ((n_flag && lcount == lmax + lines) || (c_flag && bcount == bmax + bytes)) + break; + } + + free(buf); } + + else { + while (1) { + int c = getc(fp); + if (c == EOF) + break; + + if (c == '\n') + lcount++; + bcount++; + putchar(c); + + if ((n_flag && lcount == lines) || (c_flag && bcount == bytes)) + break; + } + } + + return 0; } int main(int argc, char **argv) { - long lines = 10; + long lines = 0; long bytes = 0; int opt; while ((opt = getopt(argc, argv, "n:c:v")) != -1) { switch (opt) { case 'n': + n_flag = 1; lines = parse_long(optarg); break; @@ -63,7 +119,7 @@ int main(int argc, char **argv) { break; default: - printf("head [ncv] [file1 file2...]\n\t-n Print N lines\n\t-c Print N bytes\n\t-v Print headers\n"); + printf("head [ncv] [file1 file2...]\n\t-n Print [-]N lines\n\t-c Print [-]N bytes\n\t-v Print headers\n"); return 0; } } @@ -74,6 +130,7 @@ int main(int argc, char **argv) { if (argc == 0) print("-", stdin, lines, bytes); + int ret = 0; for (int i = 0; i < argc; i++) { FILE *fp = NULL; if (argv[i][0] == '-') @@ -84,10 +141,14 @@ int main(int argc, char **argv) { if (fp == NULL) { fprintf(stderr, "head: %s: %s\n", argv[i], strerror(errno)); - return 1; + + ret = 1; + continue; } - print(argv[i], fp, lines, bytes); + if (print(argv[i], fp, lines, bytes)) + ret = 1; + fclose(fp); }