/*
* 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;
}