X-Git-Url: https://pd.if.org/git/?p=pdutils;a=blobdiff_plain;f=utils%2Fhead%2Fhead.c;fp=utils%2Fhead%2Fhead.c;h=bf83ab35ce639d53a39f6bd496a7d6e347a3db73;hp=0000000000000000000000000000000000000000;hb=4daa873acbfc240e9ecc350e74c14bbfd58fabc9;hpb=b6d847ae20c32744d508eced2be3132c3fa8c5b9 diff --git a/utils/head/head.c b/utils/head/head.c new file mode 100644 index 0000000..bf83ab3 --- /dev/null +++ b/utils/head/head.c @@ -0,0 +1,147 @@ +/* + * head.c - copy the first part of files + * + * Version: 2008-1.01 + * Build: c89 -o head head.c + * Source: + * Spec: + * + * This is free and unencumbered software released into the public domain, + * provided "as is", without warranty of any kind, express or implied. See the + * file UNLICENSE and the website for further details. + */ + + +#define _POSIX_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "usage: head [-n number] [file ...]\n" +#define BUFSIZE 4096 + +static long ctol(char *s); +static void headfile(int fd, char *fn, int lines); +static void error(char *s); + +static int exitstatus; + + +int main(int argc, char **argv) +{ + extern int opterr, optind; + extern char *optarg; + int c, fd, many, first; + char *fn; + long lines = 10; + + setlocale(LC_ALL, ""); + opterr = 0; + + while ((c = getopt(argc, argv, "n:")) != -1) + switch (c) + { + case 'n': + if (*optarg && (lines = ctol(optarg)) > 0) + break; + /* else fall through */ + default: + fprintf(stderr, USAGE); + exit(1); + } + + if (optind >= argc) + headfile(STDIN_FILENO, "stdin", lines); + else + { + many = (optind + 1 < argc) ? 1 : 0; + first = 1; + + while (optind < argc) + { + fn = argv[optind++]; + + if (many) + { + if (first) + first = 0; + else + printf("\n"); + printf("==> %s <==\n", fn); + } + + if (strcmp(fn, "-") == 0) + headfile(STDIN_FILENO, "stdin", lines); + else + if ((fd = open(fn, O_RDONLY)) == -1) + error(fn); + else + { + headfile(fd, fn, lines); + if (close(fd) == -1) + error(fn); + } + } + } + + return(exitstatus); +} + + +long ctol(char *s) +{ + int badch = 0; + char *c = s; + + /* only copes with non-zero, optionally signed, */ + /* decimal integers; that's all we need */ + if (! (isdigit(*c) || *c == '+' || *c == '-')) + badch = 1; + else + for (c++; *c; c++) + if (! isdigit(*c)) + badch = 1; + + return (badch ? 0 : atol(s)); +} + + +void headfile(int fd, char *fn, int lines) +{ + unsigned char buf[BUFSIZE], *c; + ssize_t n, o; + + while (lines) + { + if ((n = read(fd, buf, BUFSIZE)) <= 0) + break; + + for (c = buf; lines && c < (buf + n); c++) + if (*c == '\n') + lines--; + + o = lines ? n : c - buf; + if (write(STDOUT_FILENO, buf, (size_t)o) != o) + { + error("stdout"); + break; + } + } + + if (n < 0) + error(fn); +} + + +void error(char *s) +{ + fprintf(stderr, "head: %s: %s\n", s, strerror(errno)); + exitstatus = 1; +}