diff options
-rw-r--r-- | src/staart.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/staart.c b/src/staart.c new file mode 100644 index 0000000..c2d65f3 --- /dev/null +++ b/src/staart.c @@ -0,0 +1,101 @@ +#include <assert.h> +#include <getopt.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> + +#include "io/read_file.h" +#include "util/debug.h" +#include "util/error.h" +#include "util/loop_files.h" +#include "util/versie.h" + +static int gn, gc; + +static void usage(FILE *f) { + fprintf(f, + "Gebruik: staart [-nchV] [BESTAND]...\n" + "\n" + "Toon de laatste 10 regels van elk BESTAND naar standaard uitvoer\n" + "\n" + " -n AANTAL Aantal regels om weer te geven\n" + " -c AANTAL Aantal karakters om weer te geven\n" + " -h Toon deze hulptekst\n" + " -V Toon versienummer\n"); +} + +// Returns pointer to argument array containing the file names +static char** parse_options(int argc, char **argv, int *n, int *c) { + int opt; + while ((opt = getopt(argc, argv, "n:c:hV")) != -1) { + switch (opt) { + case 'c': + *c = atoi(optarg); + *n = -1; + break; + + case 'n': + *c = -1; + *n = atoi(optarg); + break; + + case 'h': + usage(stdout); + exit(0); + + case 'V': + drukkedoos_print_versie(stdout); + exit(0); + + case '?': + usage(stderr); + exit(1); + } + } + + return argv + optind; +} + +static int process(struct filebuf *fb, char*, bool) { + // handle byte limits + if (gc != -1) { + assert(gc >= 0); + fwrite(fb->buf+fb->sz-gc, 1, gc, stdout); + goto done; + } + + assert(gn >= 0); + size_t n = gn; + if (fb->buf[fb->sz - 1] == '\n') { + // if the file has a trailing newline, we should ignore it. So we should + // except one newline more + n += 1; + } + + ssize_t i; + for (i = fb->sz - 1; i >= 0; i--) { + if (fb->buf[i] == '\n') n--; + if (n == 0) break; + } + + if (i < 0) { + // we haven't encountered the maximum of newlines, write everything + fwrite(fb->buf, 1, fb->sz, stdout); + goto done; + } + + fwrite(fb->buf + i + 1, 1, fb->sz - i, stdout); + +done: + free_filebuf(fb); + return 0; +} + +int entry_staart(int argc, char **argv) { + gn = 10; + gc = -1; + char **args = parse_options(argc, argv, &gn, &gc); + return loop_files(args, process); +} |