lib/, src/: Use strsep(3) instead of strtok(3)

strsep(3) is stateless, and so is easier to reason about.

It also has a slight difference: strtok(3) jumps over empty fields,
while strsep(3) respects them as empty fields.  In most of the cases
where we were using strtok(3), it makes more sense to respect empty
fields, and this commit probably silently fixes a few bugs.

In other cases (most notably filesystem paths), contiguous delimiters
("//") should be collapsed, so strtok(3) still makes more sense there.
This commit doesn't replace such strtok(3) calls.

While at this, remove some useless variables used by these calls, and
reduce the scope of others.

Signed-off-by: Alejandro Colomar <alx@kernel.org>
This commit is contained in:
Alejandro Colomar
2024-07-04 13:21:12 +02:00
committed by Serge Hallyn
parent bdb5e2b79f
commit 90afe61003
7 changed files with 70 additions and 65 deletions

View File

@@ -14,9 +14,10 @@
#include "prototypes.h" #include "prototypes.h"
#include "defines.h" #include "defines.h"
#include <stdio.h>
#include <grp.h>
#include <errno.h> #include <errno.h>
#include <grp.h>
#include <stdio.h>
#include <string.h>
#include "alloc/malloc.h" #include "alloc/malloc.h"
#include "alloc/reallocf.h" #include "alloc/reallocf.h"
@@ -24,19 +25,19 @@
#ident "$Id$" #ident "$Id$"
#define SEP ",:"
/* /*
* Add groups with names from LIST (separated by commas or colons) * Add groups with names from LIST (separated by commas or colons)
* to the supplementary group set. Silently ignore groups which are * to the supplementary group set. Silently ignore groups which are
* already there. Warning: uses strtok(). * already there.
*/ */
int add_groups (const char *list) int
add_groups(const char *list)
{ {
GETGROUPS_T *grouplist; GETGROUPS_T *grouplist;
size_t i; size_t i;
int ngroups; int ngroups;
bool added; bool added;
char *token; char *g, *p;
char buf[1024]; char buf[1024];
int ret; int ret;
FILE *shadow_logfd = log_get_logfd(); FILE *shadow_logfd = log_get_logfd();
@@ -71,13 +72,13 @@ int add_groups (const char *list)
} }
added = false; added = false;
for (token = strtok (buf, SEP); NULL != token; token = strtok (NULL, SEP)) { p = buf;
while (NULL != (g = strsep(&p, ",:"))) {
struct group *grp; struct group *grp;
grp = getgrnam (token); /* local, no need for xgetgrnam */ grp = getgrnam(g); /* local, no need for xgetgrnam */
if (NULL == grp) { if (NULL == grp) {
fprintf (shadow_logfd, _("Warning: unknown group %s\n"), fprintf(shadow_logfd, _("Warning: unknown group %s\n"), g);
token);
continue; continue;
} }

View File

@@ -26,7 +26,8 @@
* under "cfgin" in config (directly or indirectly). Fallback to default if * under "cfgin" in config (directly or indirectly). Fallback to default if
* something is bad. * something is bad.
*/ */
static bool is_listed (const char *cfgin, const char *tty, bool def) static bool
is_listed(const char *cfgin, const char *tty, bool def)
{ {
FILE *fp; FILE *fp;
char buf[1024], *s; char buf[1024], *s;
@@ -49,14 +50,13 @@ static bool is_listed (const char *cfgin, const char *tty, bool def)
if (*cons != '/') { if (*cons != '/') {
char *pbuf; char *pbuf;
STRTCPY(buf, cons); STRTCPY(buf, cons);
pbuf = &buf[0]; pbuf = buf;
while ((s = strtok (pbuf, ":")) != NULL) { while (NULL != (s = strsep(&pbuf, ":"))) {
if (streq(s, tty)) { if (streq(s, tty)) {
return true; return true;
} }
pbuf = NULL;
} }
return false; return false;
} }

View File

@@ -12,6 +12,7 @@
#ident "$Id$" #ident "$Id$"
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "defines.h" #include "defines.h"
#include "getdef.h" #include "getdef.h"
@@ -26,7 +27,8 @@
* it to the user's terminal at login time. The MOTD_FILE configuration * it to the user's terminal at login time. The MOTD_FILE configuration
* option is a colon-delimited list of filenames. * option is a colon-delimited list of filenames.
*/ */
void motd (void) void
motd(void)
{ {
FILE *fp; FILE *fp;
char *motdlist; char *motdlist;
@@ -41,12 +43,8 @@ void motd (void)
motdlist = xstrdup (motdfile); motdlist = xstrdup (motdfile);
for (mb = motdlist; ;mb = NULL) { mb = motdlist;
motdfile = strtok (mb, ":"); while (NULL != (motdfile = strsep(&mb, ":"))) {
if (NULL == motdfile) {
break;
}
fp = fopen (motdfile, "r"); fp = fopen (motdfile, "r");
if (NULL != fp) { if (NULL != fp) {
while ((c = getc (fp)) != EOF) { while ((c = getc (fp)) != EOF) {

View File

@@ -16,6 +16,7 @@
#include <getopt.h> #include <getopt.h>
#include <grp.h> #include <grp.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <sys/types.h> #include <sys/types.h>
#ifdef ACCT_TOOLS_SETUID #ifdef ACCT_TOOLS_SETUID
#ifdef USE_PAM #ifdef USE_PAM
@@ -164,7 +165,8 @@ static void new_sgent (struct sgrp *sgent)
* *
* grp_update() writes the new records to the group files. * grp_update() writes the new records to the group files.
*/ */
static void grp_update (void) static void
grp_update(void)
{ {
struct group grp; struct group grp;
@@ -196,19 +198,20 @@ static void grp_update (void)
#endif /* SHADOWGRP */ #endif /* SHADOWGRP */
if (user_list) { if (user_list) {
char *token; char *u, *ul;
token = strtok(user_list, ",");
while (token) { ul = user_list;
if (prefix_getpwnam (token) == NULL) { while (NULL != (u = strsep(&ul, ","))) {
fprintf (stderr, _("Invalid member username %s\n"), token); if (prefix_getpwnam(u) == NULL) {
fprintf(stderr, _("Invalid member username %s\n"), u);
exit (E_GRP_UPDATE); exit (E_GRP_UPDATE);
} }
grp.gr_mem = add_list(grp.gr_mem, token);
grp.gr_mem = add_list(grp.gr_mem, u);
#ifdef SHADOWGRP #ifdef SHADOWGRP
if (is_shadow_grp) if (is_shadow_grp)
sgrp.sg_mem = add_list(sgrp.sg_mem, token); sgrp.sg_mem = add_list(sgrp.sg_mem, u);
#endif #endif
token = strtok(NULL, ",");
} }
} }

View File

@@ -17,6 +17,7 @@
#include <grp.h> #include <grp.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <strings.h> #include <strings.h>
#include <sys/types.h> #include <sys/types.h>
#ifdef ACCT_TOOLS_SETUID #ifdef ACCT_TOOLS_SETUID
@@ -198,7 +199,8 @@ static void new_sgent (struct sgrp *sgent)
* *
* grp_update() updates the new records in the memory databases. * grp_update() updates the new records in the memory databases.
*/ */
static void grp_update (void) static void
grp_update(void)
{ {
struct group grp; struct group grp;
const struct group *ogrp; const struct group *ogrp;
@@ -251,7 +253,7 @@ static void grp_update (void)
} }
if (user_list) { if (user_list) {
char *token; char *u, *ul;
if (!aflg) { if (!aflg) {
// requested to replace the existing groups // requested to replace the existing groups
@@ -274,18 +276,18 @@ static void grp_update (void)
} }
#endif /* SHADOWGRP */ #endif /* SHADOWGRP */
token = strtok(user_list, ","); ul = user_list;
while (token) { while (NULL != (u = strsep(&ul, ","))) {
if (prefix_getpwnam (token) == NULL) { if (prefix_getpwnam(u) == NULL) {
fprintf (stderr, _("Invalid member username %s\n"), token); fprintf(stderr, _("Invalid member username %s\n"), u);
exit (E_GRP_UPDATE); exit (E_GRP_UPDATE);
} }
grp.gr_mem = add_list(grp.gr_mem, token);
grp.gr_mem = add_list(grp.gr_mem, u);
#ifdef SHADOWGRP #ifdef SHADOWGRP
if (NULL != osgrp) if (NULL != osgrp)
sgrp.sg_mem = add_list(sgrp.sg_mem, token); sgrp.sg_mem = add_list(sgrp.sg_mem, u);
#endif /* SHADOWGRP */ #endif /* SHADOWGRP */
token = strtok(NULL, ",");
} }
} }

View File

@@ -67,10 +67,6 @@
#define TABLE "/etc/login.access" #define TABLE "/etc/login.access"
#endif #endif
/* Delimiters for fields and for lists of users, ttys or hosts. */
static char fs[] = ":"; /* field separator */
static char sep[] = ", \t"; /* list-element separator */
static bool list_match (char *list, const char *item, bool (*match_fn) (const char *, const char *)); static bool list_match (char *list, const char *item, bool (*match_fn) (const char *, const char *));
static bool user_match (const char *tok, const char *string); static bool user_match (const char *tok, const char *string);
static bool from_match (const char *tok, const char *string); static bool from_match (const char *tok, const char *string);
@@ -78,7 +74,8 @@ static bool string_match (const char *tok, const char *string);
static const char *resolve_hostname (const char *string); static const char *resolve_hostname (const char *string);
/* login_access - match username/group and host/tty with access control file */ /* login_access - match username/group and host/tty with access control file */
int login_access (const char *user, const char *from) int
login_access(const char *user, const char *from)
{ {
FILE *fp; FILE *fp;
char line[BUFSIZ]; char line[BUFSIZ];
@@ -98,7 +95,10 @@ int login_access (const char *user, const char *from)
if (NULL != fp) { if (NULL != fp) {
int lineno = 0; /* for diagnostics */ int lineno = 0; /* for diagnostics */
while ( !match while ( !match
&& (fgets (line, sizeof (line), fp) == line)) { && (fgets (line, sizeof (line), fp) == line))
{
char *p;
lineno++; lineno++;
if (stpsep(line, "\n") == NULL) { if (stpsep(line, "\n") == NULL) {
SYSLOG ((LOG_ERR, SYSLOG ((LOG_ERR,
@@ -113,10 +113,11 @@ int login_access (const char *user, const char *from)
if (line[0] == '\0') { /* skip blank lines */ if (line[0] == '\0') { /* skip blank lines */
continue; continue;
} }
if ( ((perm = strtok (line, fs)) == NULL) p = line;
|| ((users = strtok (NULL, fs)) == NULL) perm = strsep(&p, ":");
|| ((froms = strtok (NULL, fs)) == NULL) users = strsep(&p, ":");
|| (strtok (NULL, fs) != NULL)) { froms = strsep(&p, ":");
if (froms == NULL || p != NULL) {
SYSLOG ((LOG_ERR, SYSLOG ((LOG_ERR,
"%s: line %d: bad field count", "%s: line %d: bad field count",
TABLE, lineno)); TABLE, lineno));
@@ -140,8 +141,11 @@ int login_access (const char *user, const char *from)
} }
/* list_match - match an item against a list of tokens with exceptions */ /* list_match - match an item against a list of tokens with exceptions */
static bool list_match (char *list, const char *item, bool (*match_fn) (const char *, const char*)) static bool
list_match(char *list, const char *item, bool (*match_fn)(const char *, const char*))
{ {
static const char sep[] = ", \t";
char *tok; char *tok;
bool match = false; bool match = false;
@@ -151,7 +155,7 @@ static bool list_match (char *list, const char *item, bool (*match_fn) (const ch
* a match, look for an "EXCEPT" list and recurse to determine whether * a match, look for an "EXCEPT" list and recurse to determine whether
* the match is affected by any exceptions. * the match is affected by any exceptions.
*/ */
for (tok = strtok (list, sep); tok != NULL; tok = strtok (NULL, sep)) { while (NULL != (tok = strsep(&list, sep))) {
if (strcasecmp (tok, "EXCEPT") == 0) { /* EXCEPT: give up */ if (strcasecmp (tok, "EXCEPT") == 0) { /* EXCEPT: give up */
break; break;
} }
@@ -163,7 +167,7 @@ static bool list_match (char *list, const char *item, bool (*match_fn) (const ch
/* Process exceptions to matches. */ /* Process exceptions to matches. */
if (match) { if (match) {
while ( ((tok = strtok (NULL, sep)) != NULL) while ( (NULL != (tok = strsep(&list, sep)))
&& (strcasecmp (tok, "EXCEPT") != 0)) && (strcasecmp (tok, "EXCEPT") != 0))
/* VOID */ ; /* VOID */ ;
if (tok == NULL || !list_match(NULL, item, match_fn)) { if (tok == NULL || !list_match(NULL, item, match_fn)) {

View File

@@ -45,11 +45,9 @@ static int isgrp (const char *, const char *);
static int lines = 0; static int lines = 0;
int check_su_auth (const char *actual_id, int
const char *wanted_id, check_su_auth(const char *actual_id, const char *wanted_id, bool su_to_root)
bool su_to_root)
{ {
const char field[] = ":";
FILE *authfile_fd; FILE *authfile_fd;
char temp[1024]; char temp[1024];
char *to_users; char *to_users;
@@ -91,10 +89,10 @@ int check_su_auth (const char *actual_id,
if (*p == '#' || *p == '\0') if (*p == '#' || *p == '\0')
continue; continue;
if (!(to_users = strtok(p, field)) to_users = strsep(&p, ":");
|| !(from_users = strtok (NULL, field)) from_users = strsep(&p, ":");
|| !(action = strtok (NULL, field)) action = strsep(&p, ":");
|| strtok (NULL, field)) { if (action == NULL || p != NULL) {
SYSLOG ((LOG_ERR, SYSLOG ((LOG_ERR,
"%s, line %d. Bad number of fields.\n", "%s, line %d. Bad number of fields.\n",
SUAUTHFILE, lines)); SUAUTHFILE, lines));
@@ -138,15 +136,14 @@ int check_su_auth (const char *actual_id,
return NOACTION; return NOACTION;
} }
static int applies (const char *single, char *list) static int
applies(const char *single, char *list)
{ {
const char split[] = ", ";
char *tok; char *tok;
int state = 0; int state = 0;
for (tok = strtok (list, split); tok != NULL; while (NULL != (tok = strsep(&list, ", "))) {
tok = strtok (NULL, split)) {
if (streq(tok, "ALL")) { if (streq(tok, "ALL")) {
if (state != 0) { if (state != 0) {