Skip to content

Conversation

@alejandro-colomar
Copy link
Collaborator

@alejandro-colomar alejandro-colomar commented Oct 12, 2025


Revisions:

v1b
  • Rebase
$ git rd 
1:  fdd0ccd6 ! 1:  a66931f3 lib/, src/: Use strspn(3) instead of its pattern
    @@ src/grpck.c
      
      #ifdef SHADOWGRP
      #include "sgroupio.h"
    -@@ src/grpck.c: static void check_grp_file (bool *errors, bool *changed)
    +@@ src/grpck.c: static void check_grp_file (bool *errors, bool *changed, struct option_flags *fl
                /*
                 * Skip all NIS entries.
                 */
    @@ src/pwck.c
      #ifdef WITH_TCB
      #include "tcbfuncs.h"
      #endif                            /* WITH_TCB */
    -@@ src/pwck.c: static void check_pw_file (bool *errors, bool *changed)
    +@@ src/pwck.c: static void check_pw_file (bool *errors, bool *changed, struct option_flags *fla
                 * If this is a NIS line, skip it. You can't "know" what NIS
                 * is going to do without directly asking NIS ...
                 */
2:  5ac4f04b = 2:  0b0e6b2f lib/, src/: Use strcspn(3) instead of its pattern
v2
  • Replace more cases.
$ git range-diff shadow/master gh/strspn strspn 
1:  a66931f3 ! 1:  21f5239f lib/, src/: Use strspn(3) instead of its pattern
    @@ lib/commonio.c: static void add_one_entry (struct commonio_db *db,
      }
      
      
    +@@ lib/commonio.c: commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
    +           (NULL != ptr)
    + #if KEEP_NIS_AT_END
    +        && ((NULL == ptr->line)
    +-           || (('+' != ptr->line[0])
    +-               && ('-' != ptr->line[0])))
    ++           || !strspn(ptr->line, "+-"))
    + #endif
    +        ;
    +        ptr = ptr->next) {
    +
    + ## lib/getrange.c ##
    +@@
    + 
    + #include <ctype.h>
    + #include <stdlib.h>
    ++#include <string.h>
    + 
    + #include "atoi/a2i/a2u.h"
    + #include "defines.h"
    +@@ lib/getrange.c: getrange(const char *range,
    +   *has_min = false;
    +   *has_max = false;
    + 
    +-  if ('-' == range[0]) {
    ++  if (strspn(range, "-")) {
    +           end = range + 1;
    +           goto parse_max;
    +   }
    +
    + ## lib/hushed.c ##
    +@@ lib/hushed.c: bool hushed (const char *username)
    +    * file exists in the user's home directory.
    +    */
    + 
    +-  if (hushfile[0] != '/') {
    ++  if (!strspn(hushfile, "/")) {
    +           SNPRINTF(buf, "%s/%s", pw->pw_dir, hushfile);
    +           return (access (buf, F_OK) == 0);
    +   }
    +
    + ## lib/prefix_flag.c ##
    +@@
    + 
    + #include <paths.h>
    + #include <stdio.h>
    ++#include <string.h>
    + 
    + #include <assert.h>
    + 
    +@@ lib/prefix_flag.c: extern const char* process_prefix_flag (const char* short_opt, int argc, char **
    +                   return ""; /* if prefix is "/" then we ignore the flag option */
    +           /* should we prevent symbolic link from being used as a prefix? */
    + 
    +-          if ( prefix[0] != '/') {
    ++          if (!strspn(prefix, "/")) {
    +                   fprintf (log_get_logfd(),
    +                            _("%s: prefix must be an absolute path\n"),
    +                            log_get_progname());
    +
    + ## lib/root_flag.c ##
    +@@
    + #ident "$Id$"
    + 
    + #include <stdio.h>
    ++#include <string.h>
    + 
    + #include "defines.h"
    + /*@-exitarg@*/
    +@@ lib/root_flag.c: static void change_root (const char* newroot)
    +           exit (EXIT_FAILURE);
    +   }
    + 
    +-  if ('/' != newroot[0]) {
    ++  if (!strspn(newroot, "/")) {
    +           fprintf (log_get_logfd(),
    +                    _("%s: invalid chroot path '%s', only absolute paths are supported.\n"),
    +                    log_get_progname(), newroot);
    +
    + ## lib/sub.c ##
    +@@
    + 
    + #include "config.h"
    + 
    +-#ident "$Id$"
    +-
    + #include <pwd.h>
    + #include <stdio.h>
    ++#include <string.h>
    + #include <sys/types.h>
    ++
    + #include "prototypes.h"
    + #include "defines.h"
    ++
    + #define   MAX_SUBROOT2    "maximum subsystem depth reached\n"
    + #define   BAD_SUBROOT2    "invalid root `%s' for user `%s'\n"
    + #define   NO_SUBROOT2     "no subsystem root `%s' for user `%s'\n"
    +@@ lib/sub.c: void subsystem (const struct passwd *pw)
    +    * The new root directory must begin with a "/" character.
    +    */
    + 
    +-  if (pw->pw_dir[0] != '/') {
    ++  if (!strspn(pw->pw_dir, "/")) {
    +           printf (_("Invalid root directory '%s'\n"), pw->pw_dir);
    +           SYSLOG ((LOG_WARN, BAD_SUBROOT2, pw->pw_dir, pw->pw_name));
    +           closelog ();
    +
    + ## src/chsh.c ##
    +@@
    + #include <getopt.h>
    + #include <pwd.h>
    + #include <stdio.h>
    ++#include <string.h>
    + #include <sys/types.h>
    + 
    + #include "chkname.h"
    +@@ src/chsh.c: int main (int argc, char **argv)
    +           fail_exit (1, process_selinux);
    +   }
    +   if (!streq(loginsh, "")
    +-      && (loginsh[0] != '/'
    ++      && (!strspn(loginsh, "/")
    +           || is_restricted_shell (loginsh)
    +           || (access (loginsh, X_OK) != 0)))
    +   {
     
      ## src/grpck.c ##
     @@
    @@ src/login.c: int main (int argc, char **argv)
                        if (streq(user_passwd, "")) {
                                const char *prevent_no_auth = getdef_str("PREVENT_NO_AUTH");
     
    + ## src/login_nopam.c ##
    +@@ src/login_nopam.c: login_access(const char *user, const char *from)
    +                                    TABLE, lineno));
    +                           continue;
    +                   }
    +-                  if (perm[0] != '+' && perm[0] != '-') {
    ++                  if (!strspn(perm, "+-")) {
    +                           SYSLOG ((LOG_ERR,
    +                                    "%s: line %jd: bad first field",
    +                                    TABLE, lineno));
    +
    + ## src/newgrp.c ##
    +@@ src/newgrp.c: int main (int argc, char **argv)
    +            * Do the command line for everything that is
    +            * not "newgrp".
    +            */
    +-          if ((argc > 0) && (argv[0][0] != '-')) {
    ++          if ((argc > 0) && !strspn(argv[0], "-")) {
    +                   if (!is_valid_group_name (argv[0])) {
    +                           fprintf (
    +                                   stderr, _("%s: provided group is not a valid group name\n"),
    +@@ src/newgrp.c: int main (int argc, char **argv)
    +            * Do the command line for "newgrp". It's just making sure
    +            * there aren't any flags and getting the new group name.
    +            */
    +-          if ((argc > 0) && strprefix(argv[0], "-")) {
    ++          if ((argc > 0) && strspn(argv[0], "-")) {
    +                   usage ();
    +                   goto failure;
    +           } else if (argv[0] != NULL) {
    +
    + ## src/newusers.c ##
    +@@ src/newusers.c: int main (int argc, char **argv)
    + /* FIXME: should check for directory */
    +                   mode_t mode = getdef_num ("HOME_MODE",
    +                                             0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK));
    +-                  if (newpw.pw_dir[0] != '/') {
    ++                  if (!strspn(newpw.pw_dir, "/")) {
    +                           fprintf(stderr,
    +                                   _("%s: line %jd: homedir must be an absolute path\n"),
    +                                   Prog, line);
    +
      ## src/passwd.c ##
     @@
      #include <pwd.h>
    @@ src/pwck.c: static void check_spw_file (bool *errors, bool *changed)
      
                /*
                 * Start with the entries that are completely corrupt. They
    +
    + ## src/useradd.c ##
    +@@ src/useradd.c: static void process_flags (int argc, char **argv, struct option_flags *flags)
    +                   switch (c) {
    +                   case 'b':
    +                           if (   ( !VALID (optarg) )
    +-                              || ( optarg[0] != '/' )) {
    ++                              || !strspn(optarg, "/")) {
    +                                   fprintf (stderr,
    +                                            _("%s: invalid base directory '%s'\n"),
    +                                            Prog, optarg);
    +@@ src/useradd.c: static void process_flags (int argc, char **argv, struct option_flags *flags)
    +                           break;
    +                   case 'd':
    +                           if (   ( !VALID (optarg) )
    +-                              || ( optarg[0] != '/' )) {
    ++                              || !strspn(optarg, "/")) {
    +                                   fprintf (stderr,
    +                                            _("%s: invalid home directory '%s'\n"),
    +                                            Prog, optarg);
    +
    + ## src/usermod.c ##
    +@@
    + #endif                            /* ACCT_TOOLS_SETUID */
    + #include <paths.h>
    + #include <stdio.h>
    ++#include <string.h>
    + #include <strings.h>
    + #include <sys/stat.h>
    + #include <sys/types.h>
    +@@ src/usermod.c: usage (int status)
    +  */
    + static char *new_pw_passwd (char *pw_pass)
    + {
    +-  if (Lflg && ('!' != pw_pass[0])) {
    ++  if (Lflg && !strspn(pw_pass, "!")) {
    + #ifdef WITH_AUDIT
    +           audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
    +                         "updating-passwd", user_newname, user_newid, 1);
2:  0b0e6b2f ! 2:  86c7c445 lib/, src/: Use strcspn(3) instead of its pattern
    @@ src/suauth.c: check_su_auth(const char *actual_id, const char *wanted_id, bool s
                        continue;
      
                to_users = strsep(&p, ":");
    +
    + ## src/useradd.c ##
    +@@ src/useradd.c: static void process_flags (int argc, char **argv, struct option_flags *flags)
    +                           break;
    +                   case 's':
    +                           if (   ( !VALID (optarg) )
    +-                              || (   !streq(optarg, "")
    +-                                  && ('/'  != optarg[0])
    +-                                  && ('*'  != optarg[0]) )) {
    ++                              || strcspn(optarg, "/*")) {
    +                                   fprintf (stderr,
    +                                            _("%s: invalid shell '%s'\n"),
    +                                            Prog, optarg);
    +                                   exit (E_BAD_ARG);
    +                           }
    +-                          if (!streq(optarg, "")
    +-                               && '*'  != optarg[0]
    ++                          if (strcspn(optarg, "*")
    +                                && !streq(optarg, "/sbin/nologin")
    +                                && !streq(optarg, "/usr/sbin/nologin")
    +                                && (   stat(optarg, &st) != 0
    +
    + ## src/usermod.c ##
    +@@ src/usermod.c: process_flags(int argc, char **argv, struct option_flags *flags)
    +                           }
    +                           dflg = true;
    +                           user_newhome = optarg;
    +-                          if ((user_newhome[0] != '/') && !streq(user_newhome, "")) {
    ++                          if (strcspn(user_newhome, "/")) {
    +                                   fprintf (stderr,
    +                                            _("%s: homedir must be an absolute path\n"),
    +                                            Prog);
    +@@ src/usermod.c: process_flags(int argc, char **argv, struct option_flags *flags)
    +                           break;
    +                   case 's':
    +                           if (   ( !VALID (optarg) )
    +-                              || (   !streq(optarg, "")
    +-                                  && ('/'  != optarg[0])
    +-                                  && ('*'  != optarg[0]) )) {
    ++                              || strcspn(optarg, "/*")) {
    +                                   fprintf (stderr,
    +                                            _("%s: invalid shell '%s'\n"),
    +                                            Prog, optarg);
    +                                   exit (E_BAD_ARG);
    +                           }
    +-                          if (!streq(optarg, "")
    +-                               && '*'  != optarg[0]
    ++                          if (strcspn(optarg, "*")
    +                                && !streq(optarg, "/sbin/nologin")
    +                                && !streq(optarg, "/usr/sbin/nologin")
    +                                && (   stat(optarg, &st) != 0
v3
  • Replace more cases.
$ git range-diff shadow/master gh/strspn strspn 
1:  21f5239f ! 1:  794f7f4d lib/, src/: Use strspn(3) instead of its pattern
    @@ lib/commonio.c: commonio_sort (struct commonio_db *db, int (*cmp) (const void *,
             ;
             ptr = ptr->next) {
     
    + ## lib/encrypt.c ##
    +@@
    + 
    + #include <unistd.h>
    + #include <stdio.h>
    ++#include <string.h>
    + 
    + #include "prototypes.h"
    + #include "defines.h"
    + #include "shadowlog_internal.h"
    +-#include "string/strcmp/strprefix.h"
    + 
    + 
    + /*@exposed@*//*@null@*/char *pw_encrypt (const char *clear, const char *salt)
    +@@
    + 
    +   /* Some crypt() do not return NULL if the algorithm is not
    +    * supported, and return a DES encrypted password. */
    +-  if ((NULL != salt) && strprefix(salt, "$") && (strlen (cp) <= 13))
    ++  if ((NULL != salt) && strspn(salt, "$") && (strlen (cp) <= 13))
    +   {
    +           /*@observer@*/const char *method;
    +           switch (salt[1])
    +
      ## lib/getrange.c ##
     @@
      
    @@ lib/hushed.c: bool hushed (const char *username)
                return (access (buf, F_OK) == 0);
        }
     
    + ## lib/limits.c ##
    +@@ lib/limits.c: static int setrlimit_value (unsigned int resource,
    +   /* The "-" is special, not belonging to a strange negative limit.
    +    * It is infinity, in a controlled way.
    +    */
    +-  if (strprefix(value, "-")) {
    ++  if (strspn(value, "-")) {
    +           limit = RLIM_INFINITY;
    + 
    +   } else {
    +@@ lib/limits.c: static int setup_user_limits (const char *uname)
    +                           break;
    +                   } else if (streq(name, "*")) {
    +                           strcpy (deflimits, tempbuf);
    +-                  } else if (strprefix(name, "@")) {
    ++                  } else if (strspn(name, "@")) {
    +                           /* If the user is in the group, the group
    +                            * limits apply unless later a line for
    +                            * the specific user is found.
    +
    + ## lib/port.c ##
    +@@
    + #include "port.h"
    + #include "prototypes.h"
    + #include "string/strcmp/streq.h"
    +-#include "string/strcmp/strprefix.h"
    + #include "string/strtok/stpsep.h"
    + #include "string/strtok/strsep2ls.h"
    + 
    +@@ lib/port.c: static int portcmp (const char *pattern, const char *port)
    +   if (streq(orig, "SU"))
    +           return 1;
    + 
    +-  return !strprefix(pattern, "*");
    ++  return !strspn(pattern, "*");
    + }
    + 
    + /*
    +@@ lib/port.c: next:
    +           errno = saveerr;
    +           return NULL;
    +   }
    +-  if (strprefix(buf, "#"))
    ++  if (strspn(buf, "#"))
    +           goto next;
    + 
    +   stpsep(buf, "\n");
    +
      ## lib/prefix_flag.c ##
     @@
      
    @@ lib/sub.c: void subsystem (const struct passwd *pw)
                SYSLOG ((LOG_WARN, BAD_SUBROOT2, pw->pw_dir, pw->pw_name));
                closelog ();
     
    + ## lib/ttytype.c ##
    +@@ lib/ttytype.c: void ttytype (const char *line)
    +           return;
    +   }
    +   while (fgets (buf, sizeof buf, fp) == buf) {
    +-          if (strprefix(buf, "#")) {
    ++          if (strspn(buf, "#"))
    +                   continue;
    +-          }
    + 
    +           stpsep(buf, "\n");
    + 
    +
    + ## lib/yesno.c ##
    +@@
    + #include <stdlib.h>
    + 
    + #include "prototypes.h"
    +-#include "string/strcmp/strcaseprefix.h"
    + 
    + 
    + /*
    +@@ lib/yesno.c: yes_or_no(bool read_only)
    + static int
    + rpmatch(const char *response)
    + {
    +-  if (strcaseprefix(response, "y"))
    ++  if (strspn(response, "yY"))
    +           return 1;
    +-  if (strcaseprefix(response, "n"))
    ++  if (strspn(response, "nN"))
    +           return 0;
    + 
    +   return -1;
    +
    + ## src/check_subid_range.c ##
    +@@
    + #include <string.h>
    + #include <stdbool.h>
    + #include <stdlib.h>
    ++#include <string.h>
    + #include <sys/types.h>
    + #include <sys/stat.h>
    + #include <fcntl.h>
    +@@
    + #include "idmapping.h"
    + #include "prototypes.h"
    + #include "shadowlog.h"
    +-#include "string/strcmp/strprefix.h"
    + #include "subordinateio.h"
    + 
    + 
    +@@ src/check_subid_range.c: main(int argc, char **argv)
    +           exit(1);
    + 
    +   owner = argv[1];
    +-  check_uids = strprefix(argv[2], "u");
    ++  check_uids = strspn(argv[2], "u");
    +   if (get_uid(argv[3], &start) == -1)
    +           exit(1);
    +   if (str2ul(&count, argv[4]) == -1)
    +
      ## src/chsh.c ##
     @@
      #include <getopt.h>
    @@ src/login.c
      #include <sys/stat.h>
      #include <sys/ioctl.h>
      #include <assert.h>
    +@@
    + #include "string/sprintf/snprintf.h"
    + #include "string/strcmp/streq.h"
    + #include "string/strcmp/strneq.h"
    +-#include "string/strcmp/strprefix.h"
    + #include "string/strcpy/strtcpy.h"
    + #include "string/strdup/xstrdup.h"
    + #include "string/strftime.h"
    +@@ src/login.c: static void process_flags (int argc, char *const *argv)
    +    * clever telnet, and getty holes.
    +    */
    +   for (arg = 1; arg < argc; arg++) {
    +-          if (strprefix(argv[arg], "-") && strlen(argv[arg]) > 2) {
    ++          if (strspn(argv[arg], "-") && strlen(argv[arg]) > 2) {
    +                   usage ();
    +           }
    +           if (streq(argv[arg], "--")) {
    +@@ src/login.c: static void init_env (void)
    +   else {
    +           cp = getdef_str ("ENV_TZ");
    +           if (NULL != cp) {
    +-                  addenv(strprefix(cp, "/") ? tz(cp) : cp, NULL);
    ++                  addenv(strspn(cp, "/") ? tz(cp) : cp, NULL);
    +           }
    +   }
    + #endif                            /* !USE_PAM */
     @@ src/login.c: int main (int argc, char **argv)
                         * login, even if they have been
                         * "pre-authenticated."
    @@ src/login.c: int main (int argc, char **argv)
      
                        if (streq(user_passwd, "")) {
                                const char *prevent_no_auth = getdef_str("PREVENT_NO_AUTH");
    +@@ src/login.c: int main (int argc, char **argv)
    +           addenv ("IFS= \t\n", NULL);     /* ... instead, set a safe IFS */
    +   }
    + 
    +-  if (strprefix(pwd->pw_shell, "*")) {  /* subsystem root */
    ++  if (strspn(pwd->pw_shell, "*")) {  /* subsystem root */
    +           pwd->pw_shell++;        /* skip the '*' */
    +           subsystem (pwd);        /* figure out what to execute */
    +           subroot = true; /* say I was here again */
     
      ## src/login_nopam.c ##
     @@ src/login_nopam.c: login_access(const char *user, const char *from)
    @@ src/login_nopam.c: login_access(const char *user, const char *from)
                                SYSLOG ((LOG_ERR,
                                         "%s: line %jd: bad first field",
                                         TABLE, lineno));
    +@@ src/login_nopam.c: login_access(const char *user, const char *from)
    +           int err = errno;
    +           SYSLOG ((LOG_ERR, "cannot open %s: %s", TABLE, strerror (err)));
    +   }
    +-  return (!match || strprefix(line, "+"))?1:0;
    ++  return (!match || strspn(line, "+"))?1:0;
    + }
    + 
    + /* list_match - match an item against a list of tokens with exceptions */
    +@@ src/login_nopam.c: static bool user_match (char *tok, const char *string)
    +   if (host != NULL) {
    +           return user_match(tok, string) && from_match(host, myhostname());
    + #if HAVE_INNETGR
    +-  } else if (strprefix(tok, "@")) {       /* netgroup */
    ++  } else if (strspn(tok, "@")) {  /* netgroup */
    +           return (netgroup_match (tok + 1, NULL, string));
    + #endif
    +   } else if (string_match (tok, string)) {        /* ALL or exact match */
    +@@ src/login_nopam.c: static bool from_match (char *tok, const char *string)
    +    * if it matches the head of the string.
    +    */
    + #if HAVE_INNETGR
    +-  if (strprefix(tok, "@")) {  /* netgroup */
    ++  if (strspn(tok, "@")) {  /* netgroup */
    +           return (netgroup_match (tok + 1, string, NULL));
    +   } else
    + #endif
    +   if (string_match (tok, string)) {       /* ALL or exact match */
    +           return true;
    +-  } else if (strprefix(tok, ".")) {  /* domain: match last fields */
    ++  } else if (strspn(tok, ".")) {  /* domain: match last fields */
    +           size_t  str_len, tok_len;
    + 
    +           str_len = strlen (string);
     
      ## src/newgrp.c ##
     @@ src/newgrp.c: int main (int argc, char **argv)
    @@ src/passwd.c
      #include <sys/types.h>
      #include <time.h>
      
    +@@
    + #include "string/memset/memzero.h"
    + #include "string/sprintf/xaprintf.h"
    + #include "string/strcmp/streq.h"
    +-#include "string/strcmp/strprefix.h"
    + #include "string/strcpy/strtcpy.h"
    + #include "string/strdup/xstrdup.h"
    + #include "time/day_to_str.h"
    +@@ src/passwd.c: static void check_password (const struct passwd *pw, const struct spwd *sp)
    +    * changed. Passwords which have been inactive too long cannot be
    +    * changed.
    +    */
    +-  if (   strprefix(sp->sp_pwdp, "!")
    ++  if (   strspn(sp->sp_pwdp, "!")
    +       || (exp_status > 1)
    +       || (   (sp->sp_max >= 0)
    +           && (sp->sp_min > sp->sp_max))) {
     @@ src/passwd.c: static void check_password (const struct passwd *pw, const struct spwd *sp)
      
      static /*@observer@*/const char *pw_status (const char *pass)
    @@ src/passwd.c: static void check_password (const struct passwd *pw, const struct
        if (streq(pass, "")) {
                return "NP";
        }
    +@@ src/passwd.c: static char *update_crypt_pw (char *cp, bool process_selinux)
    +   if (dflg)
    +           strcpy(cp, "");
    + 
    +-  if (uflg && strprefix(cp, "!")) {
    ++  if (uflg && strspn(cp, "!")) {
    +           if (cp[1] == '\0') {
    +                   (void) fprintf (stderr,
    +                                   _("%s: unlocking the password would result in a passwordless account.\n"
    +@@ src/passwd.c: static char *update_crypt_pw (char *cp, bool process_selinux)
    +           }
    +   }
    + 
    +-  if (lflg && *cp != '!') {
    ++  if (lflg && !strspn(cp, "!")) {
    +           char  *newpw;
    + 
    +           newpw = xaprintf("!%s", cp);
     
      ## src/pwck.c ##
     @@
    @@ src/pwck.c: static void check_spw_file (bool *errors, bool *changed)
                /*
                 * Start with the entries that are completely corrupt. They
     
    + ## src/su.c ##
    +@@
    + #include <pwd.h>
    + #include <signal.h>
    + #include <stdio.h>
    ++#include <string.h>
    + #include <sys/types.h>
    + #include <unistd.h>
    + #ifndef USE_PAM
    +@@
    + #include "string/sprintf/snprintf.h"
    + #include "string/sprintf/xaprintf.h"
    + #include "string/strcmp/streq.h"
    +-#include "string/strcmp/strprefix.h"
    + #include "string/strcpy/strtcpy.h"
    + #include "string/strdup/xstrdup.h"
    + 
    +@@ src/su.c: static bool restricted_shell (const char *shellname)
    + 
    +   setusershell ();
    +   while (NULL != (line = getusershell())) {
    +-          if (('#' != *line) && streq(line, shellname)) {
    ++          if (!strspn(line, "#") && streq(line, shellname)) {
    +                   endusershell ();
    +                   return false;
    +           }
    +@@ src/su.c: static /*@only@*/struct passwd * do_check_perms (void)
    +    * the shell specified in /etc/passwd (not the one specified with
    +    * --shell, which will be the one executed in the chroot later).
    +    */
    +-  if (strprefix(pw->pw_shell, "*")) {  /* subsystem root required */
    ++  if (strspn(pw->pw_shell, "*")) {  /* subsystem root required */
    +           subsystem (pw); /* change to the subsystem root */
    +           endpwent ();            /* close the old password databases */
    +           endspent ();
    +@@ src/su.c: static void set_environment (struct passwd *pw)
    + #ifndef USE_PAM
    +           cp = getdef_str ("ENV_TZ");
    +           if (NULL != cp) {
    +-                  addenv(strprefix(cp, "/") ? tz(cp) : cp, NULL);
    ++                  addenv(strspn(cp, "/") ? tz(cp) : cp, NULL);
    +           }
    + 
    +           /*
    +
    + ## src/sulogin.c ##
    +@@
    + #include <pwd.h>
    + #include <signal.h>
    + #include <stdio.h>
    ++#include <string.h>
    + #include <sys/ioctl.h>
    + #include <sys/types.h>
    + 
    +@@
    + #include "exitcodes.h"
    + #include "shadowlog.h"
    + #include "string/strcmp/streq.h"
    +-#include "string/strcmp/strprefix.h"
    + #include "string/strdup/xstrdup.h"
    + 
    + 
    +@@ src/sulogin.c: main(int argc, char *argv[])
    + #ifndef USE_PAM
    +   env = getdef_str ("ENV_TZ");
    +   if (NULL != env) {
    +-          addenv(strprefix(env, "/") ? tz(env) : env, NULL);
    ++          addenv(strspn(env, "/") ? tz(env) : env, NULL);
    +   }
    +   env = getdef_str ("ENV_HZ");
    +   if (NULL != env) {
    +
      ## src/useradd.c ##
    +@@
    + #include "string/sprintf/xaprintf.h"
    + #include "string/strcmp/strcaseeq.h"
    + #include "string/strcmp/streq.h"
    +-#include "string/strcmp/strprefix.h"
    + #include "string/strdup/xstrdup.h"
    + #include "string/strtok/stpsep.h"
    + 
     @@ src/useradd.c: static void process_flags (int argc, char **argv, struct option_flags *flags)
                        switch (c) {
                        case 'b':
    @@ src/useradd.c: static void process_flags (int argc, char **argv, struct option_f
                                        fprintf (stderr,
                                                 _("%s: invalid home directory '%s'\n"),
                                                 Prog, optarg);
    +@@ src/useradd.c: static void create_home (struct option_flags *flags)
    +    */
    +   for (cp = strtok(bhome, "/"); cp != NULL; cp = strtok(NULL, "/")) {
    +           /* Avoid turning a relative path into an absolute path. */
    +-          if (strprefix(bhome, "/") || !streq(path, ""))
    ++          if (strspn(bhome, "/") || !streq(path, ""))
    +                   strcat(path, "/");
    + 
    +           strcat(path, cp);
     
      ## src/usermod.c ##
     @@
    @@ src/usermod.c
      #include <strings.h>
      #include <sys/stat.h>
      #include <sys/types.h>
    +@@
    + #include "string/memset/memzero.h"
    + #include "string/sprintf/xaprintf.h"
    + #include "string/strcmp/streq.h"
    +-#include "string/strcmp/strprefix.h"
    + #include "string/strdup/xstrdup.h"
    + #include "time/day_to_str.h"
    + #include "typetraits.h"
    +@@ src/usermod.c: getid_range(const char *str)
    +           return result;
    +   }
    + 
    +-  if ('-' != *pos++)
    ++  if (!strspn(pos++, "-"))
    +           return result;
    + 
    +   if (a2i(id_t, &last, pos, NULL, 10, first, last) == -1)
     @@ src/usermod.c: usage (int status)
       */
      static char *new_pw_passwd (char *pw_pass)
    @@ src/usermod.c: usage (int status)
      #ifdef WITH_AUDIT
                audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
                              "updating-passwd", user_newname, user_newid, 1);
    + #endif
    +           SYSLOG ((LOG_INFO, "lock user '%s' password", user_newname));
    +           pw_pass = xaprintf("!%s", pw_pass);
    +-  } else if (Uflg && strprefix(pw_pass, "!")) {
    ++  } else if (Uflg && strspn(pw_pass, "!")) {
    +           if (pw_pass[1] == '\0') {
    +                   fprintf (stderr,
    +                            _("%s: unlocking the user's password would result in a passwordless account.\n"
2:  86c7c445 = 2:  173b93f8 lib/, src/: Use strcspn(3) instead of its pattern
v3b
  • Rebase
$ git range-diff shadow/master gh/strspn strspn 
1:  794f7f4d ! 1:  ededb876 lib/, src/: Use strspn(3) instead of its pattern
    @@ src/login.c
      #include "string/strcmp/strneq.h"
     -#include "string/strcmp/strprefix.h"
      #include "string/strcpy/strtcpy.h"
    - #include "string/strdup/xstrdup.h"
    + #include "string/strdup/strdup.h"
      #include "string/strftime.h"
     @@ src/login.c: static void process_flags (int argc, char *const *argv)
         * clever telnet, and getty holes.
    @@ src/passwd.c
      
     @@
      #include "string/memset/memzero.h"
    - #include "string/sprintf/xaprintf.h"
    + #include "string/sprintf/aprintf.h"
      #include "string/strcmp/streq.h"
     -#include "string/strcmp/strprefix.h"
      #include "string/strcpy/strtcpy.h"
    - #include "string/strdup/xstrdup.h"
    + #include "string/strdup/strdup.h"
      #include "time/day_to_str.h"
     @@ src/passwd.c: static void check_password (const struct passwd *pw, const struct spwd *sp)
         * changed. Passwords which have been inactive too long cannot be
    @@ src/su.c
      #include <unistd.h>
      #ifndef USE_PAM
     @@
    + #include "string/sprintf/aprintf.h"
      #include "string/sprintf/snprintf.h"
    - #include "string/sprintf/xaprintf.h"
      #include "string/strcmp/streq.h"
     -#include "string/strcmp/strprefix.h"
      #include "string/strcpy/strtcpy.h"
    - #include "string/strdup/xstrdup.h"
    + #include "string/strdup/strdup.h"
      
     @@ src/su.c: static bool restricted_shell (const char *shellname)
      
    @@ src/sulogin.c
      #include "shadowlog.h"
      #include "string/strcmp/streq.h"
     -#include "string/strcmp/strprefix.h"
    - #include "string/strdup/xstrdup.h"
    + #include "string/strdup/strdup.h"
      
      
     @@ src/sulogin.c: main(int argc, char *argv[])
    @@ src/sulogin.c: main(int argc, char *argv[])
     
      ## src/useradd.c ##
     @@
    - #include "string/sprintf/xaprintf.h"
    + #include "string/sprintf/snprintf.h"
      #include "string/strcmp/strcaseeq.h"
      #include "string/strcmp/streq.h"
     -#include "string/strcmp/strprefix.h"
    - #include "string/strdup/xstrdup.h"
    + #include "string/strdup/strdup.h"
      #include "string/strtok/stpsep.h"
      
     @@ src/useradd.c: static void process_flags (int argc, char **argv, struct option_flags *flags)
    @@ src/usermod.c
      #include <sys/types.h>
     @@
      #include "string/memset/memzero.h"
    - #include "string/sprintf/xaprintf.h"
    + #include "string/sprintf/aprintf.h"
      #include "string/strcmp/streq.h"
     -#include "string/strcmp/strprefix.h"
    - #include "string/strdup/xstrdup.h"
    + #include "string/strdup/strdup.h"
      #include "time/day_to_str.h"
      #include "typetraits.h"
     @@ src/usermod.c: getid_range(const char *str)
2:  173b93f8 ! 2:  0eefff6e lib/, src/: Use strcspn(3) instead of its pattern
    @@ Commit message
     
      ## lib/getdef.c ##
     @@
    - #include "string/sprintf/xaprintf.h"
    + #include "string/sprintf/aprintf.h"
      #include "string/strcmp/strcaseeq.h"
      #include "string/strcmp/streq.h"
     -#include "string/strcmp/strprefix.h"
    @@ lib/setupenv.c
      #include "defines.h"
     @@
      #include "shadowlog.h"
    - #include "string/sprintf/xaprintf.h"
    + #include "string/sprintf/aprintf.h"
      #include "string/strcmp/streq.h"
     -#include "string/strcmp/strprefix.h"
    - #include "string/strdup/xstrdup.h"
    + #include "string/strdup/strdup.h"
      #include "string/strspn/stpspn.h"
      #include "string/strtok/stpsep.h"
      

@alejandro-colomar alejandro-colomar changed the title lib/, src/: Use strspn(3) instead of its pattern lib/, src/: Use strspn(3) and strcspn(3) instead of their patterns Oct 12, 2025
@alejandro-colomar alejandro-colomar changed the title lib/, src/: Use strspn(3) and strcspn(3) instead of their patterns lib/, src/: Use strspn(3), strcspn(3), and stprspn() instead of their patterns Oct 13, 2025
@alejandro-colomar alejandro-colomar changed the title lib/, src/: Use strspn(3), strcspn(3), and stprspn() instead of their patterns lib/, src/: Use strspn(3) and strcspn(3) instead of their patterns Oct 13, 2025
Comment on lines 371 to 373
while (fgets (buf, 1024, fil) != NULL) {
if (strprefix(buf, "#") || strprefix(buf, "\n")) {
if (!strcspn(buf, "#\n"))
continue;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This reminds me of a future patch set which will check after every call to fgets(3) that there exists a \n character, and removes it. This code is bad, in the sense that it doesn't detect files with too long lines.

@alejandro-colomar alejandro-colomar force-pushed the strspn branch 6 times, most recently from 5ac4f04 to 0b0e6b2 Compare October 19, 2025 09:07
@alejandro-colomar alejandro-colomar force-pushed the strspn branch 2 times, most recently from 86c7c44 to 173b93f Compare October 24, 2025 11:59
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.

1 participant