libcsupport: Split passwd/group support

This commit is contained in:
Sebastian Huber
2014-11-14 11:01:48 +01:00
parent d82f9de1c9
commit b471854bc2
5 changed files with 476 additions and 383 deletions

View File

@@ -108,7 +108,9 @@ MALLOC_C_FILES = src/malloc_initialize.c src/calloc.c src/malloc.c \
src/rtems_heap_extend.c \
src/rtems_heap_greedy.c
PASSWORD_GROUP_C_FILES = src/getpwent.c
PASSWORD_GROUP_C_FILES = src/pwdgrp.c
PASSWORD_GROUP_C_FILES += src/getgrent.c
PASSWORD_GROUP_C_FILES += src/getpwent.c
TERMINAL_IDENTIFICATION_C_FILES = src/ctermid.c
## 20 Nov 2008: Now using these from newlib's posix directory

View File

@@ -0,0 +1,78 @@
/**
* @file
*
* @brief User Database Access Routines
* @ingroup libcsupport
*/
/*
* Copyright (c) 1999-2009 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
* Copyright (c) 1999-2013 Joel Sherrill <joel.sherrill@OARcorp.com>
* Copyright (c) 2000-2001 Fernando Ruiz Casas <fernando.ruiz@ctv.es>
* Copyright (c) 2002 Eric Norum <eric.norum@usask.ca>
* Copyright (c) 2003 Till Straumann <strauman@slac.stanford.edu>
* Copyright (c) 2012 Alex Ivanov <alexivanov97@gmail.com>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "pwdgrp.h"
/*
* Static, thread-unsafe, buffers
*/
static FILE *group_fp;
static char grbuf[200];
static struct group grent;
struct group *getgrnam(
const char *name
)
{
struct group *p;
if(getgrnam_r(name, &grent, grbuf, sizeof grbuf, &p))
return NULL;
return p;
}
struct group *getgrgid(
gid_t gid
)
{
struct group *p;
if(getgrgid_r(gid, &grent, grbuf, sizeof grbuf, &p))
return NULL;
return p;
}
struct group *getgrent(void)
{
if (group_fp == NULL)
return NULL;
if (!_libcsupport_scangr(group_fp, &grent, grbuf, sizeof grbuf))
return NULL;
return &grent;
}
void setgrent(void)
{
_libcsupport_pwdgrp_init();
if (group_fp != NULL)
fclose(group_fp);
group_fp = fopen("/etc/group", "r");
}
void endgrent(void)
{
if (group_fp != NULL)
fclose(group_fp);
}

View File

@@ -22,23 +22,7 @@
#include "config.h"
#endif
#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 <ctype.h>
#include <rtems/libio_.h>
#include <rtems/seterr.h>
/**
* POSIX 1003.1b - 9.2.2 - User Database Access Routines
*/
#include "pwdgrp.h"
/*
* Static, thread-unsafe, buffers
@@ -46,202 +30,6 @@
static FILE *passwd_fp;
static char pwbuf[200];
static struct passwd pwent;
static FILE *group_fp;
static char grbuf[200];
static struct group grent;
/*
* Prototype to avoid warning
*/
void init_etc_passwd_group(void);
/**
* Initialize useable but dummy databases
*/
void init_etc_passwd_group(void)
{
FILE *fp;
static char etc_passwd_initted = 0;
if (etc_passwd_initted)
return;
etc_passwd_initted = 1;
mkdir("/etc", 0777);
/*
* Initialize /etc/passwd
*/
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);
}
}
/**
* 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;
}
/**
* 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;
}
/*
* 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;
}
static int getpw_r(
const char *name,
int uid,
struct passwd *pwd,
char *buffer,
size_t bufsize,
struct passwd **result
)
{
FILE *fp;
int match;
init_etc_passwd_group();
if ((fp = fopen("/etc/passwd", "r")) == NULL)
rtems_set_errno_and_return_minus_one( EINVAL );
for(;;) {
if (!scanpw(fp, pwd, buffer, bufsize))
goto error_einval;
if (name) {
match = (strcmp(pwd->pw_name, name) == 0);
} else {
match = (pwd->pw_uid == uid);
}
if (match) {
fclose(fp);
*result = pwd;
return 0;
}
}
error_einval:
fclose(fp);
rtems_set_errno_and_return_minus_one( EINVAL );
}
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
@@ -254,17 +42,6 @@ struct passwd *getpwnam(
return p;
}
int getpwuid_r(
uid_t uid,
struct passwd *pwd,
char *buffer,
size_t bufsize,
struct passwd **result
)
{
return getpw_r(NULL, uid, pwd, buffer, bufsize, result);
}
struct passwd *getpwuid(
uid_t uid
)
@@ -280,14 +57,14 @@ struct passwd *getpwent(void)
{
if (passwd_fp == NULL)
return NULL;
if (!scanpw(passwd_fp, &pwent, pwbuf, sizeof pwbuf))
if (!_libcsupport_scanpw(passwd_fp, &pwent, pwbuf, sizeof pwbuf))
return NULL;
return &pwent;
}
void setpwent(void)
{
init_etc_passwd_group();
_libcsupport_pwdgrp_init();
if (passwd_fp != NULL)
fclose(passwd_fp);
@@ -299,159 +76,3 @@ 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 **)(((uintptr_t)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;
init_etc_passwd_group();
if ((fp = fopen("/etc/group", "r")) == NULL)
rtems_set_errno_and_return_minus_one( EINVAL );
for(;;) {
if (!scangr(fp, grp, buffer, bufsize))
goto error_einval;
if (name) {
match = (strcmp(grp->gr_name, name) == 0);
} else {
match = (grp->gr_gid == gid);
}
if (match) {
fclose(fp);
*result = grp;
return 0;
}
}
error_einval:
fclose(fp);
rtems_set_errno_and_return_minus_one( EINVAL );
}
int getgrnam_r(
const char *name,
struct group *grp,
char *buffer,
size_t bufsize,
struct group **result
)
{
return getgr_r(name, 0, grp, buffer, bufsize, result);
}
struct group *getgrnam(
const char *name
)
{
struct group *p;
if(getgrnam_r(name, &grent, grbuf, sizeof grbuf, &p))
return NULL;
return p;
}
int getgrgid_r(
gid_t gid,
struct group *grp,
char *buffer,
size_t bufsize,
struct group **result
)
{
return getgr_r(NULL, gid, grp, buffer, bufsize, result);
}
struct group *getgrgid(
gid_t gid
)
{
struct group *p;
if(getgrgid_r(gid, &grent, grbuf, sizeof grbuf, &p))
return NULL;
return p;
}
struct group *getgrent(void)
{
if (group_fp == NULL)
return NULL;
if (!scangr(group_fp, &grent, grbuf, sizeof grbuf))
return NULL;
return &grent;
}
void setgrent(void)
{
init_etc_passwd_group();
if (group_fp != NULL)
fclose(group_fp);
group_fp = fopen("/etc/group", "r");
}
void endgrent(void)
{
if (group_fp != NULL)
fclose(group_fp);
}

View File

@@ -0,0 +1,346 @@
/**
* @file
*
* @brief User Database Access Routines
* @ingroup libcsupport
*/
/*
* Copyright (c) 1999-2009 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
* Copyright (c) 1999-2013 Joel Sherrill <joel.sherrill@OARcorp.com>
* Copyright (c) 2000-2001 Fernando Ruiz Casas <fernando.ruiz@ctv.es>
* Copyright (c) 2002 Eric Norum <eric.norum@usask.ca>
* Copyright (c) 2003 Till Straumann <strauman@slac.stanford.edu>
* Copyright (c) 2012 Alex Ivanov <alexivanov97@gmail.com>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include <rtems/seterr.h>
#include "pwdgrp.h"
/**
* Initialize useable but dummy databases
*/
void _libcsupport_pwdgrp_init(void)
{
FILE *fp;
static char etc_passwd_initted = 0;
if (etc_passwd_initted)
return;
etc_passwd_initted = 1;
mkdir("/etc", 0777);
/*
* Initialize /etc/passwd
*/
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);
}
}
/**
* 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;
}
/**
* 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;
}
/*
* Extract a single password record from the database
*/
int _libcsupport_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;
}
static int getpw_r(
const char *name,
int uid,
struct passwd *pwd,
char *buffer,
size_t bufsize,
struct passwd **result
)
{
FILE *fp;
int match;
_libcsupport_pwdgrp_init();
if ((fp = fopen("/etc/passwd", "r")) == NULL)
rtems_set_errno_and_return_minus_one( EINVAL );
for(;;) {
if (!_libcsupport_scanpw(fp, pwd, buffer, bufsize))
goto error_einval;
if (name) {
match = (strcmp(pwd->pw_name, name) == 0);
} else {
match = (pwd->pw_uid == uid);
}
if (match) {
fclose(fp);
*result = pwd;
return 0;
}
}
error_einval:
fclose(fp);
rtems_set_errno_and_return_minus_one( EINVAL );
}
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);
}
int getpwuid_r(
uid_t uid,
struct passwd *pwd,
char *buffer,
size_t bufsize,
struct passwd **result
)
{
return getpw_r(NULL, uid, pwd, buffer, bufsize, result);
}
/**
* Extract a single group record from the database
*/
int _libcsupport_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 **)(((uintptr_t)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;
_libcsupport_pwdgrp_init();
if ((fp = fopen("/etc/group", "r")) == NULL)
rtems_set_errno_and_return_minus_one( EINVAL );
for(;;) {
if (!_libcsupport_scangr(fp, grp, buffer, bufsize))
goto error_einval;
if (name) {
match = (strcmp(grp->gr_name, name) == 0);
} else {
match = (grp->gr_gid == gid);
}
if (match) {
fclose(fp);
*result = grp;
return 0;
}
}
error_einval:
fclose(fp);
rtems_set_errno_and_return_minus_one( EINVAL );
}
int getgrnam_r(
const char *name,
struct group *grp,
char *buffer,
size_t bufsize,
struct group **result
)
{
return getgr_r(name, 0, grp, buffer, bufsize, result);
}
int getgrgid_r(
gid_t gid,
struct group *grp,
char *buffer,
size_t bufsize,
struct group **result
)
{
return getgr_r(NULL, gid, grp, buffer, bufsize, result);
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#ifndef _RTEMS_LIBCSUPPORT_PWDGRP_H
#define _RTEMS_LIBCSUPPORT_PWDGRP_H
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void _libcsupport_pwdgrp_init(void);
int _libcsupport_scanpw(
FILE *fp,
struct passwd *pwd,
char *buffer,
size_t bufsize
);
int _libcsupport_scangr(
FILE *fp,
struct group *grp,
char *buffer,
size_t bufsize
);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _RTEMS_LIBCSUPPORT_PWDGRP_H */