/* -*-c-*-
*
- * $Id: userdb.c,v 1.7 1998/04/23 13:27:46 mdw Exp $
+ * $Id: userdb.c,v 1.8 1998/06/08 11:21:22 mdw Exp $
*
* User database management
*
/*----- Revision history --------------------------------------------------*
*
* $Log: userdb.c,v $
+ * Revision 1.8 1998/06/08 11:21:22 mdw
+ * Fixed bug in password and group file reading: strtok doesn't handle
+ * double colons nicely.
+ *
* Revision 1.7 1998/04/23 13:27:46 mdw
* Switch to using the ypstuff interface to YP server.
*
#endif
+/* --- @userdb__split@ --- *
+ *
+ * Arguments: @char *p@ = pointer to string
+ * @char **v@ = pointer to vector to fill in
+ * @int sz@ = maximum number of fields to split
+ *
+ * Returns: Number of fields extracted.
+ *
+ * Use: Splits a string into fields at colon characters.
+ */
+
+static int userdb__split(char *p, char **v, int sz)
+{
+ int count = 0;
+
+ *v++ = p; sz--; count++;
+ if (!sz)
+ goto done;
+ while (*p) {
+ if (*p++ == ':') {
+ p[-1] = 0;
+ *v++ = p; sz--; count++;
+ if (!sz)
+ goto done;
+ }
+ }
+ while (sz--)
+ *v++ = 0;
+
+done:
+ return (count);
+}
+
/* --- @userdb_copyUser@ --- *
*
* Arguments: @struct passwd *pw@ = pointer to block to copy
static struct passwd *userdb__buildUser(char *s)
{
struct passwd *pw = xmalloc(sizeof(*pw));
+ char *v[7];
- s = strtok(s, ":"); if (!s) goto tidy_0; pw->pw_name = xstrdup(s);
- s = strtok(0, ":"); if (!s) goto tidy_1; pw->pw_passwd = xstrdup(s);
- s = strtok(0, ":"); if (!s) goto tidy_2; pw->pw_uid = (uid_t)atol(s);
- s = strtok(0, ":"); if (!s) goto tidy_2; pw->pw_gid = (gid_t)atol(s);
- s = strtok(0, ":"); if (!s) goto tidy_2; pw->pw_gecos = xstrdup(s);
- s = strtok(0, ":"); if (!s) goto tidy_3; pw->pw_dir = xstrdup(s);
- s = strtok(0, ":"); if (!s) goto tidy_4; pw->pw_shell = xstrdup(s);
- return (pw);
-
- /* --- Error handling --- */
-
-tidy_4:
- free(pw->pw_dir);
-tidy_3:
- free(pw->pw_gecos);
-tidy_2:
- free(pw->pw_passwd);
-tidy_1:
- free(pw->pw_name);
-tidy_0:
- free(pw);
+ if (userdb__split(s, v, 7) < 7) {
+ free(pw);
+ return (0);
+ }
- return (0);
+ pw->pw_name = xstrdup(v[0]);
+ pw->pw_passwd = xstrdup(v[1]);
+ pw->pw_uid = (uid_t)atol(v[2]);
+ pw->pw_gid = (gid_t)atol(v[3]);
+ pw->pw_gecos = xstrdup(v[4]);
+ pw->pw_dir = xstrdup(v[5]);
+ pw->pw_shell = xstrdup(v[6]);
+ return (pw);
}
/* --- @userdb_freeUser@ --- *
static struct group *userdb__buildGroup(char *s)
{
struct group *gr = xmalloc(sizeof(*gr));
- char *p;
+ char *v[4];
int i;
/* --- Do the easy bits --- */
- s = strtok(s, ":"); if (!s) goto tidy_0; gr->gr_name = xstrdup(s);
- s = strtok(0, ":"); if (!s) goto tidy_1; gr->gr_passwd = xstrdup(s);
- s = strtok(0, ":"); if (!s) goto tidy_2; gr->gr_gid = (gid_t)atol(s);
-
- /* --- Find the start of the member list --- */
-
- s = strtok(0, "");
- if (!s)
- goto tidy_2;
+ if (userdb__split(s, v, 4) < 3) {
+ free(gr);
+ return (0);
+ }
+ gr->gr_name = xstrdup(v[0]);
+ gr->gr_passwd = xstrdup(v[1]);
+ gr->gr_gid = (gid_t)atol(v[2]);
/* --- Count the number of members --- */
- p = s;
+ s = v[3];
i = 0;
- for (;;) {
- i++;
- if ((p = strpbrk(p, ",")) == 0)
- break;
- p++;
+ if (s && s[0]) {
+ for (;;) {
+ i++;
+ if ((s = strpbrk(s, ",")) == 0)
+ break;
+ s++;
+ }
}
/* --- Allocate the block and fill it --- */
gr->gr_mem = xmalloc((i + 1) * sizeof(char *));
i = 0;
- s = strtok(s, ",");
- do {
- gr->gr_mem[i++] = xstrdup(s);
- s = strtok(0, ",");
- } while (s);
+ if (v[3]) {
+ s = strtok(v[3], ",");
+ while (s) {
+ gr->gr_mem[i++] = xstrdup(s);
+ s = strtok(0, ",");
+ }
+ }
gr->gr_mem[i] = 0;
return (gr);
-
- /* --- Various tidying-up things --- */
-
-tidy_2:
- free(gr->gr_passwd);
-tidy_1:
- free(gr->gr_name);
-tidy_0:
- free(gr);
-
- return (0);
}
/* --- @userdb_freeGroup@ --- *