/* userspec.c -- Parse a user and group string.
- Copyright (C) 1989-1992, 1997, 1998, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1989-1992, 1997-1998, 2000, 2002-2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
# include <config.h>
#endif
-#ifdef __GNUC__
-# define alloca __builtin_alloca
-#else
-# if HAVE_ALLOCA_H
-# include <alloca.h>
-# else
-# ifdef _AIX
- # pragma alloca
-# else
-char *alloca ();
-# endif
-# endif
-#endif
+#include <alloca.h>
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
+#if HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
#if HAVE_STRING_H
# include <string.h>
#else
# include <unistd.h>
#endif
-#if ENABLE_NLS
-# include <libintl.h>
-# define _(Text) gettext (Text)
-#else
-# define _(Text) Text
-#endif
-#define N_(Text) Text
+#include "xalloc.h"
+#include "xstrtol.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+#define N_(msgid) msgid
#ifndef _POSIX_VERSION
struct passwd *getpwnam ();
# define endpwent() ((void) 0)
#endif
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+
+/* The extra casts work around common compiler bugs. */
+#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1))
+/* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
+ It is necessary at least when t == time_t. */
+#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
+ ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0))
+#define TYPE_MAXIMUM(t) ((t) (~ (t) 0 - TYPE_MINIMUM (t)))
+
+#ifndef UID_T_MAX
+# define UID_T_MAX TYPE_MAXIMUM (uid_t)
+#endif
+
+#ifndef GID_T_MAX
+# define GID_T_MAX TYPE_MAXIMUM (gid_t)
+#endif
+
+/* MAXUID may come from limits.h or sys/params.h. */
+#ifndef MAXUID
+# define MAXUID UID_T_MAX
+#endif
+#ifndef MAXGID
+# define MAXGID GID_T_MAX
+#endif
+
/* Perform the equivalent of the statement `dest = strdup (src);',
but obtaining storage via alloca instead of from the heap. */
- Its arg may be any int or unsigned int; it need not be an unsigned char.
- It's guaranteed to evaluate its argument exactly once.
- It's typically faster.
- Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
- only '0' through '9' are digits. Prefer ISDIGIT to isdigit unless
- it's important to use the locale's definition of `digit' even when the
- host does not conform to Posix. */
+ POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
+ ISDIGIT_LOCALE unless it's important to use the locale's definition
+ of `digit' even when the host does not conform to POSIX. */
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
#ifndef strdup
use the given user's login group.
If SPEC_ARG contains a `:', then use that as the separator, ignoring
any `.'s. If there is no `:', but there is a `.', then first look
- up SPEC_ARG as a login name. If that look-up fails, then try again
- interpreting the `.' as a separator.
+ up the entire SPEC_ARG as a login name. If that look-up fails, then
+ try again interpreting the `.' as a separator.
USERNAME and GROUPNAME will be in newly malloc'd memory.
Either one might be NULL instead, indicating that it was not
parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
char **username_arg, char **groupname_arg)
{
- static const char *E_no_memory = N_("virtual memory exhausted");
static const char *E_invalid_user = N_("invalid user");
static const char *E_invalid_group = N_("invalid group");
static const char *E_bad_spec =
{
if (!is_number (u))
- error_msg = _(E_invalid_user);
+ 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);
+ error_msg = E_bad_spec;
else
{
- /* FIXME: don't use atoi! */
- *uid = atoi (u);
+ 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;
}
}
}
if (grp == NULL)
{
if (!is_number (g))
- error_msg = _(E_invalid_group);
+ error_msg = E_invalid_group;
else
{
- /* FIXME: don't use atoi! */
- *gid = atoi (g);
+ 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
{
*username_arg = strdup (u);
if (*username_arg == NULL)
- error_msg = _(E_no_memory);
+ error_msg = xalloc_msg_memory_exhausted;
}
if (groupname != NULL && error_msg == NULL)
free (*username_arg);
*username_arg = NULL;
}
- error_msg = _(E_no_memory);
+ error_msg = xalloc_msg_memory_exhausted;
}
}
}
goto retry;
}
- return error_msg;
+ return _(error_msg);
}
#ifdef TEST