hush: fix \<newline> handling on NOMMU
[oweals/busybox.git] / libpwdgrp / pwd_grp.c
index b535ef5c43d01d7e974036b819c46d467c54177d..e2077ade0be1ba45c0564705108f12fe7b450501 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 #include "libbb.h"
-#include <features.h>
+//#include <features.h>
 #include <assert.h>
 
 #ifndef _PATH_SHADOW
@@ -396,6 +396,7 @@ struct spwd *getspnam(const char *name)
 }
 #endif
 
+#ifdef THIS_ONE_IS_UNUSED
 /* This one doesn't use static buffers */
 int getpw(uid_t uid, char *buf)
 {
@@ -419,6 +420,7 @@ int getpw(uid_t uid, char *buf)
 
        return -1;
 }
+#endif
 
 /**********************************************************************/
 
@@ -464,7 +466,7 @@ int getpwent_r(struct passwd *__restrict resultbuf,
        *result = NULL;                         /* In case of error... */
 
        if (!pwf) {
-               pwf = fopen(_PATH_PASSWD, "r");
+               pwf = fopen_for_read(_PATH_PASSWD);
                if (!pwf) {
                        rv = errno;
                        goto ERR;
@@ -511,7 +513,7 @@ int getgrent_r(struct group *__restrict resultbuf,
        *result = NULL;                         /* In case of error... */
 
        if (!grf) {
-               grf = fopen(_PATH_GROUP, "r");
+               grf = fopen_for_read(_PATH_GROUP);
                if (!grf) {
                        rv = errno;
                        goto ERR;
@@ -558,7 +560,7 @@ int getspent_r(struct spwd *resultbuf, char *buffer,
        *result = NULL;                         /* In case of error... */
 
        if (!spf) {
-               spf = fopen(_PATH_SHADOW, "r");
+               spf = fopen_for_read(_PATH_SHADOW);
                if (!spf) {
                        rv = errno;
                        goto ERR;
@@ -620,56 +622,63 @@ struct spwd *sgetspent(const char *string)
 }
 #endif
 
-int initgroups(const char *user, gid_t gid)
+static gid_t *getgrouplist_internal(int *ngroups_ptr, const char *user, gid_t gid)
 {
        FILE *grfile;
        gid_t *group_list;
-       int num_groups, rv;
-       char **m;
+       int ngroups;
        struct group group;
        char buff[PWD_BUFFER_SIZE];
 
-       rv = -1;
-
        /* We alloc space for 8 gids at a time. */
-       group_list = (gid_t *) malloc(8*sizeof(gid_t *));
-       if (group_list
-        && ((grfile = fopen(_PATH_GROUP, "r")) != NULL)
-       ) {
-               *group_list = gid;
-               num_groups = 1;
+       group_list = xmalloc(8 * sizeof(group_list[0]));
+       group_list[0] = gid;
+       ngroups = 1;
 
+       grfile = fopen_for_read(_PATH_GROUP);
+       if (grfile) {
                while (!bb__pgsreader(bb__parsegrent, &group, buff, sizeof(buff), grfile)) {
+                       char **m;
                        assert(group.gr_mem); /* Must have at least a NULL terminator. */
-                       if (group.gr_gid != gid) {
-                               for (m = group.gr_mem; *m; m++) {
-                                       if (!strcmp(*m, user)) {
-                                               if (!(num_groups & 7)) {
-                                                       gid_t *tmp = (gid_t *)
-                                                               realloc(group_list,
-                                                                               (num_groups+8) * sizeof(gid_t *));
-                                                       if (!tmp) {
-                                                               rv = -1;
-                                                               goto DO_CLOSE;
-                                                       }
-                                                       group_list = tmp;
-                                               }
-                                               group_list[num_groups++] = group.gr_gid;
-                                               break;
-                                       }
-                               }
+                       if (group.gr_gid == gid)
+                               continue;
+                       for (m = group.gr_mem; *m; m++) {
+                               if (strcmp(*m, user) != 0)
+                                       continue;
+                               group_list = xrealloc_vector(group_list, 3, ngroups);
+                               group_list[ngroups++] = group.gr_gid;
+                               break;
                        }
                }
-
-               rv = setgroups(num_groups, group_list);
-       DO_CLOSE:
                fclose(grfile);
        }
+       *ngroups_ptr = ngroups;
+       return group_list;
+}
 
-       /* group_list will be NULL if initial malloc failed, which may trigger
-        * warnings from various malloc debuggers. */
+int initgroups(const char *user, gid_t gid)
+{
+       int ngroups;
+       gid_t *group_list = getgrouplist_internal(&ngroups, user, gid);
+
+       ngroups = setgroups(ngroups, group_list);
        free(group_list);
-       return rv;
+       return ngroups;
+}
+
+int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
+{
+       int ngroups_old = *ngroups;
+       gid_t *group_list = getgrouplist_internal(ngroups, user, gid);
+
+       if (*ngroups <= ngroups_old) {
+               ngroups_old = *ngroups;
+               memcpy(groups, group_list, ngroups_old * sizeof(groups[0]));
+       } else {
+               ngroups_old = -1;
+       }
+       free(group_list);
+       return ngroups_old;
 }
 
 int putpwent(const struct passwd *__restrict p, FILE *__restrict f)
@@ -677,7 +686,7 @@ int putpwent(const struct passwd *__restrict p, FILE *__restrict f)
        int rv = -1;
 
        if (!p || !f) {
-               errno=EINVAL;
+               errno = EINVAL;
        } else {
                /* No extra thread locking is needed above what fprintf does. */
                if (fprintf(f, "%s:%s:%lu:%lu:%s:%s:%s\n",
@@ -695,13 +704,14 @@ int putpwent(const struct passwd *__restrict p, FILE *__restrict f)
 
 int putgrent(const struct group *__restrict p, FILE *__restrict f)
 {
-       static const char format[] = ",%s";
+       static const char format[] ALIGN1 = ",%s";
+
        char **m;
        const char *fmt;
        int rv = -1;
 
        if (!p || !f) {                         /* Sigh... glibc checks. */
-               errno=EINVAL;
+               errno = EINVAL;
        } else {
                if (fprintf(f, "%s:%s:%lu:",
                                        p->gr_name, p->gr_passwd,
@@ -735,18 +745,19 @@ int putgrent(const struct group *__restrict p, FILE *__restrict f)
 }
 
 #if ENABLE_USE_BB_SHADOW
-static const unsigned char _sp_off[] = {
-       offsetof(struct spwd, sp_lstchg),       /* 2 - not a char ptr */
-       offsetof(struct spwd, sp_min),          /* 3 - not a char ptr */
-       offsetof(struct spwd, sp_max),          /* 4 - not a char ptr */
-       offsetof(struct spwd, sp_warn),         /* 5 - not a char ptr */
-       offsetof(struct spwd, sp_inact),        /* 6 - not a char ptr */
-       offsetof(struct spwd, sp_expire),       /* 7 - not a char ptr */
+static const unsigned char _sp_off[] ALIGN1 = {
+       offsetof(struct spwd, sp_lstchg),       /* 2 - not a char ptr */
+       offsetof(struct spwd, sp_min),          /* 3 - not a char ptr */
+       offsetof(struct spwd, sp_max),          /* 4 - not a char ptr */
+       offsetof(struct spwd, sp_warn),         /* 5 - not a char ptr */
+       offsetof(struct spwd, sp_inact),        /* 6 - not a char ptr */
+       offsetof(struct spwd, sp_expire)        /* 7 - not a char ptr */
 };
 
 int putspent(const struct spwd *p, FILE *stream)
 {
-       static const char ld_format[] = "%ld:";
+       static const char ld_format[] ALIGN1 = "%ld:";
+
        const char *f;
        long x;
        int i;
@@ -787,14 +798,14 @@ DO_UNLOCK:
 /* Internal uClibc functions.                                         */
 /**********************************************************************/
 
-static const unsigned char pw_off[] = {
-       offsetof(struct passwd, pw_name),       /* 0 */
-       offsetof(struct passwd, pw_passwd),     /* 1 */
-       offsetof(struct passwd, pw_uid),        /* 2 - not a char ptr */
-       offsetof(struct passwd, pw_gid),        /* 3 - not a char ptr */
-       offsetof(struct passwd, pw_gecos),      /* 4 */
-       offsetof(struct passwd, pw_dir),        /* 5 */
-       offsetof(struct passwd, pw_shell)       /* 6 */
+static const unsigned char pw_off[] ALIGN1 = {
+       offsetof(struct passwd, pw_name),       /* 0 */
+       offsetof(struct passwd, pw_passwd),     /* 1 */
+       offsetof(struct passwd, pw_uid),        /* 2 - not a char ptr */
+       offsetof(struct passwd, pw_gid),        /* 3 - not a char ptr */
+       offsetof(struct passwd, pw_gecos),      /* 4 */
+       offsetof(struct passwd, pw_dir),        /* 5 */
+       offsetof(struct passwd, pw_shell)       /* 6 */
 };
 
 static int bb__parsepwent(void *data, char *line)
@@ -845,10 +856,10 @@ static int bb__parsepwent(void *data, char *line)
 
 /**********************************************************************/
 
-static const unsigned char gr_off[] = {
-       offsetof(struct group, gr_name),        /* 0 */
-       offsetof(struct group, gr_passwd),      /* 1 */
-       offsetof(struct group, gr_gid)          /* 2 - not a char ptr */
+static const unsigned char gr_off[] ALIGN1 = {
+       offsetof(struct group, gr_name),        /* 0 */
+       offsetof(struct group, gr_passwd),      /* 1 */
+       offsetof(struct group, gr_gid)          /* 2 - not a char ptr */
 };
 
 static int bb__parsegrent(void *data, char *line)
@@ -943,16 +954,16 @@ static int bb__parsegrent(void *data, char *line)
 /**********************************************************************/
 
 #if ENABLE_USE_BB_SHADOW
-static const unsigned char sp_off[] = {
-       offsetof(struct spwd, sp_namp),         /* 0 */
-       offsetof(struct spwd, sp_pwdp),         /* 1 */
-       offsetof(struct spwd, sp_lstchg),       /* 2 - not a char ptr */
-       offsetof(struct spwd, sp_min),          /* 3 - not a char ptr */
-       offsetof(struct spwd, sp_max),          /* 4 - not a char ptr */
-       offsetof(struct spwd, sp_warn),         /* 5 - not a char ptr */
-       offsetof(struct spwd, sp_inact),        /* 6 - not a char ptr */
-       offsetof(struct spwd, sp_expire),       /* 7 - not a char ptr */
-       offsetof(struct spwd, sp_flag)          /* 8 - not a char ptr */
+static const unsigned char sp_off[] ALIGN1 = {
+       offsetof(struct spwd, sp_namp),         /* 0 */
+       offsetof(struct spwd, sp_pwdp),         /* 1 */
+       offsetof(struct spwd, sp_lstchg),       /* 2 - not a char ptr */
+       offsetof(struct spwd, sp_min),          /* 3 - not a char ptr */
+       offsetof(struct spwd, sp_max),          /* 4 - not a char ptr */
+       offsetof(struct spwd, sp_warn),         /* 5 - not a char ptr */
+       offsetof(struct spwd, sp_inact),        /* 6 - not a char ptr */
+       offsetof(struct spwd, sp_expire),       /* 7 - not a char ptr */
+       offsetof(struct spwd, sp_flag)          /* 8 - not a char ptr */
 };
 
 static int bb__parsespent(void *data, char * line)