*** empty log message ***
[gnulib.git] / lib / userspec.c
index 7bb4ba1..1d3df6e 100644 (file)
@@ -1,5 +1,5 @@
 /* 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 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
@@ -40,6 +40,14 @@ char *alloca ();
 #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
@@ -58,6 +66,7 @@ char *alloca ();
 #endif
 
 #include "xalloc.h"
+#include "xstrtol.h"
 
 #if ENABLE_NLS
 # include <libintl.h>
@@ -81,6 +90,34 @@ struct group *getgrgid ();
 # 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.  */
 
@@ -97,10 +134,9 @@ struct group *getgrgid ();
    - 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
@@ -126,8 +162,8 @@ is_number (const char *str)
    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
@@ -220,8 +256,11 @@ parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
                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;
                }
            }
        }
@@ -263,8 +302,11 @@ parse_user_spec (const char *spec_arg, uid_t *uid, gid_t *gid,
            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