From 51fa767a75930d869b1db6237762c00fac40a22d Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Fri, 18 Jul 2025 23:53:30 +0200 Subject: [PATCH] src/chfn.c: Do not allow the 'slop' fields to appear before any non-slop gecos fields According to the Wikipedia page for the 'Gecos field', the "typical" format for the GECOS field is a comma-delimited list with this order: 1) User's full name (or application name, if the account is for a program) 2) Building and room number or contact person 3) Office telephone number 4) Home telephone number 5+) Any other contact information (pager number, fax, external e-mail address, etc.) But our code supported the "other contact information", which we call slop, and which is composed of an arbitrary number of key=value fields, to appear before any of the other 4 fields. This seems to be undocumented, and none of the documentation I've found for the GECOS field in any systems I checked claims to support this. By removing support for those, we can significantly simplify the copy_field() function, which was quite unreadable. After this patch, the GECOS field is treated as a CSV, blindly copying the fields as they appear, where the first 4 fields are as specified above, and anything after them is the slop (5+ fields, any other contact information). Signed-off-by: Alejandro Colomar --- src/chfn.c | 42 ++++++++++-------------------------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/src/chfn.c b/src/chfn.c index 2fb0825df..9d7a2343f 100644 --- a/src/chfn.c +++ b/src/chfn.c @@ -214,33 +214,15 @@ static void new_fields (void) * * in - the current GECOS field * out - where to copy the field to - * extra - fields with '=' get copied here */ -static char *copy_field (char *in, char *out, char *extra) +static char *copy_field(char *in, char *out) { - char *next = NULL; + char *next; - while (NULL != in) { - const char *f; + next = stpsep(in, ","); - f = in; - next = stpsep(in, ","); - - if (strchr(f, '=') == NULL) - break; - - if (NULL != extra) { - if (!streq(extra, "")) { - strcat (extra, ","); - } - - strcat(extra, f); - } - in = next; - } - if ((NULL != in) && (NULL != out)) { - strcpy (out, in); - } + if (out != NULL) + strcpy(out, in); return next; } @@ -521,39 +503,35 @@ static void get_old_fields (const char *gecos) * Now get the full name. It is the first comma separated field in * the GECOS field. */ - cp = copy_field (old_gecos, fflg ? NULL : fullnm, slop); + cp = copy_field(old_gecos, fflg ? NULL : fullnm); /* * Now get the room number. It is the next comma separated field, * if there is indeed one. */ if (NULL != cp) { - cp = copy_field (cp, rflg ? NULL : roomno, slop); + cp = copy_field(cp, rflg ? NULL : roomno); } /* * Now get the work phone number. It is the third field. */ if (NULL != cp) { - cp = copy_field (cp, wflg ? NULL : workph, slop); + cp = copy_field(cp, wflg ? NULL : workph); } /* * Now get the home phone number. It is the fourth field. */ if (NULL != cp) { - cp = copy_field (cp, hflg ? NULL : homeph, slop); + cp = copy_field(cp, hflg ? NULL : homeph); } /* * Anything left over is "slop". */ if ((NULL != cp) && !oflg) { - if (!streq(slop, "")) { - strcat (slop, ","); - } - - strcat (slop, cp); + strcpy(slop, cp); } } -- 2.47.3