Audit head(1)

1) Use (s)size_t in head().
2) BUGFIX: only check buf[len - 1] when len > 0, else there would
   be an overflow when getline returns 0 (which can happen) and a
   very potential segmentation fault.
3) fix error-messages.
4) update usage().
5) argv-argc-style.
6) clear up the main loop with if (newline).
7) add newline before return.
This commit is contained in:
FRIGN 2015-03-05 00:58:12 +01:00
parent b7c199e050
commit 38066de8c2
2 changed files with 17 additions and 18 deletions

2
README
View File

@ -35,7 +35,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support,
= find yes none = find yes none
#* fold yes none #* fold yes none
=* grep yes none =* grep yes none
=* head yes none =*| head yes none
=*| hostname non-posix none =*| hostname non-posix none
=* kill yes none =* kill yes none
=*| link yes none =*| link yes none

33
head.c
View File

@ -6,27 +6,25 @@
#include "util.h" #include "util.h"
static void static void
head(FILE *fp, const char *str, long n) head(FILE *fp, const char *fname, size_t n)
{ {
char *buf = NULL; char *buf = NULL;
size_t size = 0; size_t i = 0, size = 0;
ssize_t len; ssize_t len;
unsigned long i = 0;
while (i < n && ((len = getline(&buf, &size, fp)) != -1)) { while (i < n && (len = getline(&buf, &size, fp)) >= 0) {
fputs(buf, stdout); fputs(buf, stdout);
if (buf[len - 1] == '\n') i += (len && (buf[len - 1] == '\n'));
i++;
} }
free(buf); free(buf);
if (ferror(fp)) if (ferror(fp))
eprintf("%s: read error:", str); eprintf("getline %s:", fname);
} }
static void static void
usage(void) usage(void)
{ {
eprintf("usage: %s [-n lines] [-N] [file...]\n", argv0); eprintf("usage: %s [-n num] [-N] [file ...]\n", argv0);
} }
int int
@ -34,8 +32,7 @@ main(int argc, char *argv[])
{ {
size_t n = 10; size_t n = 10;
FILE *fp; FILE *fp;
int ret = 0; int ret = 0, newline, many;
int newline, many;
ARGBEGIN { ARGBEGIN {
case 'n': case 'n':
@ -48,23 +45,25 @@ main(int argc, char *argv[])
usage(); usage();
} ARGEND; } ARGEND;
if (argc == 0) { if (!argc) {
head(stdin, "<stdin>", n); head(stdin, "<stdin>", n);
} else { } else {
many = argc > 1; many = argc > 1;
for (newline = 0; argc > 0; argc--, argv++) { for (newline = 0; *argv; argc--, argv++) {
if (!(fp = fopen(argv[0], "r"))) { if (!(fp = fopen(*argv, "r"))) {
weprintf("fopen %s:", argv[0]); weprintf("fopen %s:", *argv);
ret = 1; ret = 1;
continue; continue;
} }
if (newline)
putchar('\n');
if (many) if (many)
printf("%s==> %s <==\n", printf("==> %s <==\n", *argv);
newline ? "\n" : "", argv[0]);
newline = 1; newline = 1;
head(fp, argv[0], n); head(fp, *argv, n);
fclose(fp); fclose(fp);
} }
} }
return ret; return ret;
} }