From 44cbb986944a0f96937ea4bd8ed991da8c0ae7fc Mon Sep 17 00:00:00 2001 From: g1n Date: Thu, 30 Jun 2022 17:36:01 +0300 Subject: [PATCH] Add head util --- src/head.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/head.c diff --git a/src/head.c b/src/head.c new file mode 100644 index 0000000..13bc937 --- /dev/null +++ b/src/head.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include + +int usage(char *argv0) { + printf("Usage: %s [-n number] [file ...]\n", argv0); + return 2; +} + +int main(int argc, char *argv[]) { + char ch; + int opt; + FILE *file = stdin; + + int number = 10; + int line = 0; + + bool multiple_files = false; + + while ((opt = getopt(argc, argv, "n:")) != -1) { + switch (opt) { + case 'n': + if (optarg[0] == '-') { + optarg++; + } + for (size_t i = 0; i < strlen(optarg); i++) { + if (!isdigit(optarg[i])) { + fprintf(stderr, "%s: invalid number of lines: '%s'\n", argv[0], optarg); + return 1; + } + } + number = atoi(optarg); + break; + case '?': + fprintf(stderr, "%s: invalid option -- '%c'\n", argv[0], optopt); + return usage(argv[0]); + } + } + + if (optind == argc) { // FIXME: this code is not clean + goto READ_STDIN; + } + + if (argc - optind > 1) { + multiple_files = true; + } + + for (; optind < argc; optind++) { + if (strcmp(argv[optind], "-")) { + file = fopen(argv[optind], "r"); + if (file == NULL) { + fprintf(stderr, "%s: ", argv[0]); + perror(argv[optind]); + return -1; + } + if (multiple_files) { + printf("%s==> %s <==\n", (optind - 1 > argc - optind ? "\n" : ""), argv[optind]); + } + } else { + file = stdin; + if (multiple_files) { + printf("%s==> %s <==\n", (optind - 1 > argc - optind ? "\n" : ""), "standard input"); + } + } +READ_STDIN: + line = 0; + while ((ch = fgetc(file)) != EOF && line < number) { + putchar(ch); + if (ch == '\n') { + line++; + } + } + if (file != NULL && file != stdin) { + fclose(file); + } + } + return 0; +}