diff options
author | Conrad Pankoff <deoxxa@fknsrs.biz> | 2019-06-01 21:39:49 +1000 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-06-01 14:48:03 +0200 |
commit | 6cabd34b9391bb9edc7dfc3c7d9e29957d99a3ad (patch) | |
tree | 2d9669988e0d665429e49c6b992776eb4ea8a249 /Userland/head.cpp | |
parent | b8e705da0eb4a21a890681ce4d7a48089ef4b655 (diff) | |
download | serenity-6cabd34b9391bb9edc7dfc3c7d9e29957d99a3ad.zip |
Userland: Improve head program
* allow specifying files as arguments, e.g. `head a b c`
* support multiple files
* print a filename header when multiple files are being printed
* allow suppression or forcing of filename header via flags
This change drops support for the legacy `-123` syntax in favour of the
more widely-supported `-n 123` form.
fixes #105
Diffstat (limited to 'Userland/head.cpp')
-rw-r--r-- | Userland/head.cpp | 82 |
1 files changed, 75 insertions, 7 deletions
diff --git a/Userland/head.cpp b/Userland/head.cpp index 85ec6faf1e..49ae45ab18 100644 --- a/Userland/head.cpp +++ b/Userland/head.cpp @@ -1,26 +1,94 @@ +#include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <LibCore/CArgsParser.h> + +int head(const String& filename, bool print_filename, int line_count); int main(int argc, char** argv) { - // FIXME: Allow setting via command-line argument. + CArgsParser args_parser("head"); + + args_parser.add_arg("n", "lines", "Number of lines to print (default 10)"); + args_parser.add_arg("q", "Never print filenames"); + args_parser.add_arg("v", "Always print filenames"); + + CArgsParserResult args = args_parser.parse(argc, (const char**)argv); + int line_count = 10; + if (args.is_present("n")) { + line_count = strtol(args.get("n").characters(), NULL, 10); + if (errno) { + args_parser.print_usage(); + return -1; + } + } + + Vector<String> files = args.get_single_values(); - if (argc > 1) { - for (int i = 1; i < argc; ++i) { - if (argv[i][0] == '-') { - line_count = atoi(&argv[i][1]); - } + bool print_filenames = files.size() > 1; + + if (args.is_present("v")) { + print_filenames = true; + } else if (args.is_present("q")) { + print_filenames = false; + } + + if (files.is_empty()) { + return head("", print_filenames, line_count); + } + + int rc = 0; + + for (auto &file : files) { + if (head(file, print_filenames, line_count) != 0) { + rc = 1; + } + } + + return rc; +} + +int head(const String& filename, bool print_filename, int line_count) +{ + bool is_stdin = false; + FILE* fp = nullptr; + + if (filename == "" || filename == "-") { + fp = stdin; + is_stdin = true; + } else { + fp = fopen(filename.characters(), "r"); + if (!fp) { + fprintf(stderr, "can't open %s for reading: %s\n", filename.characters(), strerror(errno)); + return 1; + } + } + + if (print_filename) { + if (is_stdin) { + puts("==> standard input <=="); + } else { + printf("==> %s <==\n", filename.characters()); } } for (int line = 0; line < line_count; ++line) { char buffer[BUFSIZ]; - auto* str = fgets(buffer, sizeof(buffer), stdin); + auto* str = fgets(buffer, sizeof(buffer), fp); if (!str) break; + + // specifically use fputs rather than puts, because fputs doesn't add + // its own newline. fputs(str, stdout); } + fclose(fp); + + if (print_filename) { + puts(""); + } + return 0; } |