summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2002-10-02 17:33:17 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2002-10-02 17:33:17 +0000
commited8c513a74ef3f55722a09596bf6a573e778fe92 (patch)
treec92dd89705cb21a328da1480dfe4a0d071bb0e7b /cpukit/libcsupport
parent2002-09-16 Joel Sherrill <joel@OARcorp.com> (diff)
downloadrtems-ed8c513a74ef3f55722a09596bf6a573e778fe92.tar.bz2
2002-10-02 Eric Norum <eric.norum@usask.ca>
* src/getpwent.c: Per PR283, reimplement to address reentrancy problems. * src/getgrent.c: Removed as functionality is now just a wrapper for common routines in src/getpwent.c. * Makefile.am: Reflect file removal.
Diffstat (limited to 'cpukit/libcsupport')
-rw-r--r--cpukit/libcsupport/ChangeLog7
-rw-r--r--cpukit/libcsupport/Makefile.am2
-rw-r--r--cpukit/libcsupport/src/getgrent.c193
-rw-r--r--cpukit/libcsupport/src/getpwent.c439
4 files changed, 334 insertions, 307 deletions
diff --git a/cpukit/libcsupport/ChangeLog b/cpukit/libcsupport/ChangeLog
index 1de58634a4..baa0e21330 100644
--- a/cpukit/libcsupport/ChangeLog
+++ b/cpukit/libcsupport/ChangeLog
@@ -1,3 +1,10 @@
+2002-10-02 Eric Norum <eric.norum@usask.ca>
+
+ * src/getpwent.c: Per PR283, reimplement to address reentrancy problems.
+ * src/getgrent.c: Removed as functionality is now just a wrapper for
+ common routines in src/getpwent.c.
+ * Makefile.am: Reflect file removal.
+
2002-09-14 Joel Sherrill <joel@OARcorp.com>
* include/rtems/libio.h: Change rtems_filesystem_read_t and
diff --git a/cpukit/libcsupport/Makefile.am b/cpukit/libcsupport/Makefile.am
index b758db0d61..1a6e154179 100644
--- a/cpukit/libcsupport/Makefile.am
+++ b/cpukit/libcsupport/Makefile.am
@@ -117,7 +117,7 @@ DIRECTORY_SCAN_C_FILES = src/opendir.c src/closedir.c src/readdir.c \
MALLOC_C_FILES = src/malloc.c src/mallocfreespace.c src/__brk.c src/__sbrk.c
-PASSWORD_GROUP_C_FILES = src/getpwent.c src/getgrent.c
+PASSWORD_GROUP_C_FILES = src/getpwent.c
TERMINAL_IDENTIFICATION_C_FILES = src/ctermid.c src/isatty.c src/ttyname.c \
src/ttyname_r.c
diff --git a/cpukit/libcsupport/src/getgrent.c b/cpukit/libcsupport/src/getgrent.c
deleted file mode 100644
index 104b0a317f..0000000000
--- a/cpukit/libcsupport/src/getgrent.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * POSIX 1003.1b - 9.2.1 - Group Database Access Routines
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.OARcorp.com/rtems/license.html.
- *
- * $Id$
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <grp.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include <rtems/libio_.h>
-
-
-static struct group gr_group; /* password structure */
-static FILE *group_fp;
-
-/*
- * The size of these buffers is arbitrary and there is no provision
- * to protect any of them from overflowing. The scanf patterns
- * need to be changed to prevent overflowing. In addition,
- * the limits on these needs to be examined.
- */
-
-static char groupname[8];
-static char password[1024];
-static char groups[1024];
-static char *gr_mem[16] = { } ;
-
-extern void init_etc_passwd_group(void);
-
-int getgrnam_r(
- const char *name,
- struct group *grp,
- char *buffer,
- size_t bufsize,
- struct group **result
-)
-{
- FILE *fp;
- rtems_user_env_t * aux=rtems_current_user_env; /* save */
-
- init_etc_passwd_group();
- rtems_current_user_env=&rtems_global_user_env; /* set root */
-
- if ((fp = fopen ("/etc/group", "r")) == NULL) {
- errno = EINVAL;
- rtems_current_user_env=aux; /* restore */
- return -1;
- }
-
- while (fgets (buffer, bufsize, fp)) {
- sscanf (buffer, "%[^:]:%[^:]:%d:%s\n",
- groupname, password, (int *) &grp->gr_gid,
- groups);
- grp->gr_name = groupname;
- grp->gr_passwd = password;
- grp->gr_mem = gr_mem ;
-
- if (!strcmp (groupname, name)) {
- fclose (fp);
- *result = grp;
- rtems_current_user_env=aux; /* restore */
- return 0;
- }
- }
- fclose (fp);
- errno = EINVAL;
- rtems_current_user_env=aux; /* restore */
- return -1;
-}
-
-struct group *getgrnam(
- const char *name
-)
-{
- char buf[1024];
- struct group *g;
-
- if ( getgrnam_r( name, &gr_group, buf, 1024, &g ) )
- return NULL;
-
- return g;
-}
-
-int getgrgid_r(
- gid_t gid,
- struct group *grp,
- char *buffer,
- size_t bufsize,
- struct group **result
-)
-{
- FILE *fp;
- rtems_user_env_t * aux=rtems_current_user_env; /* save */
-
-
- init_etc_passwd_group();
- rtems_current_user_env=&rtems_global_user_env; /* set root */
-
- if ((fp = fopen ("/etc/group", "r")) == NULL) {
- errno = EINVAL;
- rtems_current_user_env=aux; /* restore */
- return -1;
- }
-
- while (fgets (buffer, bufsize, fp)) {
- sscanf (buffer, "%[^:]:%[^:]:%d:%s\n",
- groupname, password, (int *) &gr_group.gr_gid,
- groups);
- gr_group.gr_name = groupname;
- gr_group.gr_passwd = password;
- gr_group.gr_mem = gr_mem ;
-
-
- if (gid == gr_group.gr_gid) {
- fclose (fp);
- *result = grp;
- rtems_current_user_env=aux; /* restore */
- return 0;
- }
- }
- fclose (fp);
- errno = EINVAL;
- rtems_current_user_env=aux; /* restore */
- return -1;
-}
-
-struct group *getgrgid (
- gid_t gid
-)
-{
- char buf[1024];
- struct group *g;
-
- if ( getgrgid_r( gid, &gr_group, buf, 1024, &g ) )
- return NULL;
-
- return g;
-}
-
-struct group *getgrent( void )
-{
- char buf[1024];
-
- if (group_fp == NULL)
- return NULL;
-
- if (fgets (buf, sizeof (buf), group_fp) == NULL)
- return NULL;
-
- sscanf (buf, "%[^:]:%[^:]:%d:%s\n",
- groupname, password, (int *) &gr_group.gr_gid,
- groups);
- gr_group.gr_name = groupname;
- gr_group.gr_passwd = password;
- gr_group.gr_mem = gr_mem ;
-
- return &gr_group;
-}
-
-void
-setgrent ()
-{
- rtems_user_env_t * aux=rtems_current_user_env; /* save */
- init_etc_passwd_group();
- rtems_current_user_env=&rtems_global_user_env; /* set root */
-
- if (group_fp != NULL)
- fclose (group_fp);
-
- group_fp = fopen ("/etc/group", "r");
- rtems_current_user_env=aux; /* restore */
-}
-
-void
-endgrent ()
-{
- if (group_fp != NULL)
- fclose (group_fp);
-}
diff --git a/cpukit/libcsupport/src/getpwent.c b/cpukit/libcsupport/src/getpwent.c
index 91b6550f59..00ae4a47f6 100644
--- a/cpukit/libcsupport/src/getpwent.c
+++ b/cpukit/libcsupport/src/getpwent.c
@@ -15,81 +15,168 @@
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
+#include <grp.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
-#include <fcntl.h>
-#include <unistd.h>
+#include <ctype.h>
#include <rtems/libio_.h>
-static struct passwd pw_passwd; /* password structure */
-static FILE *passwd_fp;
-
/*
- * The size of these buffers is arbitrary and there is no provision
- * to protect any of them from overflowing. The scanf patterns
- * need to be changed to prevent overflowing. In addition,
- * the limits on these needs to be examined.
+ * Static, thread-unsafe, buffers
*/
-
-static char logname[8];
-static char password[1024];
-static char comment[1024];
-static char gecos[1024];
-static char dir[1024];
-static char shell[1024];
+static FILE *passwd_fp;
+static char pwbuf[200];
+static struct passwd pwent;
+static FILE *group_fp;
+static char grbuf[200];
+static struct group grent;
/*
- * Initialize a useable but dummy /etc/passwd
- *
- * NOTE: Ignore all errors.
- *
+ * Initialize useable but dummy databases
*/
-
-static char etc_passwd_initted = 0;
-
void init_etc_passwd_group(void)
{
FILE *fp;
+ static char etc_passwd_initted = 0;
- if ( etc_passwd_initted )
+ if (etc_passwd_initted)
return;
etc_passwd_initted = 1;
-
- (void) mkdir( "/etc", 0777);
+ mkdir("/etc", 0777);
/*
* Initialize /etc/passwd
*/
-
- if ((fp = fopen ("/etc/passwd", "w")) == NULL)
- return;
-
- fprintf( fp, "root:*:0:0:root,,,,:/:/bin/sh\n"
- "rtems:*:1:1:RTEMS Application,,,,:/:/bin/sh\n"
- "tty:!:2:2:tty owner,,,,:/:/bin/false\n" );
-
- fclose( fp );
+ if ((fp = fopen("/etc/passwd", "r")) != NULL) {
+ fclose(fp);
+ }
+ else if ((fp = fopen("/etc/passwd", "w")) != NULL) {
+ fprintf(fp, "root:*:0:0:root::/:/bin/sh\n"
+ "rtems:*:1:1:RTEMS Application::/:/bin/sh\n"
+ "tty:!:2:2:tty owner::/:/bin/false\n" );
+ fclose(fp);
+ }
/*
* Initialize /etc/group
*/
+ if ((fp = fopen("/etc/group", "r")) != NULL) {
+ fclose(fp);
+ }
+ else if ((fp = fopen("/etc/group", "w")) != NULL) {
+ fprintf( fp, "root:x:0:root\n"
+ "rtems:x:1:rtems\n"
+ "tty:x:2:tty\n" );
+ fclose(fp);
+ }
+}
- if ((fp = fopen ("/etc/group", "w")) == NULL)
- return;
+/*
+ * Extract a string value from the database
+ */
+static int
+scanString(FILE *fp, char **name, char **bufp, size_t *nleft, int nlFlag)
+{
+ int c;
+
+ *name = *bufp;
+ for (;;) {
+ c = getc(fp);
+ if (c == ':') {
+ if (nlFlag)
+ return 0;
+ break;
+ }
+ if (c == '\n') {
+ if (!nlFlag)
+ return 0;
+ break;
+ }
+ if (c == EOF)
+ return 0;
+ if (*nleft < 2)
+ return 0;
+ **bufp = c;
+ ++(*bufp);
+ --(*nleft);
+ }
+ **bufp = '\0';
+ ++(*bufp);
+ --(*nleft);
+ return 1;
+}
- fprintf( fp, "root:x:0:root\n"
- "rtems:x:1:rtems\n"
- "tty:x:2:tty\n" );
+/*
+ * Extract an integer value from the database
+ */
+static int
+scanInt(FILE *fp, int *val)
+{
+ int c;
+ unsigned int i = 0;
+ unsigned int limit = INT_MAX;
+ int sign = 0;
+ int d;
+
+ for (;;) {
+ c = getc(fp);
+ if (c == ':')
+ break;
+ if (sign == 0) {
+ if (c == '-') {
+ sign = -1;
+ limit++;
+ continue;
+ }
+ sign = 1;
+ }
+ if (!isdigit(c))
+ return 0;
+ d = c - '0';
+ if ((i > (limit / 10))
+ || ((i == (limit / 10)) && (d > (limit % 10))))
+ return 0;
+ i = i * 10 + d;
+ }
+ if (sign == 0)
+ return 0;
+ *val = i * sign;
+ return 1;
+}
- fclose( fp );
+/*
+ * Extract a single password record from the database
+ */
+static int scanpw(
+ FILE *fp,
+ struct passwd *pwd,
+ char *buffer,
+ size_t bufsize
+)
+{
+ int pwuid, pwgid;
+
+ if (!scanString(fp, &pwd->pw_name, &buffer, &bufsize, 0)
+ || !scanString(fp, &pwd->pw_passwd, &buffer, &bufsize, 0)
+ || !scanInt(fp, &pwuid)
+ || !scanInt(fp, &pwgid)
+ || !scanString(fp, &pwd->pw_comment, &buffer, &bufsize, 0)
+ || !scanString(fp, &pwd->pw_gecos, &buffer, &bufsize, 0)
+ || !scanString(fp, &pwd->pw_dir, &buffer, &bufsize, 0)
+ || !scanString(fp, &pwd->pw_shell, &buffer, &bufsize, 1))
+ return 0;
+ pwd->pw_uid = pwuid;
+ pwd->pw_gid = pwgid;
+ return 1;
}
-int getpwnam_r(
+static int getpw_r(
const char *name,
+ int uid,
struct passwd *pwd,
char *buffer,
size_t bufsize,
@@ -97,52 +184,62 @@ int getpwnam_r(
)
{
FILE *fp;
+ int match;
rtems_user_env_t * aux=rtems_current_user_env; /* save */
init_etc_passwd_group();
rtems_current_user_env=&rtems_global_user_env; /* set root */
- if ((fp = fopen ("/etc/passwd", "r")) == NULL) {
+ if ((fp = fopen("/etc/passwd", "r")) == NULL) {
errno = EINVAL;
rtems_current_user_env=aux; /* restore */
return -1;
}
-
- while (fgets (buffer, bufsize, fp)) {
- sscanf (buffer, "%[^:]:%[^:]:%d:%d:%[^:]:%[^:]:%[^:]:%s\n",
- logname, password, &pwd->pw_uid,
- &pwd->pw_gid, comment, gecos,
- dir, shell);
- pwd->pw_name = logname;
- pwd->pw_passwd = password;
- pwd->pw_comment = comment;
- pwd->pw_gecos = gecos;
- pwd->pw_dir = dir;
- pwd->pw_shell = shell;
-
- if (!strcmp (logname, name)) {
- fclose (fp);
+ for(;;) {
+ if (!scanpw(fp, pwd, buffer, bufsize)) {
+ errno = EINVAL;
+ fclose(fp);
+ rtems_current_user_env=aux; /* restore */
+ return -1;
+ }
+ if (name) {
+ match = (strcmp(pwd->pw_name, name) == 0);
+ }
+ else {
+ match = (pwd->pw_uid == uid);
+ }
+ if (match) {
+ fclose(fp);
*result = pwd;
rtems_current_user_env=aux; /* restore */
return 0;
}
}
- fclose (fp);
+ fclose(fp);
errno = EINVAL;
- rtems_current_user_env=aux; /* restore */
+ rtems_current_user_env=aux; /* restore */
return -1;
}
-struct passwd *getpwnam(
+int getpwnam_r(
+ const char *name,
+ struct passwd *pwd,
+ char *buffer,
+ size_t bufsize,
+ struct passwd **result
+)
+{
+ return getpw_r(name, 0, pwd, buffer, bufsize, result);
+}
+
+struct passwd *getpwnam(
const char *name
)
{
- char buf[1024];
struct passwd *p;
- if ( getpwnam_r( name, &pw_passwd, buf, 1024, &p ) )
+ if(getpwnam_r(name, &pwent, pwbuf, sizeof pwbuf, &p))
return NULL;
-
return p;
}
@@ -154,95 +251,211 @@ int getpwuid_r(
struct passwd **result
)
{
+ return getpw_r(NULL, uid, pwd, buffer, bufsize, result);
+}
+
+struct passwd *getpwuid(
+ uid_t uid
+)
+{
+ struct passwd *p;
+
+ if(getpwuid_r(uid, &pwent, pwbuf, sizeof pwbuf, &p))
+ return NULL;
+ return p;
+}
+
+struct passwd *getpwent()
+{
+ if (passwd_fp == NULL)
+ return NULL;
+ if (!scanpw(passwd_fp, &pwent, pwbuf, sizeof pwbuf))
+ return NULL;
+ return &pwent;
+}
+
+void setpwent(void)
+{
+ rtems_user_env_t * aux=rtems_current_user_env; /* save */
+ init_etc_passwd_group();
+ rtems_current_user_env=&rtems_global_user_env; /* set root */
+
+ if (passwd_fp != NULL)
+ fclose(passwd_fp);
+ passwd_fp = fopen("/etc/passwd", "r");
+ rtems_current_user_env=aux; /* restore */
+}
+
+void endpwent(void)
+{
+ if (passwd_fp != NULL)
+ fclose(passwd_fp);
+}
+
+/*
+ * Extract a single group record from the database
+ */
+static int scangr(
+ FILE *fp,
+ struct group *grp,
+ char *buffer,
+ size_t bufsize
+)
+{
+ int grgid;
+ char *grmem, *cp;
+ int memcount;
+
+ if (!scanString(fp, &grp->gr_name, &buffer, &bufsize, 0)
+ || !scanString(fp, &grp->gr_passwd, &buffer, &bufsize, 0)
+ || !scanInt(fp, &grgid)
+ || !scanString(fp, &grmem, &buffer, &bufsize, 1))
+ return 0;
+ grp->gr_gid = grgid;
+
+ /*
+ * Determine number of members
+ */
+ for (cp = grmem, memcount = 1 ; *cp != 0 ; cp++) {
+ if(*cp == ',')
+ memcount++;
+ }
+
+ /*
+ * Hack to produce (hopefully) a suitably-aligned array of pointers
+ */
+ if (bufsize < (((memcount+1)*sizeof(char *)) + 15))
+ return 0;
+ grp->gr_mem = (char **)(((unsigned long)buffer + 15) & ~15);
+
+ /*
+ * Fill in pointer array
+ */
+ grp->gr_mem[0] = grmem;
+ for (cp = grmem, memcount = 1 ; *cp != 0 ; cp++) {
+ if(*cp == ',') {
+ *cp = '\0';
+ grp->gr_mem[memcount++] = cp + 1;
+ }
+ }
+ grp->gr_mem[memcount] = NULL;
+ return 1;
+}
+
+static int getgr_r(
+ const char *name,
+ int gid,
+ struct group *grp,
+ char *buffer,
+ size_t bufsize,
+ struct group **result
+)
+{
FILE *fp;
+ int match;
rtems_user_env_t * aux=rtems_current_user_env; /* save */
init_etc_passwd_group();
rtems_current_user_env=&rtems_global_user_env; /* set root */
- if ((fp = fopen ("/etc/passwd", "r")) == NULL) {
+ if ((fp = fopen("/etc/group", "r")) == NULL) {
errno = EINVAL;
rtems_current_user_env=aux; /* restore */
return -1;
}
-
- while (fgets (buffer, bufsize, fp)) {
- sscanf (buffer, "%[^:]:%[^:]:%d:%d:%[^:]:%[^:]:%[^:]:%s\n",
- logname, password, &pw_passwd.pw_uid,
- &pw_passwd.pw_gid, comment, gecos,
- dir, shell);
- pwd->pw_name = logname;
- pwd->pw_passwd = password;
- pwd->pw_comment = comment;
- pwd->pw_gecos = gecos;
- pwd->pw_dir = dir;
- pwd->pw_shell = shell;
-
- if (uid == pwd->pw_uid) {
- fclose (fp);
- *result = pwd;
+ for(;;) {
+ if (!scangr(fp, grp, buffer, bufsize)) {
+ errno = EINVAL;
+ fclose(fp);
+ rtems_current_user_env=aux; /* restore */
+ return -1;
+ }
+ if (name) {
+ match = (strcmp(grp->gr_name, name) == 0);
+ }
+ else {
+ match = (grp->gr_gid == gid);
+ }
+ if (match) {
+ fclose(fp);
+ *result = grp;
rtems_current_user_env=aux; /* restore */
return 0;
}
}
- fclose (fp);
+ fclose(fp);
errno = EINVAL;
rtems_current_user_env=aux; /* restore */
return -1;
}
-struct passwd *getpwuid(
- uid_t uid
+int getgrnam_r(
+ const char *name,
+ struct group *grp,
+ char *buffer,
+ size_t bufsize,
+ struct group **result
)
{
- char buf[1024];
- struct passwd *p;
+ return getgr_r(name, 0, grp, buffer, bufsize, result);
+}
- if ( getpwuid_r( uid, &pw_passwd, buf, 1024, &p ) )
- return NULL;
+struct group *getgrnam(
+ const char *name
+)
+{
+ struct group *p;
+ if(getgrnam_r(name, &grent, grbuf, sizeof grbuf, &p))
+ return NULL;
return p;
}
-struct passwd *getpwent()
+int getgrgid_r(
+ gid_t gid,
+ struct group *grp,
+ char *buffer,
+ size_t bufsize,
+ struct group **result
+)
{
- char buf[1024];
+ return getgr_r(NULL, gid, grp, buffer, bufsize, result);
+}
- if (passwd_fp == NULL)
- return NULL;
+struct group *getgrgid(
+ gid_t gid
+)
+{
+ struct group *p;
- if (fgets (buf, sizeof (buf), passwd_fp) == NULL)
+ if(getgrgid_r(gid, &grent, grbuf, sizeof grbuf, &p))
return NULL;
+ return p;
+}
- sscanf (buf, "%[^:]:%[^:]:%d:%d:%[^:]:%[^:]:%[^:]:%s\n",
- logname, password, &pw_passwd.pw_uid,
- &pw_passwd.pw_gid, comment, gecos,
- dir, shell);
- pw_passwd.pw_name = logname;
- pw_passwd.pw_passwd = password;
- pw_passwd.pw_comment = comment;
- pw_passwd.pw_gecos = gecos;
- pw_passwd.pw_dir = dir;
- pw_passwd.pw_shell = shell;
-
- return &pw_passwd;
+struct group *getgrent()
+{
+ if (group_fp == NULL)
+ return NULL;
+ if (!scangr(group_fp, &grent, grbuf, sizeof grbuf))
+ return NULL;
+ return &grent;
}
-void setpwent( void )
+void setgrent(void)
{
rtems_user_env_t * aux=rtems_current_user_env; /* save */
init_etc_passwd_group();
rtems_current_user_env=&rtems_global_user_env; /* set root */
- if (passwd_fp != NULL)
- fclose (passwd_fp);
-
- passwd_fp = fopen ("/etc/passwd", "r");
+ if (group_fp != NULL)
+ fclose(group_fp);
+ group_fp = fopen("/etc/group", "r");
rtems_current_user_env=aux; /* restore */
}
-void endpwent( void )
+void endgrent(void)
{
- if (passwd_fp != NULL)
- fclose (passwd_fp);
+ if (group_fp != NULL)
+ fclose(group_fp);
}