rem: static const char *E_invalid_user = N_("invalid user"); static const char *E_invalid_group = N_("invalid group"); static const char *E_bad_spec = N_("cannot get the login group of a numeric UID"); static const char *E_cannot_omit_both = N_("cannot omit both user and group");
add: char const *colon = strchr (spec, ':'); char const *error_msg = parse_with_separator (spec, colon, uid, gid, username, groupname);
context: parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,		 char **username_arg, char **groupname_arg){  static const char *E_invalid_user = N_("invalid user");  static const char *E_invalid_group = N_("invalid group");  static const char *E_bad_spec =    N_("cannot get the login group of a numeric UID");  static const char *E_cannot_omit_both =    N_("cannot omit both user and group");  const char *error_msg;  char *spec;			/* A copy we can write on.  */  struct passwd *pwd;  struct group *grp;  char *g, *u, *separator;  char *groupname;  int maybe_retry = 0;  char *dot = NULL;  error_msg = NULL;  *username_arg = *groupname_arg = NULL;  groupname = NULL;  V_STRDUP (spec, spec_arg);  /* Find the POSIX `:' separator if there is one.  */  separator = strchr (spec, ':');  /* If there is no colon, then see if there's a `.'.  */  if (separator == NULL)    {      dot = strchr (spec, '.');      /* If there's no colon but there is a `.', then first look up the	 whole spec, in case it's an OWNER name that includes a dot.	 If that fails, then we'll try again, but interpreting the `.'	 as a separator.  */      /* FIXME: accepting `.' as the separator is contrary to POSIX.	 someday we should drop support for this.  */      if (dot)	maybe_retry = 1;    } retry:  /* Replace separator with a NUL.  */  if (separator != NULL)    *separator = '\0';  /* Set U and G to non-zero length strings corresponding to user and     group specifiers or to NULL.  */  u = (*spec == '\0' ? NULL : spec);  g = (separator == NULL || *(separator + 1) == '\0'       ? NULL       : separator + 1);  if (u == NULL && g == NULL)    return _(E_cannot_omit_both);#ifdef __DJGPP__  /* Pretend that we are the user U whose group is G.  This makes     pwd and grp functions ``know'' about the UID and GID of these.  */  if (u && !is_number (u))    setenv ("USER", u, 1);  if (g && !is_number (g))    setenv ("GROUP", g, 1);#endif  if (u != NULL)    {      pwd = getpwnam (u);      if (pwd == NULL)	{	  if (!is_number (u))	    error_msg = E_invalid_user;	  else	    {	      int use_login_group;	      use_login_group = (separator != NULL && g == NULL);	      if (use_login_group)		error_msg = E_bad_spec;	      else		{		  unsigned long int tmp_long;		  if (xstrtoul (u, NULL, 0, &tmp_long, NULL) != LONGINT_OK		      || tmp_long > MAXUID)		    return _(E_invalid_user);		  *uid = tmp_long;		}	    }	}      else	{	  *uid = pwd->pw_uid;	  if (g == NULL && separator != NULL)	    {	      /* A separator was given, but a group was not specified,	         so get the login group.  */	      *gid = pwd->pw_gid;	      grp = getgrgid (pwd->pw_gid);	      if (grp == NULL)		{		  /* This is enough room to hold the unsigned decimal		     representation of any 32-bit quantity and the trailing		     zero byte.  */		  char uint_buf[21];		  sprintf (uint_buf, "%u", (unsigned) (pwd->pw_gid));		  V_STRDUP (groupname, uint_buf);		}	      else		{		  V_STRDUP (groupname, grp->gr_name);		}	      endgrent ();	    }	}      endpwent ();    }  if (g != NULL && error_msg == NULL)    {      /* Explicit group.  */      grp = getgrnam (g);      if (grp == NULL)	{	  if (!is_number (g))	    error_msg = E_invalid_group;	  else	    {	      unsigned long int tmp_long;	      if (xstrtoul (g, NULL, 0, &tmp_long, NULL) != LONGINT_OK		  || tmp_long > MAXGID)		return _(E_invalid_group);	      *gid = tmp_long;	    }	}      else	*gid = grp->gr_gid;      endgrent ();		/* Save a file descriptor.  */      if (error_msg == NULL)	V_STRDUP (groupname, g);    }  if (error_msg == NULL)    {      if (u != NULL)	{	  *username_arg = strdup (u);	  if (*username_arg == NULL)	    error_msg = xalloc_msg_memory_exhausted;	}      if (groupname != NULL && error_msg == NULL)	{	  *groupname_arg = strdup (groupname);	  if (*groupname_arg == NULL)	    {	      if (*username_arg != NULL)		{		  free (*username_arg);		  *username_arg = NULL;		}	      error_msg = xalloc_msg_memory_exhausted;	    }	}    }  if (error_msg && maybe_retry)    {      maybe_retry = 0;      separator = dot;      error_msg = NULL;      goto retry;    }  return _(error_msg);}