Audit comm(1)

1) Use the LIMIT()-macro in util.h instead of defining our own.
2) Drop nextline() and finish(), not needed anymore. Use
   fputs in printline instead of printf.
   --> BUGFIX: Finish exited with status 1, but actually should
               exit with status 0 if ferror(f) == 0.
3) Don't use /dev/fd/0 and use idiomatic <stdin> and fp = stdin
   instead.
4) Refactor loop to use getline() instead of some handrolled
   nextline-function.
   --> BUGFIX: Line-length was limited to LINE_MAX before, now
               it's factually unlimited.
5) Combine diff >= 0 and diff <= 0 into one loop with a beginning
   continue-condition (diff && i == (diff < 0)).
6) BUGFIX: If diff == 0, don't print one buffer after EOFing on the
           other.
This commit is contained in:
FRIGN 2015-03-11 13:39:08 +01:00
parent 76ea3fdd52
commit a4587b84f8

79
comm.c
View File

@ -5,8 +5,6 @@
#include "util.h" #include "util.h"
#define CLAMP(x, l, h) MIN(h, MAX(l, x))
static int show = 0x07; static int show = 0x07;
static void static void
@ -21,28 +19,7 @@ printline(int pos, char *line)
if (show & (0x1 << i)) if (show & (0x1 << i))
putchar('\t'); putchar('\t');
} }
printf("%s", line); fputs(line, stdout);
}
static char *
nextline(char *buf, int n, FILE *f, char *name)
{
buf = fgets(buf, n, f);
if (!buf && !feof(f))
eprintf("%s: read error:", name);
if (buf && !strchr(buf, '\n'))
eprintf("%s: line too long\n", name);
return buf;
}
static void
finish(int pos, FILE *f, char *name)
{
char buf[LINE_MAX + 1];
while (nextline(buf, sizeof(buf), f, name))
printline(pos, buf);
exit(1);
} }
static void static void
@ -54,9 +31,10 @@ usage(void)
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int i, diff = 0;
FILE *fp[2]; FILE *fp[2];
char lines[2][LINE_MAX + 1]; size_t linelen[2] = { 0, 0 };
int i, diff = 0;
char *line[2] = { NULL, NULL };
ARGBEGIN { ARGBEGIN {
case '1': case '1':
@ -71,36 +49,35 @@ main(int argc, char *argv[])
if (argc != 2) if (argc != 2)
usage(); usage();
for (i = 0; i < LEN(fp); i++) { for (i = 0; i < 2; i++) {
if (argv[i][0] == '-' && !argv[i][1]) if (argv[i][0] == '-' && !argv[i][1]) {
argv[i] = "/dev/fd/0"; argv[i] = "<stdin>";
if (!(fp[i] = fopen(argv[i], "r"))) fp[i] = stdin;
} else if (!(fp[i] = fopen(argv[i], "r"))) {
eprintf("fopen %s:", argv[i]); eprintf("fopen %s:", argv[i]);
} }
}
for (;;) { for (;;) {
if (diff <= 0) { for (i = 0; i < 2; i++) {
lines[0][0] = '\0'; if (diff && i == (diff < 0))
if (!nextline(lines[0], sizeof(lines[0]), continue;
fp[0], argv[0])) { if (getline(&line[i], &linelen[i], fp[i]) >= 0)
if (lines[1][0] != '\0') continue;
printline(1, lines[1]); if (ferror(fp[i]))
finish(1, fp[1], argv[1]); eprintf("getline %s:", argv[i]);
if (diff && strlen(line[!i]))
printline(!i, line[!i]);
while (getline(&line[!i], &linelen[!i], fp[!i]) >= 0)
printline(!i, line[!i]);
if (ferror(fp[!i]))
eprintf("getline %s:", argv[!i]);
goto end;
} }
diff = strcmp(line[0], line[1]);
LIMIT(diff, -1, 1);
printline((2-diff) % 3, line[MAX(0, diff)]);
} }
if (diff >= 0) { end:
lines[1][0] = '\0';
if (!nextline(lines[1], sizeof(lines[1]),
fp[1], argv[1])) {
if (lines[0][0] != '\0')
printline(0, lines[0]);
finish(0, fp[0], argv[0]);
}
}
diff = strcmp(lines[0], lines[1]);
diff = CLAMP(diff, -1, 1);
printline((2-diff) % 3, lines[MAX(0, diff)]);
}
return 0; return 0;
} }