summaryrefslogtreecommitdiffstats
path: root/cpukit/libcsupport/src/getpwent.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libcsupport/src/getpwent.c')
-rw-r--r--cpukit/libcsupport/src/getpwent.c439
1 files changed, 326 insertions, 113 deletions
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);
}