- char *endptr;
- char *p;
- int i;
-
- i = 0;
- do {
- p = ((char *) ((struct passwd *) data)) + pw_off[i];
-
- if ((i & 6) ^ 2) { /* i!=2 and i!=3 */
- *((char **) p) = line;
- if (i==6) {
- return 0;
- }
- /* NOTE: glibc difference - glibc allows omission of
- * ':' seperators after the gid field if all remaining
- * entries are empty. We require all separators. */
- line = strchr(line, ':');
- if (!line) {
- break;
- }
- } else {
- unsigned long t = strtoul(line, &endptr, 10);
- /* Make sure we had at least one digit, and that the
- * failing char is the next field seperator ':'. See
- * glibc difference note above. */
- /* TODO: Also check for leading whitespace? */
- if ((endptr == line) || (*endptr != ':')) {
- break;
- }
- line = endptr;
- if (i & 1) { /* i == 3 -- gid */
- *((gid_t *) p) = t;
- } else { /* i == 2 -- uid */
- *((uid_t *) p) = t;
- }
- }
-
- *line++ = 0;
- ++i;
- } while (1);
-
- return -1;
-}
-
-/**********************************************************************/
-
-static const unsigned char gr_off[] = {
- offsetof(struct group, gr_name), /* 0 */
- offsetof(struct group, gr_passwd), /* 1 */
- offsetof(struct group, gr_gid) /* 2 - not a char ptr */
-};
-
-static int __parsegrent(void *data, char *line)
-{
- char *endptr;
- char *p;
- int i;
- char **members;
- char *end_of_buf;
-
- end_of_buf = ((struct group *) data)->gr_name; /* Evil hack! */
- i = 0;
- do {
- p = ((char *) ((struct group *) data)) + gr_off[i];
-
- if (i < 2) {
- *((char **) p) = line;
- line = strchr(line, ':');
- if (!line) {
- break;
- }
- *line++ = 0;
- ++i;
- } else {
- *((gid_t *) p) = strtoul(line, &endptr, 10);
-
- /* NOTE: glibc difference - glibc allows omission of the
- * trailing colon when there is no member list. We treat
- * this as an error. */
-
- /* Make sure we had at least one digit, and that the
- * failing char is the next field seperator ':'. See
- * glibc difference note above. */
- if ((endptr == line) || (*endptr != ':')) {
- break;
- }
-
- i = 1; /* Count terminating NULL ptr. */
- p = endptr;
-
- if (p[1]) { /* We have a member list to process. */
- /* Overwrite the last ':' with a ',' before counting.
- * This allows us to test for initial ',' and adds
- * one ',' so that the ',' count equals the member
- * count. */
- *p = ',';
- do {
- /* NOTE: glibc difference - glibc allows and trims leading
- * (but not trailing) space. We treat this as an error. */
- /* NOTE: glibc difference - glibc allows consecutive and
- * trailing commas, and ignores "empty string" users. We
- * treat this as an error. */
- if (*p == ',') {
- ++i;
- *p = 0; /* nul-terminate each member string. */
- if (!*++p || (*p == ',') || isspace(*p)) {
- goto ERR;
- }
- }
- } while (*++p);
- }
-
- /* Now align (p+1), rounding up. */
- /* Assumes sizeof(char **) is a power of 2. */
- members = (char **)( (((intptr_t) p) + sizeof(char **))
- & ~((intptr_t)(sizeof(char **) - 1)) );
-
- if (((char *)(members + i)) > end_of_buf) { /* No space. */
- break;
- }
-
- ((struct group *) data)->gr_mem = members;