X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=coreutils%2Fhead.c;h=ec4512765abff2f2bd5a387b630b4dea92b17351;hb=eced0c78a54bbecc61f1717d33f64ee7d99804bb;hp=f42f4837d323a6bddad94ea6cc6cd41a7a7675ea;hpb=b610615be9aedfac07d1e01f12575707fa3a227c;p=oweals%2Fbusybox.git diff --git a/coreutils/head.c b/coreutils/head.c index f42f4837d..ec4512765 100644 --- a/coreutils/head.c +++ b/coreutils/head.c @@ -1,115 +1,155 @@ /* vi: set sw=4 ts=4: */ /* - * Mini head implementation for busybox + * head implementation for busybox * + * Copyright (C) 2003 Manuel Novoa III * - * Copyright (C) 1999,2000 by Lineo, inc. - * Written by John Beppu - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ -#include "internal.h" -#include -#include +/* BB_AUDIT SUSv3 compliant */ +/* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */ +/* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */ + +//usage:#define head_trivial_usage +//usage: "[OPTIONS] [FILE]..." +//usage:#define head_full_usage "\n\n" +//usage: "Print first 10 lines of each FILE (or stdin) to stdout.\n" +//usage: "With more than one FILE, precede each with a filename header.\n" +//usage: "\n -n N[kbm] Print first N lines" +//usage: IF_FEATURE_FANCY_HEAD( +//usage: "\n -c N[kbm] Print first N bytes" +//usage: "\n -q Never print headers" +//usage: "\n -v Always print headers" +//usage: ) +//usage: "\n" +//usage: "\nN may be suffixed by k (x1024), b (x512), or m (x1024^2)." +//usage: +//usage:#define head_example_usage +//usage: "$ head -n 2 /etc/passwd\n" +//usage: "root:x:0:0:root:/root:/bin/bash\n" +//usage: "daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n" -const char head_usage[] = - "head [OPTION] [FILE]...\n" -#ifndef BB_FEATURE_TRIVIAL_HELP - "\nPrint first 10 lines of each FILE to standard output.\n" - "With more than one FILE, precede each with a header giving the\n" - "file name. With no FILE, or when FILE is -, read standard input.\n\n" +#include "libbb.h" - "Options:\n" "\t-n NUM\t\tPrint first NUM lines instead of first 10\n" +/* This is a NOEXEC applet. Be very careful! */ + +static const char head_opts[] ALIGN1 = + "n:" +#if ENABLE_FEATURE_FANCY_HEAD + "c:qv" #endif ; -int head(int len, FILE * src) -{ - int i; - char buffer[1024]; +static const struct suffix_mult head_suffixes[] = { + { "b", 512 }, + { "k", 1024 }, + { "m", 1024*1024 }, + { "", 0 } +}; - for (i = 0; i < len; i++) { - fgets(buffer, 1024, src); - if (feof(src)) { - break; - } - fputs(buffer, stdout); - } - return 0; -} +#define header_fmt_str "\n==> %s <==\n" -/* BusyBoxed head(1) */ +int head_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int head_main(int argc, char **argv) { - char opt; - int len = 10, tmplen, i; + unsigned long count = 10; + unsigned long i; +#if ENABLE_FEATURE_FANCY_HEAD + int count_bytes = 0; + int header_threshhold = 1; +#endif + FILE *fp; + const char *fmt; + char *p; + int opt; + int c; + int retval = EXIT_SUCCESS; - /* parse argv[] */ - for (i = 1; i < argc; i++) { - if (argv[i][0] == '-') { - opt = argv[i][1]; - switch (opt) { - case 'n': - tmplen = 0; - if (++i < argc) - tmplen = atoi(argv[i]); - if (tmplen < 1) - usage(head_usage); - len = tmplen; - break; - case '-': - case 'h': - usage(head_usage); - default: - fprintf(stderr, "head: invalid option -- %c\n", opt); - usage(head_usage); - } - } else { +#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD + /* Allow legacy syntax of an initial numeric option without -n. */ + if (argv[1] && argv[1][0] == '-' + && isdigit(argv[1][1]) + ) { + --argc; + ++argv; + p = (*argv) + 1; + goto GET_COUNT; + } +#endif + + /* No size benefit in converting this to getopt32 */ + while ((opt = getopt(argc, argv, head_opts)) > 0) { + switch (opt) { +#if ENABLE_FEATURE_FANCY_HEAD + case 'q': + header_threshhold = INT_MAX; break; + case 'v': + header_threshhold = -1; + break; + case 'c': + count_bytes = 1; + /* fall through */ +#endif + case 'n': + p = optarg; +#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD + GET_COUNT: +#endif + count = xatoul_sfx(p, head_suffixes); + break; + default: + bb_show_usage(); } } - /* get rest of argv[] or stdin if nothing's left */ - if (i >= argc) { - head(len, stdin); + argc -= optind; + argv += optind; + if (!*argv) + *--argv = (char*)"-"; - } else { - int need_headers = ((argc - i) > 1); - - for (; i < argc; i++) { - FILE *src; + fmt = header_fmt_str + 1; +#if ENABLE_FEATURE_FANCY_HEAD + if (argc <= header_threshhold) { + header_threshhold = 0; + } +#else + if (argc <= 1) { + fmt += 11; /* "" */ + } + /* Now define some things here to avoid #ifdefs in the code below. + * These should optimize out of the if conditions below. */ +#define header_threshhold 1 +#define count_bytes 0 +#endif - src = fopen(argv[i], "r"); - if (!src) { - fprintf(stderr, "head: %s: %s\n", argv[i], - strerror(errno)); - } else { - /* emulating GNU behaviour */ - if (need_headers) { - fprintf(stdout, "==> %s <==\n", argv[i]); - } - head(len, src); - if (i < argc - 1) { - fprintf(stdout, "\n"); + do { + fp = fopen_or_warn_stdin(*argv); + if (fp) { + if (fp == stdin) { + *argv = (char *) bb_msg_standard_input; + } + if (header_threshhold) { + printf(fmt, *argv); + } + i = count; + while (i && ((c = getc(fp)) != EOF)) { + if (count_bytes || (c == '\n')) { + --i; } + putchar(c); + } + if (fclose_if_not_stdin(fp)) { + bb_simple_perror_msg(*argv); + retval = EXIT_FAILURE; } + die_if_ferror_stdout(); + } else { + retval = EXIT_FAILURE; } - } - return(0); -} + fmt = header_fmt_str; + } while (*++argv); -/* $Id: head.c,v 1.11 2000/06/19 17:25:39 andersen Exp $ */ + fflush_stdout_and_exit(retval); +}