#include "../command.h" struct Flags { int count; bool lines; bool print_headers; bool dont_print_headers; }; static void head_file_lines(FILE* file, struct Flags* flags) { size_t len = 0; char* line = NULL; int count = flags->count; while(count > 0 && getline(&line, &len, file) != -1) { printf("%s", line); count--; } free(line); fclose(file); } static void head_file_chars(FILE* file, struct Flags* flags) { char c; int count = flags->count; while(count > 0 && (c = getc(file)) != EOF) { putchar(c); count--; } fclose(file); } static void help() { printf("Usage: head [OPTIONS] [FILE]...\n\n"); printf("Print first 10 lines of FILEs (or stdin)\n"); printf("With more than one FILE, precede each with a filename header.\n\n"); printf("\t-c [+]N[bkm]\tPrint first N bytes\n"); printf("\t-n N[bkm]\tPrint first N lines\n"); printf("\t\t\t(b:*512 k:*1024 m:*1024^2)\n"); printf("\t-q\t\tNever print headers\n"); printf("\t-v\t\tAlways print headers\n"); exit(EXIT_SUCCESS); } static char* next_arg(int argc, char** argv, int index) { if (index >= argc) { error("error: expected another argument after option"); } return argv[index]; } static void print_header(char* path, struct Flags* flags, bool many) { if (flags->dont_print_headers) return; if (!many && !flags->print_headers) return; if (streql("-", path)) { printf("\n==> standard input <==\n"); } else { printf("\n=>> %s <==\n", path); } } static void head_file(char* path, struct Flags* flags, bool many) { FILE* file = get_file(path, "r"); print_header(path, flags, many); if (flags->lines) { head_file_lines(file, flags); } else { head_file_chars(file, flags); } } COMMAND(head) { struct Flags flags; flags.count = 10; flags.lines = true; flags.print_headers = false; flags.dont_print_headers = false; int start = 0; for (int i = 0; i < argc; i++) { if (!prefix("-", argv[i])) break; if (streql(argv[0], "--help")) help(); start++; int i_s = i; for (size_t j = 1; j < strlen(argv[i_s]); j++) { char c = argv[i_s][j]; switch(c) { case 'c': { start++; flags.lines = false; char* arg = next_arg(argc, argv, ++i); long int bkm = get_blkm(arg); if (bkm < 1) { error("error: bkm cannot be less than 1"); } flags.count = bkm; break; } case 'n': { start++; flags.lines = true; char* arg = next_arg(argc, argv, ++i); long int bkm = get_blkm(arg); if (bkm < 1) { error("error: bkm cannot be less than 1"); } flags.count = bkm; break; } case 'q': flags.dont_print_headers = true; break; case 'v': flags.print_headers = true; break; default: { error("error: unknown option -%c", c); } } } } int count = argc - start; if (count < 1) { head_file_lines(stdin, &flags); return EXIT_SUCCESS; } if (count == 1) { head_file(argv[start], &flags, false); return EXIT_SUCCESS; } for (int i = 0; i < count; i++) { head_file(argv[start + i], &flags, true); } return EXIT_SUCCESS; }