| /* { dg-do compile } */ |
| /* { dg-options "-O2 -Wnull-dereference" } */ |
| |
| typedef __SIZE_TYPE__ size_t; |
| typedef unsigned long int uintmax_t; |
| |
| struct group |
| { |
| char *gr_name; |
| char *gr_passwd; |
| unsigned gr_gid; |
| char **gr_mem; |
| }; |
| |
| struct passwd |
| { |
| char *pw_name; |
| char *pw_passwd; |
| |
| unsigned pw_uid; |
| unsigned pw_gid; |
| char *pw_gecos; |
| char *pw_dir; |
| char *pw_shell; |
| }; |
| |
| extern struct group *getgrnam (const char *); |
| extern struct group *getgrgid (unsigned); |
| extern void endgrent (void); |
| extern struct passwd *getpwnam (const char *); |
| extern void endpwent (void); |
| extern unsigned long int strtoul (const char *__restrict, |
| char **__restrict, int); |
| |
| char const * |
| parse_with_separator (char const *spec, char const *separator, |
| unsigned *uid, unsigned *gid, |
| char **username, char **groupname) |
| { |
| static const char *E_invalid_user = "invalid user"; |
| static const char *E_invalid_group = "invalid group"; |
| static const char *E_bad_spec = "invalid spec"; |
| const char *error_msg; |
| struct passwd *pwd; |
| struct group *grp; |
| char *u; |
| char const *g; |
| char *gname = 0; |
| unsigned unum = *uid; |
| unsigned gnum = gid ? *gid : (unsigned)-1; |
| |
| error_msg = 0; |
| |
| if (username) |
| *username = 0; |
| |
| if (groupname) |
| *groupname = 0; |
| |
| u = 0; |
| if (separator == 0) |
| { |
| if (*spec) |
| u = __builtin_strdup (spec); |
| } |
| else |
| { |
| size_t ulen = separator - spec; |
| if (ulen != 0) |
| { |
| u = __builtin_malloc (ulen + 1); |
| __builtin_memcpy (u, spec, ulen + 1); |
| u[ulen] = '\0'; |
| } |
| } |
| |
| g = (separator == 0 || *(separator + 1) == '\0' ? 0 : separator + 1); |
| |
| if (u != 0) |
| { |
| pwd = (*u == '+' ? 0 : getpwnam (u)); |
| if (pwd == 0) |
| { |
| _Bool use_login_group = (separator != 0 && g == 0); |
| if (use_login_group) |
| { |
| error_msg = E_bad_spec; |
| } |
| else |
| { |
| unsigned long int tmp; |
| tmp = strtoul (u, 0, 10); |
| if (tmp <= (1ul << 31) && (unsigned) tmp != (unsigned) -1) |
| unum = tmp; |
| else |
| error_msg = E_invalid_user; |
| } |
| } |
| else |
| { |
| unum = pwd->pw_uid; |
| if (g == 0 && separator != 0) |
| { |
| char buf[128]; |
| gnum = pwd->pw_gid; |
| grp = getgrgid (gnum); |
| |
| gname = buf; |
| |
| if (grp) |
| gname = __builtin_strdup (grp->gr_name); |
| else |
| __builtin_snprintf (buf, sizeof(buf), "%ju", (uintmax_t)gnum); |
| |
| endgrent (); |
| } |
| } |
| |
| endpwent (); |
| } |
| |
| if (g != 0 && error_msg == 0) |
| { |
| grp = (*g == '+' ? 0 : getgrnam (g)); |
| if (grp == 0) |
| { |
| unsigned long int tmp = strtoul (g, 0, 10); |
| |
| if (tmp <= (1ul << 31) && (unsigned) tmp != (unsigned) -1) |
| gnum = tmp; |
| else |
| error_msg = E_invalid_group; |
| } |
| else |
| gnum = grp->gr_gid; |
| endgrent (); |
| gname = __builtin_strdup (g); |
| } |
| |
| if (error_msg == 0) |
| { |
| *uid = unum; |
| if (gid) |
| *gid = gnum; |
| if (username) |
| { |
| *username = u; |
| u = 0; |
| } |
| if (groupname) |
| { |
| *groupname = gname; |
| gname = 0; |
| } |
| } |
| |
| __builtin_free (u); |
| __builtin_free (gname); |
| return error_msg ? error_msg : 0; |
| } |
| |