Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace fgetsx() by fgets(3) and fputsx() by fputs(3) #1056

Draft
wants to merge 19 commits into
base: master
Choose a base branch
from

Conversation

alejandro-colomar
Copy link
Collaborator

@alejandro-colomar alejandro-colomar commented Jul 21, 2024

It seems they never worked correctly. Let's keep it simple and remove
support for escaped newlines.

Closes: #1055
Reported-by: @zeha

(Merge after #1048.)


Revisions:

v1b
  • Rebase
$ git range-diff c76f680fceb4^..gh/fgets string..fgets 
1:  c76f680f = 1:  d0cdc9c8 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  18db7b5a = 2:  4d66df60 lib/, src/: Consistently use NULL with fgets(3)
3:  b38c5eb0 = 3:  941c951c lib/, src/: Remove useless casts in fgets(3)
4:  2c112e69 = 4:  cd64d530 lib/, po/: Remove fgetsx() and fputsx()
v2
  • Use getline(3) instead of its pattern.
$ git range-diff string gh/fgets fgets 
1:  d0cdc9c8 = 1:  d0cdc9c8 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  4d66df60 = 2:  4d66df60 lib/, src/: Consistently use NULL with fgets(3)
3:  941c951c = 3:  941c951c lib/, src/: Remove useless casts in fgets(3)
4:  cd64d530 = 4:  cd64d530 lib/, po/: Remove fgetsx() and fputsx()
-:  -------- > 5:  e8036d0e lib/: Use getline(3) instead of its pattern
v2b
  • Remove unused include and macro
$ git range-diff string gh/fgets fgets 
1:  d0cdc9c8 = 1:  d0cdc9c8 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  4d66df60 = 2:  4d66df60 lib/, src/: Consistently use NULL with fgets(3)
3:  941c951c = 3:  941c951c lib/, src/: Remove useless casts in fgets(3)
4:  cd64d530 = 4:  cd64d530 lib/, po/: Remove fgetsx() and fputsx()
5:  e8036d0e ! 5:  0c59138d lib/: Use getline(3) instead of its pattern
    @@ Commit message
         Signed-off-by: Alejandro Colomar <[email protected]>
     
      ## lib/commonio.c ##
    +@@
    + #include <utime.h>
    + 
    + #include "alloc/malloc.h"
    +-#include "alloc/reallocf.h"
    + #include "atoi/getnum.h"
    + #include "commonio.h"
    + #include "defines.h"
    +@@ lib/commonio.c: static void add_one_entry_nis (struct commonio_db *db,
    + }
    + #endif                            /* KEEP_NIS_AT_END */
    + 
    +-/* Initial buffer size, as well as increment if not sufficient
    +-   (for reading very long lines in group files).  */
    +-#define BUFLEN 4096
    + 
    +-int commonio_open (struct commonio_db *db, int mode)
    ++int
    ++commonio_open(struct commonio_db *db, int mode)
    + {
    +   char *buf;
    +   char *line;
     @@ lib/commonio.c: int commonio_open (struct commonio_db *db, int mode)
                return 0;
        }
    @@ lib/commonio.c: int commonio_open (struct commonio_db *db, int mode)
      
                line = strdup (buf);
                if (NULL == line) {
    +@@ lib/commonio.c: int commonio_open (struct commonio_db *db, int mode)
    +   return 0;
    + }
    + 
    ++
    + /*
    +  * Sort given db according to cmp function (usually compares uids)
    +  */
     
      ## lib/gshadow.c ##
     @@ lib/gshadow.c: void endsgent (void)
v3
  • Cosmetic in function declarator.
  • free(3) memory instead of keeping a static pointer. [@zeha]
$ git range-diff string gh/fgets fgets 
1:  d0cdc9c8 = 1:  d0cdc9c8 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  4d66df60 = 2:  4d66df60 lib/, src/: Consistently use NULL with fgets(3)
3:  941c951c = 3:  941c951c lib/, src/: Remove useless casts in fgets(3)
4:  cd64d530 = 4:  cd64d530 lib/, po/: Remove fgetsx() and fputsx()
5:  0c59138d ! 5:  decf456e lib/: Use getline(3) instead of its pattern
    @@ lib/commonio.c: int commonio_open (struct commonio_db *db, int mode)
     
      ## lib/gshadow.c ##
     @@ lib/gshadow.c: void endsgent (void)
    +   return &sgroup;
    + }
    + 
    ++
    + /*
    +  * fgetsgent - convert next line in stream to (struct sgrp)
    +  *
    +@@ lib/gshadow.c: void endsgent (void)
    +  * converts it to a (struct sgrp).  NULL is returned on EOF.
    +  */
    + 
    +-/*@observer@*//*@null@*/struct sgrp *fgetsgent (/*@null@*/FILE * fp)
    ++/*@observer@*//*@null@*/struct sgrp *
    ++fgetsgent(/*@null@*/FILE *fp)
    + {
        static size_t buflen = 0;
        static char *buf = NULL;
      
    @@ lib/gshadow.c: void endsgent (void)
        return (sgetsgent (buf));
      }
      
    ++
    + /*
    +  * getsgent - get a single shadow group entry
    +  */
-:  -------- > 6:  3e3b3743 lib/gshadow.c: fgetsgent(): Don't use static variables
v3b
  • Remove formatting fix that complicates diff.
$ git range-diff string gh/fgets fgets 
1:  d0cdc9c8 = 1:  d0cdc9c8 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  4d66df60 = 2:  4d66df60 lib/, src/: Consistently use NULL with fgets(3)
3:  941c951c = 3:  941c951c lib/, src/: Remove useless casts in fgets(3)
4:  cd64d530 = 4:  cd64d530 lib/, po/: Remove fgetsx() and fputsx()
5:  decf456e = 5:  decf456e lib/: Use getline(3) instead of its pattern
6:  3e3b3743 ! 6:  0936efac lib/gshadow.c: fgetsgent(): Don't use static variables
    @@ lib/gshadow.c: void endsgent (void)
     +  size_t       buflen = 0;
     +  struct sgrp  *sg;
      
    --  if (NULL == fp) {
    -+  if (NULL == fp)
    -           return NULL;
    --  }
    - 
    -   if (getline(&buf, &buflen, fp) == -1)
    +   if (NULL == fp) {
                return NULL;
    +@@ lib/gshadow.c: fgetsgent(/*@null@*/FILE *fp)
        if (stpsep(buf, "\n") == NULL)
                return NULL;
      
v4
  • Globally make the uses of sizeof() consistent.
  • Provide semantic patches where they can be used to validate the patches, in the corresponding commit message. [@thesamesam ]
  • Move the white-space and brace changes, to commits where it can be hidden with git-diff(1)'s -w and/or --color-words=., so that it doesn't hurt review.
$ git range-diff string gh/fgets fgets 
1:  d0cdc9c8 = 1:  d0cdc9c8 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
-:  -------- > 2:  8f77030f contrib/, lib/, src/: Consistently use sizeof() as if it were a function
3:  941c951c ! 3:  b2b9bbb3 lib/, src/: Remove useless casts in fgets(3)
    @@ Metadata
      ## Commit message ##
         lib/, src/: Remove useless casts in fgets(3)
     
    +    This patch can be replicated with the following semantic patch:
    +
    +            $ cat fgets_cast.sp
    +            @@
    +            expression a, b, c;
    +            @@
    +
    +            - fgets(a, (int) (b), c)
    +            + fgets(a, b, c)
    +
    +            @@
    +            expression a, b, c;
    +            @@
    +
    +            - fgets(a, (int) b, c)
    +            + fgets(a, b, c)
    +
    +            @@
    +            expression a, b, c;
    +            @@
    +
    +            - fgetsx(a, (int) (b), c)
    +            + fgetsx(a, b, c)
    +
    +            @@
    +            expression a, b, c;
    +            @@
    +
    +            - fgetsx(a, (int) b, c)
    +            + fgetsx(a, b, c)
    +
    +            @@
    +            expression a, b, c, p;
    +            @@
    +
    +            - p->fgets(a, (int) (b), c)
    +            + p->fgets(a, b, c)
    +
    +            @@
    +            expression a, b, c, p;
    +            @@
    +
    +            - p->fgets(a, (int) b, c)
    +            + p->fgets(a, b, c)
    +
    +    which is applied as:
    +
    +            $ find lib* src/ -type f \
    +            | xargs spatch --sp-file ~/tmp/spatch/fgets_cast.sp --in-place;
    +
         Signed-off-by: Alejandro Colomar <[email protected]>
     
      ## lib/commonio.c ##
    @@ lib/commonio.c: int commonio_open (struct commonio_db *db, int mode)
     -                  if (db->ops->fgets (buf + len,
     -                                      (int) (buflen - len),
     -                                      db->fp) == NULL) {
    -+                  if (db->ops->fgets(buf + len, buflen - len, db->fp) == NULL)
    ++                  if (db->ops->fgets(buf + len, buflen - len, db->fp) == NULL) {
                                goto cleanup_buf;
    --                  }
    +                   }
                }
    -           stpsep(buf, "\n");
    - 
     
      ## lib/gshadow.c ##
     @@ lib/gshadow.c: void endsgent (void)
                buflen *= 2;
      
                len = strlen (buf);
    --          if (fgetsx(&buf[len], (int) (buflen - len), fp) == NULL)
    -+          if (fgetsx(&buf[len], buflen - len, fp) == NULL)
    +-          if (fgetsx (&buf[len],
    +-                      (int) (buflen - len),
    +-                      fp) != &buf[len]) {
    ++          if (fgetsx(&buf[len], buflen - len, fp) != &buf[len]) {
                        return NULL;
    +           }
        }
    -   stpsep(buf, "\n");
     
      ## lib/setupenv.c ##
     @@ lib/setupenv.c: static void read_env_file (const char *filename)
        if (NULL == fp) {
                return;
        }
    --  while (fgets(buf, (int)(sizeof(buf)), fp) != NULL) {
    -+  while (fgets(buf, sizeof(buf), fp) != NULL) {
    +-  while (fgets(buf, (int) sizeof(buf), fp) == buf) {
    ++  while (fgets(buf, sizeof(buf), fp) == buf) {
                if (stpsep(buf, "\n") == NULL)
                        break;
      
    @@ src/chgpasswd.c: int main (int argc, char **argv)
         * group entry for each group will be looked up in the appropriate
         * file (gshadow or group) and the password changed.
         */
    --  while (fgets (buf, (int) sizeof buf, stdin) != NULL) {
    +-  while (fgets(buf, (int) sizeof(buf), stdin) != NULL) {
     +  while (fgets(buf, sizeof(buf), stdin) != NULL) {
                line++;
                if (stpsep(buf, "\n") == NULL) {
2:  4d66df60 ! 4:  00db7341 lib/, src/: Consistently use NULL with fgets(3)
    @@ Commit message
     
         <stddef.h> is the header that provides NULL; add it where appropriate.
     
    +    The meat of this patch can be approximated with the following semantic
    +    patch:
    +
    +            $ cat ~/tmp/spatch/fgets_null.sp
    +            @@
    +            expression a, b, c;
    +            @@
    +
    +            - fgets(a, b, c) == a
    +            + fgets(a, b, c) != NULL
    +
    +            @@
    +            expression a, b, c;
    +            @@
    +
    +            - fgetsx(a, b, c) == a
    +            + fgetsx(a, b, c) != NULL
    +
    +            @@
    +            expression a, b, c, p;
    +            @@
    +
    +            - p->fgets(a, b, c) == a
    +            + p->fgets(a, b, c) != NULL
    +
    +            @@
    +            expression a, b, c;
    +            @@
    +
    +            - fgets(a, b, c) != a
    +            + fgets(a, b, c) == NULL
    +
    +            @@
    +            expression a, b, c;
    +            @@
    +
    +            - fgetsx(a, b, c) != a
    +            + fgetsx(a, b, c) == NULL
    +
    +            @@
    +            expression a, b, c, p;
    +            @@
    +
    +            - p->fgets(a, b, c) != a
    +            + p->fgets(a, b, c) == NUL
    +
    +    Applied as
    +
    +            $ find contrib/ lib* src/ -type f \
    +            | xargs spatch --sp-file ~/tmp/spatch/fgets_null.sp --in-place;
    +
    +    The differences between the actual patch and the approximation via the
    +    semantic patch from above are includes, whitespace, braces, and a case
    +    where there was an implicit pointer-to-bool comparison which I made
    +    explicit.  When reviewing, it'll be useful to use git-diff(1) with '-w'
    +    and '--color-words=.'.
    +
         Signed-off-by: Alejandro Colomar <[email protected]>
     
      ## lib/commonio.c ##
    @@ lib/gshadow.c: void endsgent (void)
                buflen *= 2;
      
                len = strlen (buf);
    --          if (fgetsx (&buf[len],
    --                      (int) (buflen - len),
    --                      fp) != &buf[len]) {
    -+          if (fgetsx(&buf[len], (int) (buflen - len), fp) == NULL)
    +-          if (fgetsx(&buf[len], buflen - len, fp) != &buf[len]) {
    ++          if (fgetsx(&buf[len], buflen - len, fp) == NULL)
                        return NULL;
     -          }
        }
    @@ lib/hushed.c: bool hushed (const char *username)
        if (NULL == fp) {
                return false;
        }
    --  for (found = false; !found && (fgets (buf, sizeof buf, fp) == buf);) {
    +-  for (found = false; !found && (fgets(buf, sizeof(buf), fp) == buf);) {
     +  for (found = false; !found && (fgets(buf, sizeof(buf), fp) != NULL);) {
                stpsep(buf, "\n");
                found = (strcmp (buf, pw->pw_shell) == 0) ||
    @@ lib/loginprompt.c: login_prompt(char *name, int namesize)
         */
      
        MEMZERO(buf);
    --  if (fgets (buf, sizeof buf, stdin) != buf) {
    +-  if (fgets(buf, sizeof(buf), stdin) != buf) {
     +  if (fgets(buf, sizeof(buf), stdin) == NULL)
                exit (EXIT_FAILURE);
     -  }
    @@ lib/setupenv.c: static void read_env_file (const char *filename)
        if (NULL == fp) {
                return;
        }
    --  while (fgets (buf, (int)(sizeof buf), fp) == buf) {
    -+  while (fgets(buf, (int)(sizeof(buf)), fp) != NULL) {
    +-  while (fgets(buf, sizeof(buf), fp) == buf) {
    ++  while (fgets(buf, sizeof(buf), fp) != NULL) {
                if (stpsep(buf, "\n") == NULL)
                        break;
      
    @@ lib/ttytype.c: void ttytype (const char *line)
                        perror (typefile);
                return;
        }
    --  while (fgets (buf, sizeof buf, fp) == buf) {
    +-  while (fgets(buf, sizeof(buf), fp) == buf) {
     +  while (fgets(buf, sizeof(buf), fp) != NULL) {
                if (buf[0] == '#') {
                        continue;
                }
     
    + ## lib/user_busy.c ##
    +@@
    + #ident "$Id: $"
    + 
    + #include <assert.h>
    ++#include <stddef.h>
    + #include <stdio.h>
    + #include <sys/types.h>
    + #include <dirent.h>
    +@@ lib/user_busy.c: static int check_status (const char *name, const char *sname, uid_t uid)
    +   if (NULL == sfile) {
    +           return 0;
    +   }
    +-  while (fgets(line, sizeof(line), sfile) == line) {
    ++  while (fgets(line, sizeof(line), sfile) != NULL) {
    +           if (strncmp (line, "Uid:\t", 5) == 0) {
    +                   unsigned long ruid, euid, suid;
    + 
    +
      ## src/login_nopam.c ##
     @@ src/login_nopam.c: login_access(const char *user, const char *from)
        if (NULL != fp) {
                int lineno = 0; /* for diagnostics */
                while (   !match
    --                 && (fgets (line, sizeof (line), fp) == line))
    +-                 && (fgets(line, sizeof(line), fp) == line))
     +                 && (fgets(line, sizeof(line), fp) != NULL))
                {
                        char  *p;
    @@ src/useradd.c: get_defaults(void)
         * Read the file a line at a time. Only the lines that have relevant
         * values are used, everything else can be ignored.
         */
    --  while (fgets (buf, sizeof buf, fp) == buf) {
    +-  while (fgets(buf, sizeof(buf), fp) == buf) {
     +  while (fgets(buf, sizeof(buf), fp) != NULL) {
                stpsep(buf, "\n");
      
    @@ src/useradd.c: set_defaults(void)
                goto skip;
        }
      
    --  while (fgets (buf, sizeof buf, ifp) == buf) {
    +-  while (fgets(buf, sizeof(buf), ifp) == buf) {
     +  while (fgets(buf, sizeof(buf), ifp) != NULL) {
                char  *val;
      
4:  cd64d530 ! 5:  c1ccbb9a lib/, po/: Remove fgetsx() and fputsx()
    @@ lib/commonio.c: int commonio_open (struct commonio_db *db, int mode)
                                goto cleanup_errno;
      
                        len = strlen (buf);
    --                  if (db->ops->fgets(buf + len, buflen - len, db->fp) == NULL)
    +-                  if (db->ops->fgets(buf + len, buflen - len, db->fp) == NULL) {
     +                  if (fgets(buf + len, buflen - len, db->fp) == NULL)
                                goto cleanup_buf;
    +-                  }
                }
                stpsep(buf, "\n");
    + 
     @@ lib/commonio.c: static int write_all (const struct commonio_db *db)
                                return -1;
                        }
                } else if (NULL != p->line) {
     -                  if (db->ops->fputs (p->line, db->fp) == EOF) {
    -+                  if (fputs(p->line, db->fp) == EOF) {
    ++                  if (fputs(p->line, db->fp) == EOF)
    +                           return -1;
    +-                  }
    ++
    +                   if (putc ('\n', db->fp) == EOF) {
                                return -1;
                        }
    -                   if (putc ('\n', db->fp) == EOF) {
     
      ## lib/commonio.h ##
     @@ lib/commonio.h: struct commonio_ops {
5:  decf456e = 6:  9991189d lib/: Use getline(3) instead of its pattern
6:  0936efac = 7:  51005793 lib/gshadow.c: fgetsgent(): Don't use static variables
v4b
  • Rebase
$ git range-diff d0cdc9c8f683^..gh/fgets string..fgets 
1:  d0cdc9c8 = 1:  8dbc8149 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  8f77030f ! 2:  ac57816a contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    @@ Commit message
         Signed-off-by: Alejandro Colomar <[email protected]>
     
      ## contrib/adduser.c ##
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
          printf ("\nLogin to add (^C to quit): ");
          fflush (stdout);
      
    @@ contrib/adduser.c: main(void)
      
          if (!strlen (usrname))
            {
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
      
            printf ("\nFull Name [%s]: ", usrname);
            fflush (stdout);
    @@ contrib/adduser.c: main(void)
          strcpy (person, usrname);
        };
      
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
              bad = 0;
              printf ("GID [%d]: ", DEFAULT_GROUP);
              fflush (stdout);
    @@ contrib/adduser.c: main(void)
              if (!strlen (foo))
                group = DEFAULT_GROUP;
              else if (isdigit (*foo))
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
          printf ("\nIf home dir ends with a / then '%s' will be appended to it\n", usrname);
          printf ("Home Directory [%s/%s]: ", DEFAULT_HOME, usrname);
          fflush (stdout);
    @@ contrib/adduser.c: main(void)
          if (!strlen(dir))  /* hit return */
            sprintf(dir, "%s/%s", DEFAULT_HOME, usrname);
          else if (dir[strlen (dir) - 1] == '/')
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
      
            printf ("\nShell [%s]: ", DEFAULT_SHELL);
            fflush (stdout);
    @@ contrib/adduser.c: main(void)
            if (!strlen (shell))
        strcpy(shell, DEFAULT_SHELL);
            else
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
      #endif
          printf ("\nMin. Password Change Days [%d]: ", DEFAULT_MIN_PASS);
          fflush (stdout);
    @@ contrib/adduser.c: main(void)
          if (strlen (foo) > 1)
            min_pass = DEFAULT_MIN_PASS;
          else
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
      
          printf ("Max. Password Change Days [%d]: ", DEFAULT_MAX_PASS);
          fflush (stdout);
    @@ contrib/adduser.c: main(void)
          if (strlen (foo) > 1)
            max_pass = atoi (foo);
          else
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
      
          printf ("Password Warning Days [%d]: ", DEFAULT_WARN_PASS);
          fflush (stdout);
    @@ contrib/adduser.c: main(void)
          warn_pass = atoi (foo);
          if (warn_pass == 0)
      
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
      
          printf ("Days after Password Expiry for Account Locking [%d]: ", DEFAULT_USER_DIE);
          fflush (stdout);
    @@ contrib/adduser.c: main(void)
          user_die = atoi (foo);
          if (user_die == 0)
            user_die = DEFAULT_USER_DIE;
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
              min_pass, max_pass, warn_pass, user_die);
            printf ("\nIs this correct? [y/N]: ");
            fflush (stdout);
     -      safeget (foo, sizeof (foo));
     +      safeget(foo, sizeof(foo));
      
    -       done = bad = correct = !!strchr("yY", foo[0]);
    +       done = bad = correct = (foo[0] == 'y' || foo[0] == 'Y');
      
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
      
        *environ = NULL;
      
    @@ contrib/adduser.c: main(void)
        sprintf (cmd, "%s -g %d -d %s -s %s -c \"%s\" -m -k /etc/skel %s",
           USERADD_PATH, group, dir, shell, person, usrname);
        printf ("Calling useradd to add new user:\n%s\n", cmd);
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
                         */
        setuid (0);
      
    @@ contrib/adduser.c: main(void)
      
        /* Chage runs suid root. => we need ruid root to run it with
         * anything other than chage -l
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
        /* I want to add a user completely with one easy command --chris */
      
      #ifdef HAVE_QUOTAS
    @@ contrib/adduser.c: main(void)
        sprintf (cmd, "%s -p %s -u %s", EDQUOTA_PATH, QUOTA_DEFAULT, usrname);
        printf ("%s\n", cmd);
        if (system (cmd))
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
          printf ("\nDefault quota set.\n");
      #endif /* HAVE_QUOTAS */
      
    @@ contrib/adduser.c: main(void)
        sprintf (cmd, "%s %s", PASSWD_PATH, usrname);
        if (system (cmd))
          {
    -@@ contrib/adduser.c: main(void)
    +@@ contrib/adduser.c: main (void)
      #endif
          }
      #ifdef IMMEDIATE_CHANGE
    @@ src/lastlog.c: static void update_one (/*@null@*/const struct passwd *pw)
                                 Prog, (unsigned long)pw->pw_uid);
     
      ## src/login.c ##
    -@@ src/login.c: main(int argc, char **argv)
    +@@ src/login.c: int main (int argc, char **argv)
                unsigned int  failcount = 0;
      
                /* Make the login prompt look like we want it */
    @@ src/login.c: main(int argc, char **argv)
                        SNPRINTF(loginprompt, _("%s login: "), hostn);
                } else {
                        STRTCPY(loginprompt, _("login: "));
    -@@ src/login.c: main(int argc, char **argv)
    +@@ src/login.c: int main (int argc, char **argv)
      #ifdef HAVE_LL_HOST               /* __linux__ || SUN4 */
                        if ('\0' != ll.ll_host[0]) {
                                printf (_(" from %.*s"),
3:  b2b9bbb3 = 3:  9fdffc48 lib/, src/: Remove useless casts in fgets(3)
4:  00db7341 = 4:  d46fd02e lib/, src/: Consistently use NULL with fgets(3)
5:  c1ccbb9a = 5:  1721920a lib/, po/: Remove fgetsx() and fputsx()
6:  9991189d = 6:  664817b3 lib/: Use getline(3) instead of its pattern
7:  51005793 = 7:  a71fc6f3 lib/gshadow.c: fgetsgent(): Don't use static variables
v4c
  • Rebase
$ git range-diff gh/string..gh/fgets string..fgets 
1:  8dbc8149 = 1:  8af482a6 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  ac57816a = 2:  7cae4284 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
3:  9fdffc48 = 3:  410f2492 lib/, src/: Remove useless casts in fgets(3)
4:  d46fd02e = 4:  a0953493 lib/, src/: Consistently use NULL with fgets(3)
5:  1721920a = 5:  9abcea85 lib/, po/: Remove fgetsx() and fputsx()
6:  664817b3 = 6:  dc3819ff lib/: Use getline(3) instead of its pattern
7:  a71fc6f3 = 7:  e49bcf8b lib/gshadow.c: fgetsgent(): Don't use static variables
v4d
  • Rebase
$ git range-diff gh/string..gh/fgets string..fgets 
1:  8af482a6 = 1:  b4a37bc9 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  7cae4284 = 2:  d1abe1ac contrib/, lib/, src/: Consistently use sizeof() as if it were a function
3:  410f2492 = 3:  f388b921 lib/, src/: Remove useless casts in fgets(3)
4:  a0953493 = 4:  31c6c72f lib/, src/: Consistently use NULL with fgets(3)
5:  9abcea85 = 5:  bf0a81e6 lib/, po/: Remove fgetsx() and fputsx()
6:  dc3819ff = 6:  bbbae6af lib/: Use getline(3) instead of its pattern
7:  e49bcf8b = 7:  f7d5cc12 lib/gshadow.c: fgetsgent(): Don't use static variables
v4e
  • Rebase
$ git range-diff gh/string..gh/fgets string..fgets 
1:  b4a37bc9 = 1:  be73a591 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  d1abe1ac = 2:  219af975 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
3:  f388b921 = 3:  691673bc lib/, src/: Remove useless casts in fgets(3)
4:  31c6c72f = 4:  7cb79af6 lib/, src/: Consistently use NULL with fgets(3)
5:  bf0a81e6 = 5:  364b354d lib/, po/: Remove fgetsx() and fputsx()
6:  bbbae6af = 6:  3f398748 lib/: Use getline(3) instead of its pattern
7:  f7d5cc12 = 7:  ef91817e lib/gshadow.c: fgetsgent(): Don't use static variables
v4f
  • Rebase
$ git range-diff gh/string..gh/fgets string..fgets 
1:  be73a591 = 1:  5684988b lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  219af975 = 2:  022f2da0 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
3:  691673bc = 3:  05fe7f89 lib/, src/: Remove useless casts in fgets(3)
4:  7cb79af6 = 4:  5991bd9c lib/, src/: Consistently use NULL with fgets(3)
5:  364b354d = 5:  5cf10040 lib/, po/: Remove fgetsx() and fputsx()
6:  3f398748 = 6:  7e3d5d58 lib/: Use getline(3) instead of its pattern
7:  ef91817e = 7:  27dd9f5c lib/gshadow.c: fgetsgent(): Don't use static variables
v4g
  • Rebase
$ git range-diff 5684988b^..gh/fgets string..fgets 
1:  5684988b = 1:  77e6a686 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  022f2da0 = 2:  c42d9568 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
3:  05fe7f89 = 3:  b67527a6 lib/, src/: Remove useless casts in fgets(3)
4:  5991bd9c = 4:  87af89d8 lib/, src/: Consistently use NULL with fgets(3)
5:  5cf10040 = 5:  375d57a0 lib/, po/: Remove fgetsx() and fputsx()
6:  7e3d5d58 = 6:  d094dc5d lib/: Use getline(3) instead of its pattern
7:  27dd9f5c = 7:  8ef8fc73 lib/gshadow.c: fgetsgent(): Don't use static variables
v4h
  • Rebase
$ git range-diff gh/string..gh/fgets string..fgets 
1:  77e6a686 = 1:  8a8c6635 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  c42d9568 ! 2:  da61e23a contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    @@ lib/tz.c
        if (   (NULL == fp)
     -      || (fgets (tzbuf, sizeof (tzbuf), fp) == NULL)) {
     +      || (fgets(tzbuf, sizeof(tzbuf), fp) == NULL)) {
    -           def_tz = getdef_str ("ENV_TZ");
    -           if ((NULL == def_tz) || ('/' == def_tz[0])) {
    -                   def_tz = "TZ=CST6CDT";
    +           result = "TZ=CST6CDT";
    +   } else {
    +           stpsep(tzbuf, "\n");
     
      ## lib/user_busy.c ##
     @@ lib/user_busy.c: user_busy_utmp(const char *name)
    @@ src/useradd.c: static void lastlog_reset (uid_t uid)
                return;
        }
        if (   (lseek (fd, offset_uid, SEEK_SET) != offset_uid)
    --      || (write_full (fd, &ll, sizeof (ll)) != (ssize_t) sizeof (ll))
    -+      || (write_full(fd, &ll, sizeof(ll)) != (ssize_t) sizeof(ll))
    +-      || (write_full (fd, &ll, sizeof (ll)) == -1)
    ++      || (write_full(fd, &ll, sizeof(ll)) == -1)
            || (fsync (fd) != 0)) {
                fprintf (stderr,
                         _("%s: failed to reset the lastlog entry of UID %lu: %s\n"),
3:  b67527a6 = 3:  9f934b2a lib/, src/: Remove useless casts in fgets(3)
4:  87af89d8 = 4:  8a8620eb lib/, src/: Consistently use NULL with fgets(3)
5:  375d57a0 = 5:  2e696e77 lib/, po/: Remove fgetsx() and fputsx()
6:  d094dc5d = 6:  2375cbfc lib/: Use getline(3) instead of its pattern
7:  8ef8fc73 = 7:  7d2a356c lib/gshadow.c: fgetsgent(): Don't use static variables
v4i
  • Rebase
$ git range-diff gh/string..gh/fgets string..fgets 
1:  8a8c6635 = 1:  c6dabf04 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  da61e23a = 2:  6d57727a contrib/, lib/, src/: Consistently use sizeof() as if it were a function
3:  9f934b2a = 3:  857da077 lib/, src/: Remove useless casts in fgets(3)
4:  8a8620eb = 4:  db2b027d lib/, src/: Consistently use NULL with fgets(3)
5:  2e696e77 = 5:  c8645b33 lib/, po/: Remove fgetsx() and fputsx()
6:  2375cbfc = 6:  8d9b55dd lib/: Use getline(3) instead of its pattern
7:  7d2a356c = 7:  b5663560 lib/gshadow.c: fgetsgent(): Don't use static variables
v4j
  • Rebase
$ git range-diff gh/string..gh/fgets string..fgets 
1:  c6dabf04 = 1:  2ff6e318 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  6d57727a = 2:  6faa0944 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
3:  857da077 = 3:  ee315ddc lib/, src/: Remove useless casts in fgets(3)
4:  db2b027d = 4:  876c36d1 lib/, src/: Consistently use NULL with fgets(3)
5:  c8645b33 = 5:  5fc868e2 lib/, po/: Remove fgetsx() and fputsx()
6:  8d9b55dd = 6:  f7ac2b0a lib/: Use getline(3) instead of its pattern
7:  b5663560 = 7:  9fd4a0b3 lib/gshadow.c: fgetsgent(): Don't use static variables
v4k
  • Rebase
$ git range-diff gh/string..gh/fgets string..fgets 
1:  2ff6e318 = 1:  2b6a1413 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  6faa0944 ! 2:  61bc9a04 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    @@ lib/log.c: void dolastlog (
      
     
      ## lib/loginprompt.c ##
    -@@ lib/loginprompt.c: login_prompt(char *name, int namesize)
    +@@ lib/loginprompt.c: void login_prompt (char *name, int namesize)
                        (void) fclose (fp);
                }
        }
    @@ lib/loginprompt.c: login_prompt(char *name, int namesize)
        printf (_("\n%s login: "), buf);
        (void) fflush (stdout);
      
    -@@ lib/loginprompt.c: login_prompt(char *name, int namesize)
    +@@ lib/loginprompt.c: void login_prompt (char *name, int namesize)
         */
      
        MEMZERO(buf);
3:  ee315ddc = 3:  ca165ccf lib/, src/: Remove useless casts in fgets(3)
4:  876c36d1 ! 4:  8929e11e lib/, src/: Consistently use NULL with fgets(3)
    @@ lib/loginprompt.c
      
      #include "attr.h"
      #include "defines.h"
    -@@ lib/loginprompt.c: login_prompt(char *name, int namesize)
    +@@ lib/loginprompt.c: void login_prompt (char *name, int namesize)
         */
      
        MEMZERO(buf);
5:  5fc868e2 = 5:  fee111ca lib/, po/: Remove fgetsx() and fputsx()
6:  f7ac2b0a = 6:  08d1534f lib/: Use getline(3) instead of its pattern
7:  9fd4a0b3 = 7:  b6b6a6b5 lib/gshadow.c: fgetsgent(): Don't use static variables
v4l
  • Rebase
$ git range-diff gh/string..gh/fgets string..fgets 
1:  2b6a1413 = 1:  ea9f29ec lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  61bc9a04 = 2:  e628440c contrib/, lib/, src/: Consistently use sizeof() as if it were a function
3:  ca165ccf = 3:  dec51b42 lib/, src/: Remove useless casts in fgets(3)
4:  8929e11e = 4:  e63fef58 lib/, src/: Consistently use NULL with fgets(3)
5:  fee111ca = 5:  5fe14748 lib/, po/: Remove fgetsx() and fputsx()
6:  08d1534f = 6:  0dc3bf45 lib/: Use getline(3) instead of its pattern
7:  b6b6a6b5 = 7:  d3278c53 lib/gshadow.c: fgetsgent(): Don't use static variables
v5
  • Several rebases
$ git range-diff string..fgets gh/string..gh/fgets 
1:  ea9f29ec = 1:  bbde7826 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  e628440c ! 2:  e1d0706a contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    @@ lib/getdef.c: struct itemdef {
      static struct itemdef def_table[] = {
        {"CHFN_RESTRICT", NULL},
        {"CONSOLE_GROUPS", NULL},
    -@@ lib/getdef.c: static struct itemdef def_table[] = {
    -   {NULL, NULL}
    - };
    - 
    --#define NUMKNOWNDEFS      (sizeof(knowndef_table)/sizeof(knowndef_table[0]))
    -+#define NUMKNOWNDEFS  (sizeof(knowndef_table) / sizeof(knowndef_table[0]))
    - static struct itemdef knowndef_table[] = {
    - #ifdef USE_PAM
    -   PAMDEFS
     @@ lib/getdef.c: static void def_load (void)
        /*
         * Go through all of the lines in the file.
    @@ lib/log.c: void dolastlog (
      
     
      ## lib/loginprompt.c ##
    -@@ lib/loginprompt.c: void login_prompt (char *name, int namesize)
    +@@ lib/loginprompt.c: login_prompt(char *name, int namesize)
                        (void) fclose (fp);
                }
        }
    @@ lib/loginprompt.c: void login_prompt (char *name, int namesize)
        printf (_("\n%s login: "), buf);
        (void) fflush (stdout);
      
    -@@ lib/loginprompt.c: void login_prompt (char *name, int namesize)
    +@@ lib/loginprompt.c: login_prompt(char *name, int namesize)
         */
      
        MEMZERO(buf);
    @@ lib/subordinateio.c: subordinate_parse(const char *line)
        strcpy (rangebuf, line);
      
     
    - ## lib/tcbfuncs.c ##
    -@@ lib/tcbfuncs.c: static /*@null@*/ char *shadowtcb_path_rel_existing (const char *name)
    -           free (path);
    -           return NULL;
    -   }
    --  ret = readlink (path, link, sizeof (link) - 1);
    -+  ret = readlink(path, link, sizeof(link) - 1);
    -   if (-1 == ret) {
    -           fprintf (shadow_logfd,
    -                    _("%s: Cannot read symbolic link %s: %s\n"),
    -
      ## lib/ttytype.c ##
     @@ lib/ttytype.c: void ttytype (const char *line)
                        perror (typefile);
    @@ lib/user_busy.c: user_busy_utmp(const char *name)
                        continue;
                }
                if (kill (utent->ut_pid, 0) != 0) {
    -@@ lib/user_busy.c: static int different_namespace (const char *sname)
    - 
    -   SNPRINTF(path, "/proc/%s/ns/user", sname);
    - 
    --  if ((llen1 = readlink (path, buf, sizeof(buf))) == -1)
    -+  if ((llen1 = readlink(path, buf, sizeof(buf))) == -1)
    -           return 0;
    - 
    --  if ((llen2 = readlink ("/proc/self/ns/user", buf2, sizeof(buf2))) == -1)
    -+  if ((llen2 = readlink("/proc/self/ns/user", buf2, sizeof(buf2))) == -1)
    -           return 0;
    - 
    -   if (llen1 == llen2 && memcmp (buf, buf2, llen1) == 0)
     @@ lib/user_busy.c: static int check_status (const char *name, const char *sname, uid_t uid)
        if (NULL == sfile) {
                return 0;
3:  dec51b42 = 3:  1cf6b14d lib/, src/: Remove useless casts in fgets(3)
4:  e63fef58 ! 4:  3fc6e9ed lib/, src/: Consistently use NULL with fgets(3)
    @@ lib/loginprompt.c
      
      #include "attr.h"
      #include "defines.h"
    -@@ lib/loginprompt.c: void login_prompt (char *name, int namesize)
    +@@ lib/loginprompt.c: login_prompt(char *name, int namesize)
         */
      
        MEMZERO(buf);
5:  5fe14748 ! 5:  79adfd9d lib/, po/: Remove fgetsx() and fputsx()
    @@ lib/Makefile.am: libshadow_la_SOURCES = \
        find_new_sub_gids.c \
        find_new_sub_uids.c \
     -  fputsx.c \
    -   get_pid.c \
    -   getdate.h \
    -   getdate.y \
    +   fs/readlink/areadlink.c \
    +   fs/readlink/areadlink.h \
    +   fs/readlink/readlinknul.c \
     
      ## lib/commonio.c ##
     @@ lib/commonio.c: int commonio_open (struct commonio_db *db, int mode)
6:  0dc3bf45 = 6:  5bac295b lib/: Use getline(3) instead of its pattern
7:  d3278c53 = 7:  b3acc480 lib/gshadow.c: fgetsgent(): Don't use static variables
v5b
  • Rebase
$ git range-diff gh/string..gh/fgets string..fgets 
1:  bbde7826 < -:  -------- lib/gshadow.c: endsgent(): Invert logic to reduce indentation
2:  e1d0706a = 1:  045fcee5 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
3:  1cf6b14d = 2:  fafa51f2 lib/, src/: Remove useless casts in fgets(3)
4:  3fc6e9ed = 3:  cddf585c lib/, src/: Consistently use NULL with fgets(3)
5:  79adfd9d = 4:  ff64b68b lib/, po/: Remove fgetsx() and fputsx()
6:  5bac295b = 5:  7bd6a873 lib/: Use getline(3) instead of its pattern
7:  b3acc480 = 6:  0ea5edc8 lib/gshadow.c: fgetsgent(): Don't use static variables
v5c
  • Rebase
$ git range-diff gh/string..gh/fgets string..fgets 
1:  045fcee5 ! 1:  8f180904 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    @@ lib/sgetspent.c: sgetspent(const char *string)
                         shadow_progname);
     
      ## lib/shadow.c ##
    -@@ lib/shadow.c: my_sgetspent(const char *string)
    -    * have to do that to our private copy.
    -    */
    - 
    --  if (strlen (string) >= sizeof spwbuf)
    -+  if (strlen(string) >= sizeof(spwbuf))
    -           return 0;
    -   strcpy (spwbuf, string);
    -   stpsep(spwbuf, "\n");
     @@ lib/shadow.c: struct spwd *fgetspent (FILE * fp)
                return (0);
        }
    @@ lib/shadow.c: struct spwd *fgetspent (FILE * fp)
     +  if (fgets(buf, sizeof(buf), fp) != NULL)
        {
                stpsep(buf, "\n");
    -           return my_sgetspent (buf);
    +           return sgetspent(buf);
     
      ## lib/subordinateio.c ##
     @@ lib/subordinateio.c: subordinate_parse(const char *line)
    @@ src/groupmod.c: grp_update(void)
     
      ## src/grpconv.c ##
     @@ src/grpconv.c: int main (int argc, char **argv)
    -                   static char *empty = 0;
    +                   static char *empty = NULL;
      
                        /* add new shadow group entry */
     -                  bzero(&sgent, sizeof sgent);
2:  fafa51f2 = 2:  afb1c131 lib/, src/: Remove useless casts in fgets(3)
3:  cddf585c ! 3:  188be985 lib/, src/: Consistently use NULL with fgets(3)
    @@ lib/fputsx.c: fgetsx(/*@returned@*/char *restrict buf, int cnt, FILE *restrict f
     -          if (fgets (cp, cnt, f) != cp) {
     +          if (fgets(cp, cnt, f) == NULL) {
                        if (cp == buf) {
    --                          return 0;
    -+                          return NULL;
    +                           return NULL;
                        } else {
    -                           break;
    -                   }
     
      ## lib/getdate.y ##
     @@
4:  ff64b68b = 4:  85fe221b lib/, po/: Remove fgetsx() and fputsx()
5:  7bd6a873 = 5:  917c4cbd lib/: Use getline(3) instead of its pattern
6:  0ea5edc8 = 6:  4997bf3c lib/gshadow.c: fgetsgent(): Don't use static variables
v5d
  • Rebase
  • $ git range-diff 4443b615..gh/fgets string..fgets 
    1:  8f180904 ! 1:  b218e332 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
        @@ lib/console.c: is_listed(const char *cfgin, const char *tty, bool def)
         -  while (fgets (buf, sizeof (buf), fp) != NULL) {
         +  while (fgets(buf, sizeof(buf), fp) != NULL) {
                    stpsep(buf, "\n");
        -           if (strcmp (buf, tty) == 0) {
        +           if (streq(buf, tty)) {
                            (void) fclose (fp);
         
          ## lib/copydir.c ##
        @@ lib/hushed.c: bool hushed (const char *username)
         -  for (found = false; !found && (fgets (buf, sizeof buf, fp) == buf);) {
         +  for (found = false; !found && (fgets(buf, sizeof(buf), fp) == buf);) {
                    stpsep(buf, "\n");
        -           found = (strcmp (buf, pw->pw_shell) == 0) ||
        -                   (strcmp (buf, pw->pw_name) == 0);
        +           found = streq(buf, pw->pw_shell) ||
        +                   streq(buf, pw->pw_name);
         
          ## lib/log.c ##
         @@ lib/log.c: void dolastlog (
        @@ src/chage.c: static int new_fields (void)
         -  change_field (buf, sizeof buf, _("Last Password Change (YYYY-MM-DD)"));
         +  change_field(buf, sizeof(buf), _("Last Password Change (YYYY-MM-DD)"));
          
        -   if (strcmp (buf, "-1") == 0) {
        +   if (streq(buf, "-1")) {
                    lstchgdate = -1;
         @@ src/chage.c: static int new_fields (void)
            }
        @@ src/chage.c: static int new_fields (void)
         +  change_field(buf, sizeof(buf),
                          _("Account Expiration Date (YYYY-MM-DD)"));
          
        -   if (strcmp (buf, "-1") == 0) {
        +   if (streq(buf, "-1")) {
         @@ src/chage.c: static void update_age (/*@null@*/const struct spwd *sp,
            if (NULL == sp) {
                    struct passwd pwent = *pw;
    2:  afb1c131 = 2:  5747fddc lib/, src/: Remove useless casts in fgets(3)
    3:  188be985 ! 3:  76ad76fd lib/, src/: Consistently use NULL with fgets(3)
        @@ lib/hushed.c: bool hushed (const char *username)
         -  for (found = false; !found && (fgets(buf, sizeof(buf), fp) == buf);) {
         +  for (found = false; !found && (fgets(buf, sizeof(buf), fp) != NULL);) {
                    stpsep(buf, "\n");
        -           found = (strcmp (buf, pw->pw_shell) == 0) ||
        -                   (strcmp (buf, pw->pw_name) == 0);
        +           found = streq(buf, pw->pw_shell) ||
        +                   streq(buf, pw->pw_name);
         
          ## lib/loginprompt.c ##
         @@
    4:  85fe221b = 4:  2b584c1d lib/, po/: Remove fgetsx() and fputsx()
    5:  917c4cbd = 5:  2b0dced9 lib/: Use getline(3) instead of its pattern
    6:  4997bf3c = 6:  decea534 lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5e
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  b218e332 = 1:  d735f06d contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    2:  5747fddc = 2:  bc48d436 lib/, src/: Remove useless casts in fgets(3)
    3:  76ad76fd = 3:  de5d37f4 lib/, src/: Consistently use NULL with fgets(3)
    4:  2b584c1d = 4:  433653dc lib/, po/: Remove fgetsx() and fputsx()
    5:  2b0dced9 = 5:  b7014a18 lib/: Use getline(3) instead of its pattern
    6:  decea534 = 6:  55705d75 lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5f
    • Rebase
    $ git range-diff d735f06df02a^..gh/fgets string..fgets 
    1:  d735f06d = 1:  10a97f1a contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    2:  bc48d436 = 2:  2edf4077 lib/, src/: Remove useless casts in fgets(3)
    3:  de5d37f4 = 3:  2e7b5948 lib/, src/: Consistently use NULL with fgets(3)
    4:  433653dc = 4:  88978371 lib/, po/: Remove fgetsx() and fputsx()
    5:  b7014a18 = 5:  9ba864e1 lib/: Use getline(3) instead of its pattern
    6:  55705d75 = 6:  00a84c7c lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5g
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets  
    1:  10a97f1a = 1:  6b1f4504 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    2:  2edf4077 = 2:  e019f028 lib/, src/: Remove useless casts in fgets(3)
    3:  2e7b5948 = 3:  bb286988 lib/, src/: Consistently use NULL with fgets(3)
    4:  88978371 = 4:  df5e91b2 lib/, po/: Remove fgetsx() and fputsx()
    5:  9ba864e1 = 5:  8319879d lib/: Use getline(3) instead of its pattern
    6:  00a84c7c = 6:  8533575c lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5h
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  6b1f4504 = 1:  c5662ba2 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    2:  e019f028 = 2:  c98032d3 lib/, src/: Remove useless casts in fgets(3)
    3:  bb286988 = 3:  8bd9acd7 lib/, src/: Consistently use NULL with fgets(3)
    4:  df5e91b2 = 4:  1df2aa5a lib/, po/: Remove fgetsx() and fputsx()
    5:  8319879d = 5:  964e080e lib/: Use getline(3) instead of its pattern
    6:  8533575c = 6:  5a9bf7fe lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5i
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  c5662ba2 ! 1:  65450ddd contrib/, lib/, src/: Consistently use sizeof() as if it were a function
        @@ src/login_nopam.c: login_access(const char *user, const char *from)
         @@ src/login_nopam.c: myhostname(void)
            static char name[MAXHOSTNAMELEN + 1] = "";
          
        -   if (strcmp(name, "") == 0) {
        +   if (streq(name, "")) {
         -          gethostname (name, sizeof (name));
         +          gethostname(name, sizeof(name));
                    stpcpy(&name[MAXHOSTNAMELEN], "");
    2:  c98032d3 = 2:  e7a79bec lib/, src/: Remove useless casts in fgets(3)
    3:  8bd9acd7 = 3:  8f8351b5 lib/, src/: Consistently use NULL with fgets(3)
    4:  1df2aa5a = 4:  bf670236 lib/, po/: Remove fgetsx() and fputsx()
    5:  964e080e = 5:  7d38ceda lib/: Use getline(3) instead of its pattern
    6:  5a9bf7fe = 6:  4c8d340c lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5j
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  65450ddd = 1:  551780b3 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    2:  e7a79bec = 2:  00e3d101 lib/, src/: Remove useless casts in fgets(3)
    3:  8f8351b5 ! 3:  def7bd46 lib/, src/: Consistently use NULL with fgets(3)
        @@ lib/loginprompt.c: login_prompt(char *name, int namesize)
         
          ## lib/setupenv.c ##
         @@
        + #ident "$Id$"
          
          #include <assert.h>
        - #include <ctype.h>
         +#include <stddef.h>
        - #include <stdio.h>
        - #include <string.h>
          #include <sys/types.h>
        + #include <sys/stat.h>
        + #include <stdio.h>
         @@ lib/setupenv.c: static void read_env_file (const char *filename)
            if (NULL == fp) {
                    return;
    4:  bf670236 = 4:  361e2d27 lib/, po/: Remove fgetsx() and fputsx()
    5:  7d38ceda = 5:  4b73c980 lib/: Use getline(3) instead of its pattern
    6:  4c8d340c = 6:  29f75cf2 lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5k
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  551780b3 ! 1:  9595d531 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
        @@ src/login_nopam.c: login_access(const char *user, const char *from)
                    {
                            char  *p;
          
        -@@ src/login_nopam.c: myhostname(void)
        +@@ src/login_nopam.c: static char *myhostname (void)
            static char name[MAXHOSTNAMELEN + 1] = "";
          
            if (streq(name, "")) {
    2:  00e3d101 = 2:  39b4a028 lib/, src/: Remove useless casts in fgets(3)
    3:  def7bd46 = 3:  52aee4d3 lib/, src/: Consistently use NULL with fgets(3)
    4:  361e2d27 = 4:  b219136c lib/, po/: Remove fgetsx() and fputsx()
    5:  4b73c980 = 5:  df79b8fc lib/: Use getline(3) instead of its pattern
    6:  29f75cf2 = 6:  a371b78b lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5l
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  9595d531 = 1:  8be05fda contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    2:  39b4a028 = 2:  3620b3d5 lib/, src/: Remove useless casts in fgets(3)
    3:  52aee4d3 = 3:  d5f7872a lib/, src/: Consistently use NULL with fgets(3)
    4:  b219136c = 4:  779f70be lib/, po/: Remove fgetsx() and fputsx()
    5:  df79b8fc = 5:  240124a5 lib/: Use getline(3) instead of its pattern
    6:  a371b78b = 6:  714a2b14 lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5m
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  8be05fda = 1:  e07132f5 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    2:  3620b3d5 = 2:  93f18f76 lib/, src/: Remove useless casts in fgets(3)
    3:  d5f7872a = 3:  dc657761 lib/, src/: Consistently use NULL with fgets(3)
    4:  779f70be ! 4:  3aa23780 lib/, po/: Remove fgetsx() and fputsx()
        @@ lib/fputsx.c (deleted)
         -
         -#include "defines.h"
         -#include "prototypes.h"
        --
        --#ident "$Id$"
        +-#include "string/strcmp/streq.h"
         -
         -
         -/*@null@*/char *
        @@ lib/fputsx.c (deleted)
         -{
         -  int i;
         -
        --  for (i = 0; '\0' != *s; i++, s++) {
        +-  for (i = 0; !streq(s, ""); i++, s++) {
         -          if (putc (*s, stream) == EOF) {
         -                  return EOF;
         -          }
    5:  240124a5 = 5:  67f45381 lib/: Use getline(3) instead of its pattern
    6:  714a2b14 = 6:  8b45ec41 lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5n
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  e07132f5 = 1:  80694cff contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    2:  93f18f76 ! 2:  30f2f88d lib/, src/: Remove useless casts in fgets(3)
        @@ lib/commonio.c: int commonio_open (struct commonio_db *db, int mode)
                    }
         
          ## lib/gshadow.c ##
        -@@ lib/gshadow.c: void endsgent (void)
        +@@ lib/gshadow.c: sgetsgent(const char *string)
                    buflen *= 2;
          
                    len = strlen (buf);
    3:  dc657761 ! 3:  3ac49d36 lib/, src/: Consistently use NULL with fgets(3)
        @@ lib/getdate.y: main(void)
                if (d == -1)
         
          ## lib/gshadow.c ##
        -@@ lib/gshadow.c: void endsgent (void)
        +@@ lib/gshadow.c: sgetsgent(const char *string)
                    buflen *= 2;
          
                    len = strlen (buf);
    4:  3aa23780 ! 4:  6c058335 lib/, po/: Remove fgetsx() and fputsx()
        @@ lib/groupio.c: static struct commonio_ops group_ops = {
          };
         
          ## lib/gshadow.c ##
        -@@ lib/gshadow.c: void endsgent (void)
        +@@ lib/gshadow.c: sgetsgent(const char *string)
                    return NULL;
            }
          
        @@ lib/gshadow.c: void endsgent (void)
                    return NULL;
          
            while (   (strrchr(buf, '\n') == NULL)
        -@@ lib/gshadow.c: void endsgent (void)
        +@@ lib/gshadow.c: sgetsgent(const char *string)
                    buflen *= 2;
          
                    len = strlen (buf);
    5:  67f45381 ! 5:  377e0abd lib/: Use getline(3) instead of its pattern
        @@ lib/commonio.c: int commonio_open (struct commonio_db *db, int mode)
           */
         
          ## lib/gshadow.c ##
        -@@ lib/gshadow.c: void endsgent (void)
        +@@ lib/gshadow.c: sgetsgent(const char *string)
            return &sgroup;
          }
          
        @@ lib/gshadow.c: void endsgent (void)
          /*
           * fgetsgent - convert next line in stream to (struct sgrp)
           *
        -@@ lib/gshadow.c: void endsgent (void)
        +@@ lib/gshadow.c: sgetsgent(const char *string)
           * converts it to a (struct sgrp).  NULL is returned on EOF.
           */
          
    6:  8b45ec41 ! 6:  b9658b23 lib/gshadow.c: fgetsgent(): Don't use static variables
        @@ Commit message
             Signed-off-by: Alejandro Colomar <[email protected]>
         
          ## lib/gshadow.c ##
        -@@ lib/gshadow.c: void endsgent (void)
        +@@ lib/gshadow.c: sgetsgent(const char *string)
          /*@observer@*//*@null@*/struct sgrp *
          fgetsgent(/*@null@*/FILE *fp)
          {
    
    v5o
    • Rebase
    $ git range-diff 80694cff^..gh/fgets string..fgets 
    1:  80694cff ! 1:  90aa5f8b contrib/, lib/, src/: Consistently use sizeof() as if it were a function
        @@ lib/user_busy.c: static int check_status (const char *name, const char *sname, u
            }
         -  while (fgets (line, sizeof (line), sfile) == line) {
         +  while (fgets(line, sizeof(line), sfile) == line) {
        -           if (strncmp (line, "Uid:\t", 5) == 0) {
        +           if (strprefix(line, "Uid:\t")) {
                            unsigned long ruid, euid, suid;
          
         
    2:  30f2f88d = 2:  33373c47 lib/, src/: Remove useless casts in fgets(3)
    3:  3ac49d36 ! 3:  7d30f553 lib/, src/: Consistently use NULL with fgets(3)
        @@ lib/user_busy.c: static int check_status (const char *name, const char *sname, u
            }
         -  while (fgets(line, sizeof(line), sfile) == line) {
         +  while (fgets(line, sizeof(line), sfile) != NULL) {
        -           if (strncmp (line, "Uid:\t", 5) == 0) {
        +           if (strprefix(line, "Uid:\t")) {
                            unsigned long ruid, euid, suid;
          
         
    4:  6c058335 = 4:  3894a987 lib/, po/: Remove fgetsx() and fputsx()
    5:  377e0abd = 5:  62fbb8e1 lib/: Use getline(3) instead of its pattern
    6:  b9658b23 = 6:  1e3d7afa lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5p
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  90aa5f8b ! 1:  e2f46820 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
        @@ contrib/adduser.c: main (void)
         -      safeget (foo, sizeof (foo));
         +      safeget(foo, sizeof(foo));
          
        -       done = bad = correct = (foo[0] == 'y' || foo[0] == 'Y');
        +       done = bad = correct = (strprefix(foo, "y") || strprefix(foo, "Y"));
          
         @@ contrib/adduser.c: main (void)
          
        @@ lib/ttytype.c: void ttytype (const char *line)
            }
         -  while (fgets (buf, sizeof buf, fp) == buf) {
         +  while (fgets(buf, sizeof(buf), fp) == buf) {
        -           if (buf[0] == '#') {
        +           if (strprefix(buf, "#")) {
                            continue;
                    }
         
    2:  33373c47 = 2:  12cf176f lib/, src/: Remove useless casts in fgets(3)
    3:  7d30f553 ! 3:  0320b6ea lib/, src/: Consistently use NULL with fgets(3)
        @@ lib/ttytype.c: void ttytype (const char *line)
            }
         -  while (fgets(buf, sizeof(buf), fp) == buf) {
         +  while (fgets(buf, sizeof(buf), fp) != NULL) {
        -           if (buf[0] == '#') {
        +           if (strprefix(buf, "#")) {
                            continue;
                    }
         
    4:  3894a987 = 4:  fd585453 lib/, po/: Remove fgetsx() and fputsx()
    5:  62fbb8e1 = 5:  93239c4a lib/: Use getline(3) instead of its pattern
    6:  1e3d7afa = 6:  3261e283 lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5q
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  e2f46820 = 1:  5f807312 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    2:  12cf176f = 2:  d008c70a lib/, src/: Remove useless casts in fgets(3)
    3:  0320b6ea = 3:  78e34e84 lib/, src/: Consistently use NULL with fgets(3)
    4:  fd585453 = 4:  7c492df2 lib/, po/: Remove fgetsx() and fputsx()
    5:  93239c4a = 5:  22a830bc lib/: Use getline(3) instead of its pattern
    6:  3261e283 = 6:  8d1c561a lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5r
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  5f807312 = 1:  bdec46cf contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    2:  d008c70a = 2:  af0903a9 lib/, src/: Remove useless casts in fgets(3)
    3:  78e34e84 = 3:  ce5cea23 lib/, src/: Consistently use NULL with fgets(3)
    4:  7c492df2 = 4:  cab93702 lib/, po/: Remove fgetsx() and fputsx()
    5:  22a830bc = 5:  3293e367 lib/: Use getline(3) instead of its pattern
    6:  8d1c561a = 6:  f0b6756c lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5s
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  bdec46cf ! 1:  f8d0c008 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
        @@ src/chgpasswd.c: int main (int argc, char **argv)
                            fprintf (stderr, _("%s: line %d: line too long\n"),
         
          ## src/chpasswd.c ##
        -@@ src/chpasswd.c: main(int argc, char **argv)
        +@@ src/chpasswd.c: int main (int argc, char **argv)
             * last change date is set in the age only if aging information is
             * present.
             */
        @@ src/chpasswd.c: main(int argc, char **argv)
                                    // Drop all remaining characters on this line.
         -                          while (fgets (buf, sizeof buf, stdin) != NULL) {
         +                          while (fgets(buf, sizeof(buf), stdin) != NULL) {
        -                                   if (!!strchr(buf, '\n'))
        +                                   if (strchr(buf, '\n'))
                                                    break;
                                    }
         
    2:  af0903a9 = 2:  8e9867a3 lib/, src/: Remove useless casts in fgets(3)
    3:  ce5cea23 = 3:  218faac9 lib/, src/: Consistently use NULL with fgets(3)
    4:  cab93702 = 4:  45ce40e0 lib/, po/: Remove fgetsx() and fputsx()
    5:  3293e367 = 5:  1f221414 lib/: Use getline(3) instead of its pattern
    6:  f0b6756c = 6:  38b17e29 lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5t
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  f8d0c008 = 1:  a320dadc contrib/, lib/, src/: Consistently use sizeof() as if it were a function
    2:  8e9867a3 = 2:  23a841d9 lib/, src/: Remove useless casts in fgets(3)
    3:  218faac9 = 3:  cbc5d2e2 lib/, src/: Consistently use NULL with fgets(3)
    4:  45ce40e0 = 4:  453d6fde lib/, po/: Remove fgetsx() and fputsx()
    5:  1f221414 = 5:  f3ea5c75 lib/: Use getline(3) instead of its pattern
    6:  38b17e29 = 6:  08d68d10 lib/gshadow.c: fgetsgent(): Don't use static variables
    
    v5u
    • Rebase
    $ git range-diff gh/string..gh/fgets string..fgets 
    1:  a320dadc ! 1:  4b9d2f28 contrib/, lib/, src/: Consistently use sizeof() as if it were a function
        @@ src/chgpasswd.c: int main (int argc, char **argv)
         +  while (fgets(buf, (int) sizeof(buf), stdin) != NULL) {
                    line++;
                    if (stpsep(buf, "\n") == NULL) {
        -                   fprintf (stderr, _("%s: line %d: line too long\n"),
        +                   fprintf (stderr, _("%s: line %jd: line too long\n"),
         
          ## src/chpasswd.c ##
         @@ src/chpasswd.c: int main (int argc, char **argv)
        @@ src/login.c: int main (int argc, char **argv)
          ## src/login_nopam.c ##
         @@ src/login_nopam.c: login_access(const char *user, const char *from)
            if (NULL != fp) {
        -           int lineno = 0; /* for diagnostics */
        +           intmax_t lineno = 0;    /* for diagnostics */
                    while (   !match
         -                 && (fgets (line, sizeof (line), fp) == line))
         +                 && (fgets(line, sizeof(line), fp) == line))
        @@ src/newusers.c: int main (int argc, char **argv)
         +  while (fgets(buf, sizeof(buf), stdin) != NULL) {
                    line++;
                    if (stpsep(buf, "\n") == NULL && feof(stdin) == 0) {
        -                   fprintf (stderr, _("%s: line %d: line too long\n"),
        +                   fprintf (stderr, _("%s: line %jd: line too long\n"),
         
          ## src/pwconv.c ##
         @@ src/pwconv.c: int main (int argc, char **argv)
    2:  23a841d9 ! 2:  8579d59f lib/, src/: Remove useless casts in fgets(3)
        @@ src/chgpasswd.c: int main (int argc, char **argv)
         +  while (fgets(buf, sizeof(buf), stdin) != NULL) {
                    line++;
                    if (stpsep(buf, "\n") == NULL) {
        -                   fprintf (stderr, _("%s: line %d: line too long\n"),
        +                   fprintf (stderr, _("%s: line %jd: line too long\n"),
    3:  cbc5d2e2 ! 3:  7912afb8 lib/, src/: Consistently use NULL with fgets(3)
        @@ lib/user_busy.c: static int check_status (const char *name, const char *sname, u
          ## src/login_nopam.c ##
         @@ src/login_nopam.c: login_access(const char *user, const char *from)
            if (NULL != fp) {
        -           int lineno = 0; /* for diagnostics */
        +           intmax_t lineno = 0;    /* for diagnostics */
                    while (   !match
         -                 && (fgets(line, sizeof(line), fp) == line))
         +                 && (fgets(line, sizeof(line), fp) != NULL))
    4:  453d6fde = 4:  02cdc1c8 lib/, po/: Remove fgetsx() and fputsx()
    5:  f3ea5c75 = 5:  cff254db lib/: Use getline(3) instead of its pattern
    6:  08d68d10 = 6:  4cbd4be7 lib/gshadow.c: fgetsgent(): Don't use static variables
    

    @alejandro-colomar alejandro-colomar marked this pull request as ready for review July 21, 2024 17:01
    @alejandro-colomar alejandro-colomar marked this pull request as draft July 21, 2024 17:01
    lib/gshadow.c Outdated
    Comment on lines 158 to 177
    if (fgetsx(buf, buflen, fp) == buf) {
    while ( ((cp = strrchr (buf, '\n')) == NULL)
    && (feof (fp) == 0)) {
    size_t len;

    cp = REALLOC(buf, buflen * 2, char);
    if (NULL == cp) {
    return NULL;
    }
    buf = cp;
    buflen *= 2;

    len = strlen (buf);
    if (fgetsx (&buf[len],
    (int) (buflen - len),
    fp) != &buf[len]) {
    return NULL;
    }
    if (fgets(buf, buflen, fp) == NULL)
    return NULL;

    while ( (strrchr(buf, '\n') == NULL)
    && (feof (fp) == 0)) {
    size_t len;

    cp = REALLOC(buf, buflen * 2, char);
    if (NULL == cp) {
    return NULL;
    }
    stpsep(buf, "\n");
    return (sgetsgent (buf));
    buf = cp;
    buflen *= 2;

    len = strlen (buf);
    if (fgets(&buf[len], buflen - len, fp) == NULL)
    return NULL;
    }
    return NULL;
    stpsep(buf, "\n");
    return (sgetsgent (buf));
    Copy link
    Collaborator Author

    @alejandro-colomar alejandro-colomar Jul 22, 2024

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    @thesamesam

    Hi Sam,

    It might be worth commenting this here.

    Here's an overview of the branch:

    $ git log --oneline master..fgets 
    cd64d530 (HEAD -> fgets, gh/fgets) lib/, po/: Remove fgetsx() and fputsx()
    941c951c lib/, src/: Remove useless casts in fgets(3)
    4d66df60 lib/, src/: Consistently use NULL with fgets(3)
    d0cdc9c8 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
    a719bc39 (gh/string, string) lib/fields.c: Remove dead code
    b71d2236 contrib/, lib/, src/: Use consistent style using strchr(3) in conditionals
    44df1083 lib/, src/: Use str[n]cmp(3) instead of explicit byte comparisons
    d3350b67 contrib/, lib/, src/: Use strchr(3) to compact comparisons
    9a6e3284 lib/loginprompt.c: login_prompt(): Use strtcpy() instead of its pattern
    db93a222 lib/, src/: Use strsep(3) instead of strtok(3)
    376e4166 src/suauth.c: check_su_auth(): Use pointers to simplify
    ae1c284e src/suauth.c: check_su_auth(): Use strspn(3) instead of its pattern
    93362cc3 lib/gshadow.c: endsgent(): Remove dead assignment
    5a46723a lib/port.c: portcmp(): Use strcmp(3) instead of its pattern
    7442a127 lib/, src/: Use stpspn() instead of its pattern
    

    This fgets branch is really only

    $ git log --oneline string..fgets 
    cd64d530 (HEAD -> fgets, gh/fgets) lib/, po/: Remove fgetsx() and fputsx()
    941c951c lib/, src/: Remove useless casts in fgets(3)
    4d66df60 lib/, src/: Consistently use NULL with fgets(3)
    d0cdc9c8 lib/gshadow.c: endsgent(): Invert logic to reduce indentation
    

    but I based it on string, which corresponds to PR #1048.

    Here's why. Basically, according to the bug report that it closes, the PR is about replacing fgetsx => fgets. Here are two of the calls that we replace:

    $ grep -rnC4 fgetsx lib/gshadow.c
    154-	if (NULL == fp) {
    155-		return NULL;
    156-	}
    157-
    158:	if (fgetsx(buf, buflen, fp) == buf) {
    159-		while (   ((cp = strrchr (buf, '\n')) == NULL)
    160-		       && (feof (fp) == 0)) {
    161-			size_t len;
    162-
    --
    167-			buf = cp;
    168-			buflen *= 2;
    169-
    170-			len = strlen (buf);
    171:			if (fgetsx (&buf[len],
    172-			            (int) (buflen - len),
    173-			            fp) != &buf[len]) {
    174-				return NULL;
    175-			}

    I want to fully understand what the code is doing before doing the change, which makes me more confident that the change is correct. To that end, I need to reduce superfluous complexity.

    In the code above, you may notice a dead assignment:

    159-		while (   ((cp = strrchr (buf, '\n')) == NULL)

    I already had removed that dead assignment in #1048 in commit 93362cc. That's the only reason why I decided to base it on that PR.

    Now let's see why this PR has 4 new commits, instead of 1.

    Line

    158:	if (fgetsx(buf, buflen, fp) == buf) {

    Has a conditional that spans the entire rest of the function. Commit 1 turns this into the usual thing, which is an early return on error.

    Then we get to

    171:			if (fgetsx (&buf[len],
    172-			            (int) (buflen - len),
    173-			            fp) != &buf[len]) {

    Why do we have that cast? It's nonsense. I'll remove it.
    And also &buf[len] is very brittle, and a small typo could add a bug here. Let's use NULL there.

    While doing those two changes, I'll check any other places that do similarly bad stuff, and replace it in the entire code base. Then commit 4 does what we originally wanted.

    I don't reason too much the first 3 commits, which you might find frustrating while reviewing the changes a posteriori. I didn't because they're not the main purpose of the PR; they're just trivial cosmetic changes in preparation for the PR. And it's usual to apply cosmetic patches as the first patches in a patch set, to prepare for the important ones.

    Do you have any suggestions for making it easier for you to review the changes later?

    Maybe I could add an explicit [cosmetic] in the second line of the commit message, to mark those as unimportant commits.

    Still, I need to apply those cosmetic changes, or it would be much more difficult to me to reason about the important changes of the PR.

    Copy link
    Collaborator Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    And these cosmetic patches combined with the change fgetsx=>fgets have allowed me to see a transformation fgets=>getline too. I probably wouldn't have been able to see it without the cosmetic changes.

    Copy link
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Did you consider my coccinelle suggestion?

    Copy link
    Collaborator Author

    @alejandro-colomar alejandro-colomar Jul 22, 2024

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    I don't know how to use it. If you point me to some docs and/or show me a small shell example session showing how it's useful (the example will help more than the docs, TBH), I'll be happy to try it.

    Copy link
    Collaborator Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Hmmm. https://coccinelle.gitlabpages.inria.fr/website/sp.html. Sounds like it could be interesting.

    Copy link
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    That's why I mentioned it before ;)

    I think it's both a good fit for the work you're interested in and eases review of it.

    Copy link
    Collaborator Author

    @alejandro-colomar alejandro-colomar Jul 23, 2024

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    I'm trying to develop a coccinelle script that would do something similar to 941c951

    So far, I've written

    $ cat fgets_cast.sp 
    @@
    expression a, b, c;
    type t;
    
    @@
    
    - fgets(a, (t) (b), c)
    + fgets(a, b, c)
    
    @@
    expression a, b, c;
    type t;
    
    @@
    
    - fgets(a, (t) b, c)
    + fgets(a, b, c)
    
    @@
    expression a, b, c;
    type t;
    @@
    
    - fgetsx(a, (t) (b), c)
    + fgetsx(a, b, c)
    
    @@
    expression a, b, c;
    type t;
    @@
    
    - fgetsx(a, (t) b, c)
    + fgetsx(a, b, c)
    
    @@
    expression a, b, c, p;
    type t;
    @@
    
    - p->fgets(a, (t) (b), c)
    + p->fgets(a, b, c)
    
    @@
    expression a, b, c, p;
    type t;
    @@
    
    - p->fgets(a, (t) b, c)
    + p->fgets(a, b, c)

    and I'm running it as

    $ find lib* src/ -type f \
    | xargs spatch --sp-file ~/tmp/spatch/fgets_cast.sp --in-place;

    but it results in false positives, such as

    diff --git i/lib/shadow.c w/lib/shadow.c
    index 44436836..5759f259 100644
    --- i/lib/shadow.c
    +++ w/lib/shadow.c
    @@ -202,7 +202,7 @@ struct spwd *fgetspent (FILE * fp)
                    return (0);
            }
     
    -       if (fgets (buf, sizeof buf, fp) != NULL)
    +       if (fgets(buf, sizeof buf, fp) != NULL)
            {
                    stpsep(buf, "\n");
                    return my_sgetspent (buf);

    How is that matching (t), if there are no casts?

    lib/gshadow.c Show resolved Hide resolved
    @@ -81,9 +84,8 @@ void login_prompt (char *name, int namesize)
    */

    MEMZERO(buf);
    if (fgets (buf, sizeof buf, stdin) != buf) {
    if (fgets(buf, sizeof(buf), stdin) == NULL)
    Copy link
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    It would be helpful if formatting changes weren't mixed in.

    Copy link
    Collaborator Author

    @alejandro-colomar alejandro-colomar Jul 22, 2024

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    I try to keep those to a minimum: only whitespace and (sometimes) parentheses. And only on hunks where it (subjectively, admittedly) doesn't hurt too much readability (i.e., if I'm doing some huge transformations where I need your attention somewhere, I'll try to not do it there.

    I'll keep in mind your concern.

    /*
    * fgetsgent - convert next line in stream to (struct sgrp)
    *
    * fgetsgent() reads the next line from the provided stream and
    * converts it to a (struct sgrp). NULL is returned on EOF.
    */

    /*@observer@*//*@null@*/struct sgrp *fgetsgent (/*@null@*/FILE * fp)
    /*@observer@*//*@null@*/struct sgrp *
    fgetsgent(/*@null@*/FILE *fp)
    Copy link
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Is this null stuff really needed? Can't we use the attribute for it?

    Copy link
    Collaborator Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    I added some patches for reducing those comments some time ago, and replaced some of them by attributes and qualifiers

    I should have another look at those at some point, and send another round of patches.

    lib/fields.c Outdated
    @@ -66,7 +68,8 @@ int valid_field (const char *field, const char *illegal)
    * prompt the user with the name of the field being changed and the
    * current value.
    */
    void change_field (char *buf, size_t maxsize, const char *prompt)
    void
    Copy link
    Contributor

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Really, if you must do this, can't you just do a huge clang-format pass?

    Copy link
    Collaborator Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    Hmm, I'll have a look at using it. Thanks for the suggestion.

    @thesamesam
    Copy link
    Contributor

    I really feel this PR is still pretty noisy.

    @alejandro-colomar alejandro-colomar force-pushed the fgets branch 2 times, most recently from 0936efa to 5100579 Compare July 23, 2024 21:32
    Comment on lines -401 to +404
    bzero (cmd, sizeof (cmd));
    bzero(cmd, sizeof(cmd));
    Copy link
    Collaborator Author

    Choose a reason for hiding this comment

    The reason will be displayed to describe this comment to others. Learn more.

    @thesamesam

    If you apply the semantic patch accompanied with the corresponding commit message, and then git diff -w against the actual commit, you should be able to ignore these unrelated whitespace changes. I've written recommendations for how to better review each commit.

    I hope that helps reviewing, while at the same time allowing me to apply some house style while doing the changes.

    @alejandro-colomar alejandro-colomar force-pushed the fgets branch 4 times, most recently from b9658b2 to 1e3d7af Compare December 10, 2024 04:27
    }
    char *val;

    cp = strprefix(cp, ",") ?: cp;

    Check notice

    Code scanning / CodeQL

    For loop variable changed in body Note

    Loop counters should not be modified in the body of the
    loop
    .
    This skips an optional prefix.
    
    Signed-off-by: Alejandro Colomar <[email protected]>
    This is simpler to read, IMO.
    
    Signed-off-by: Alejandro Colomar <[email protected]>
    …onals
    
    While the return value is a pointer, it can be interpreted as a boolean
    value meaning "found".  In general, we use explicit comparisons of
    pointers to NULL, but in this specific case, let's use that
    interpretation, and make an exception, using an implicit conversion to
    boolean.
    
    For negative matches, use
    	if (!strchr(...))
    
    For positive matches, use
    	if (strchr(...))
    
    For positive matches, when a variable is also set, use
    	while (NULL != (p = strchr(...)))
    
    Signed-off-by: Alejandro Colomar <[email protected]>
    sizeof(foo)
    
    -  No spaces.
    	Not:  sizeof (foo)
    -  Parentheses.
    	Not:  sizeof foo
    -  No parentheses wrapping sizeof itself
    	Not:  (sizeof foo)
    
    This patch can be approximated with the following semantic patch:
    
    	$ cat ~/tmp/spatch/sizeof.sp
    	@@
    	identifier a, b;
    	@@
    
    	- sizeof a->b
    	+ sizeof(a->b)
    
    	@@
    	identifier a, b;
    	@@
    
    	- sizeof a.b
    	+ sizeof(a.b)
    
    	@@
    	identifier x;
    	@@
    
    	- sizeof x
    	+ sizeof(x)
    
    	@@
    	identifier x;
    	@@
    
    	- sizeof *x
    	+ sizeof(*x)
    
    	@@
    	identifier x;
    	@@
    
    	- (sizeof(x))
    	+ sizeof(x)
    
    	@@
    	identifier x;
    	@@
    
    	- (sizeof(*x))
    	+ sizeof(*x)
    
    Applied as
    
    	$ find contrib/ lib* src/ -type f \
    	| xargs spatch --sp-file ~/tmp/spatch/sizeof.sp --in-place;
    
    The differences between the actual patch and the approximation via the
    semantic patch from above are whitespace only.  When reviewing, it'll
    be useful to diff with '-w'.
    
    Link: <https://lkml.org/lkml/2012/7/11/103>
    Signed-off-by: Alejandro Colomar <[email protected]>
    This patch can be replicated with the following semantic patch:
    
    	$ cat fgets_cast.sp
    	@@
    	expression a, b, c;
    	@@
    
    	- fgets(a, (int) (b), c)
    	+ fgets(a, b, c)
    
    	@@
    	expression a, b, c;
    	@@
    
    	- fgets(a, (int) b, c)
    	+ fgets(a, b, c)
    
    	@@
    	expression a, b, c;
    	@@
    
    	- fgetsx(a, (int) (b), c)
    	+ fgetsx(a, b, c)
    
    	@@
    	expression a, b, c;
    	@@
    
    	- fgetsx(a, (int) b, c)
    	+ fgetsx(a, b, c)
    
    	@@
    	expression a, b, c, p;
    	@@
    
    	- p->fgets(a, (int) (b), c)
    	+ p->fgets(a, b, c)
    
    	@@
    	expression a, b, c, p;
    	@@
    
    	- p->fgets(a, (int) b, c)
    	+ p->fgets(a, b, c)
    
    which is applied as:
    
    	$ find lib* src/ -type f \
    	| xargs spatch --sp-file ~/tmp/spatch/fgets_cast.sp --in-place;
    
    Signed-off-by: Alejandro Colomar <[email protected]>
    fgets(3) returns either NULL or the input pointer.  Checking for NULL is
    more explicit, and simpler.
    
    <stddef.h> is the header that provides NULL; add it where appropriate.
    
    The meat of this patch can be approximated with the following semantic
    patch:
    
    	$ cat ~/tmp/spatch/fgets_null.sp
    	@@
    	expression a, b, c;
    	@@
    
    	- fgets(a, b, c) == a
    	+ fgets(a, b, c) != NULL
    
    	@@
    	expression a, b, c;
    	@@
    
    	- fgetsx(a, b, c) == a
    	+ fgetsx(a, b, c) != NULL
    
    	@@
    	expression a, b, c, p;
    	@@
    
    	- p->fgets(a, b, c) == a
    	+ p->fgets(a, b, c) != NULL
    
    	@@
    	expression a, b, c;
    	@@
    
    	- fgets(a, b, c) != a
    	+ fgets(a, b, c) == NULL
    
    	@@
    	expression a, b, c;
    	@@
    
    	- fgetsx(a, b, c) != a
    	+ fgetsx(a, b, c) == NULL
    
    	@@
    	expression a, b, c, p;
    	@@
    
    	- p->fgets(a, b, c) != a
    	+ p->fgets(a, b, c) == NUL
    
    Applied as
    
    	$ find contrib/ lib* src/ -type f \
    	| xargs spatch --sp-file ~/tmp/spatch/fgets_null.sp --in-place;
    
    The differences between the actual patch and the approximation via the
    semantic patch from above are includes, whitespace, braces, and a case
    where there was an implicit pointer-to-bool comparison which I made
    explicit.  When reviewing, it'll be useful to use git-diff(1) with '-w'
    and '--color-words=.'.
    
    Signed-off-by: Alejandro Colomar <[email protected]>
    It seems they never worked correctly.  Let's keep it simple and remove
    support for escaped newlines.
    
    Closes: <shadow-maint#1055>
    Reported-by: Chris Hofstaedtler <[email protected]>
    Signed-off-by: Alejandro Colomar <[email protected]>
    Reported-by: Chris Hofstaedtler <[email protected]>
    Signed-off-by: Alejandro Colomar <[email protected]>
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    None yet
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    fputsx is not round-trip safe with backslash-ending usernames
    4 participants