+ for (; *argv != NULL; argv++) is argv[1] guaranteed? I have never seen this before.
On Wed, Jan 26, 2022 at 9:52 PM Scott Cheloha <scottchel...@gmail.com> wrote: > The main loop in head(1) is obfuscated. In particular, the path > through the loop to exit(3) is extremely clever. Clever in a bad way. > > This patch moves the open/read/write/close portions of the loop out > into a separate function, head_file(). I think the result is easier > to understand. We only loop in main() if we have file arguments, the > argv[] loop is idiomatic and simple, we actually reach the end of > main(), etc. > > In a subsequent patch I intend to switch to getline(3) and add more > error checking to head_file(). For now I have just moved the > getc/putchar loop into head_file() as-is. > > ok? > > Index: head.c > =================================================================== > RCS file: /cvs/src/usr.bin/head/head.c,v > retrieving revision 1.22 > diff -u -p -r1.22 head.c > --- head.c 10 Oct 2021 15:57:25 -0000 1.22 > +++ head.c 27 Jan 2022 04:41:09 -0000 > @@ -37,6 +37,7 @@ > #include <errno.h> > #include <unistd.h> > > +int head_file(const char *, long, int); > static void usage(void); > > /* > @@ -49,9 +50,7 @@ int > main(int argc, char *argv[]) > { > const char *errstr; > - FILE *fp; > - long cnt; > - int ch, firsttime; > + int ch; > long linecnt = 10; > int status = 0; > > @@ -81,33 +80,46 @@ main(int argc, char *argv[]) > } > argc -= optind, argv += optind; > > - for (firsttime = 1; ; firsttime = 0) { > - if (!*argv) { > - if (!firsttime) > - exit(status); > - fp = stdin; > - if (pledge("stdio", NULL) == -1) > - err(1, "pledge"); > - } else { > - if ((fp = fopen(*argv, "r")) == NULL) { > - warn("%s", *argv++); > - status = 1; > - continue; > - } > - if (argc > 1) { > - if (!firsttime) > - putchar('\n'); > - printf("==> %s <==\n", *argv); > - } > - ++argv; > - } > - for (cnt = linecnt; cnt && !feof(fp); --cnt) > - while ((ch = getc(fp)) != EOF) > - if (putchar(ch) == '\n') > - break; > - fclose(fp); > + if (argc == 0) { > + if (pledge("stdio", NULL) == -1) > + err(1, "pledge"); > + > + status = head_file(NULL, linecnt, 0); > + } else { > + for (; *argv != NULL; argv++) > + status |= head_file(*argv, linecnt, argc > 1); > } > - /*NOTREACHED*/ > + > + return status; > +} > + > +int > +head_file(const char *path, long count, int need_header) > +{ > + FILE *fp; > + int ch; > + static int first = 1; > + > + if (path != NULL) { > + fp = fopen(path, "r"); > + if (fp == NULL) { > + warn("%s", path); > + return 1; > + } > + if (need_header) { > + printf("%s==> %s <==\n", first ? "" : "\n", path); > + first = 0; > + } > + } else > + fp = stdin; > + > + for (; count > 0 && !feof(fp); --count) > + while ((ch = getc(fp)) != EOF) > + if (putchar(ch) == '\n') > + break; > + fclose(fp); > + > + return 0; > } > > > >