+               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;
>  }
>
>
>
>

Reply via email to