Audit cut(1)

1) Add check to parselist() to warn about an empty list.
2) Remove all "cut: "-prefixes from error-messages and other style
   changes.
3) != -1 --> >= 0 and check for ferror on fp after getline.
4) Update usage with argv0.
5) argv-centric loop refactor
6) Properly report exit-status.
7) Add empty line before return.
This commit is contained in:
FRIGN 2015-03-11 17:29:18 +01:00
parent 011c81b21b
commit c9de9dd3c2

39
cut.c
View File

@ -50,6 +50,8 @@ parselist(char *str)
size_t n = 1; size_t n = 1;
Range *r; Range *r;
if (!*str)
eprintf("empty list\n");
for (s = str; *s; s++) { for (s = str; *s; s++) {
if (*s == ' ') if (*s == ' ')
*s = ','; *s = ',';
@ -62,7 +64,7 @@ parselist(char *str)
r->max = (*s == '-') ? strtoul(s + 1, &s, 10) : r->min; r->max = (*s == '-') ? strtoul(s + 1, &s, 10) : r->min;
r->next = NULL; r->next = NULL;
if (!r->min || (r->max && r->max < r->min) || (*s && *s != ',')) if (!r->min || (r->max && r->max < r->min) || (*s && *s != ','))
eprintf("cut: bad list value\n"); eprintf("bad list value\n");
insert(r++); insert(r++);
} }
} }
@ -103,7 +105,7 @@ seek(const char *s, size_t pos, size_t *prev, size_t count)
} }
static void static void
cut(FILE *fp) cut(FILE *fp, char *fname)
{ {
static char *buf = NULL; static char *buf = NULL;
static size_t size = 0; static size_t size = 0;
@ -112,7 +114,7 @@ cut(FILE *fp)
ssize_t len; ssize_t len;
Range *r; Range *r;
while ((len = getline(&buf, &size, fp)) != -1) { while ((len = getline(&buf, &size, fp)) >= 0) {
if (len && buf[len - 1] == '\n') if (len && buf[len - 1] == '\n')
buf[len - 1] = '\0'; buf[len - 1] = '\0';
if (mode == 'f' && !utfutf(buf, delim)) { if (mode == 'f' && !utfutf(buf, delim)) {
@ -132,24 +134,28 @@ cut(FILE *fp)
n = seek(s, r->max + 1, &p, i); n = seek(s, r->max + 1, &p, i);
i += (mode == 'f') ? delimlen : 1; i += (mode == 'f') ? delimlen : 1;
if (fwrite(s, 1, n, stdout) != n) if (fwrite(s, 1, n, stdout) != n)
eprintf("write error:"); eprintf("fwrite <stdout>:");
} }
putchar('\n'); putchar('\n');
} }
if (ferror(fp))
eprintf("getline %s:", fname);
} }
static void static void
usage(void) usage(void)
{ {
eprintf("usage: cut -b list [-n] [file ...]\n" eprintf("usage: %s -b list [-n] [file ...]\n"
" cut -c list [file ...]\n" " %s -c list [file ...]\n"
" cut -f list [-d delim] [-s] [file ...]\n"); " %s -f list [-d delim] [-s] [file ...]\n",
argv0, argv0, argv0);
} }
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
FILE *fp; FILE *fp;
int ret = 0;
ARGBEGIN { ARGBEGIN {
case 'b': case 'b':
@ -161,7 +167,7 @@ main(int argc, char *argv[])
case 'd': case 'd':
delim = EARGF(usage()); delim = EARGF(usage());
if (!*delim) if (!*delim)
eprintf("cut: empty delimiter\n"); eprintf("empty delimiter\n");
delimlen = unescape(delim); delimlen = unescape(delim);
break; break;
case 'n': case 'n':
@ -176,19 +182,24 @@ main(int argc, char *argv[])
if (!mode) if (!mode)
usage(); usage();
if (!argc) if (!argc)
cut(stdin); cut(stdin, "<stdin>");
else for (; argc--; argv++) {
if (!strcmp(*argv, "-"))
cut(stdin);
else { else {
for (; *argv; argc--, argv++) {
if (*argv[0] == '-' && !*argv[1]) {
cut(stdin, "<stdin>");
} else {
if (!(fp = fopen(*argv, "r"))) { if (!(fp = fopen(*argv, "r"))) {
weprintf("fopen %s:", *argv); weprintf("fopen %s:", *argv);
ret = 1;
continue; continue;
} }
cut(fp); cut(fp, *argv);
fclose(fp); fclose(fp);
} }
} }
return 0; }
return ret;
} }