This adds a -native recipe for the shadow utilities.

The custom --root option allows the the following utilities to be
run within a chroot when invoked under pseudo:

* useradd
* groupadd
* usermod
* groupmod
* userdel
* groupdel
* passwd
* gpasswd
* pwconv
* pwunconv
* grpconv
* grpunconv

They can then be used to manipulate user and group account information
in target sysroots.

useradd was also modified to create home directories recursively when
necessary.

Signed-off-by: Scott Garman <scott.a.gar...@intel.com>
---
 .../shadow/files/add_root_cmd_options.patch        | 1293 ++++++++++++++++++++
 .../shadow/shadow-native_4.1.4.3.bb                |   66 +
 2 files changed, 1359 insertions(+), 0 deletions(-)
 create mode 100644 
meta/recipes-extended/shadow/files/add_root_cmd_options.patch
 create mode 100644 meta/recipes-extended/shadow/shadow-native_4.1.4.3.bb

diff --git a/meta/recipes-extended/shadow/files/add_root_cmd_options.patch 
b/meta/recipes-extended/shadow/files/add_root_cmd_options.patch
new file mode 100644
index 0000000..3511ebb
--- /dev/null
+++ b/meta/recipes-extended/shadow/files/add_root_cmd_options.patch
@@ -0,0 +1,1293 @@
+Add a --root command option to the following utilties:
+
+* useradd
+* groupadd
+* usermod
+* groupmod
+* userdel
+* groupdel
+* passwd
+* gpasswd
+* pwconv
+* pwunconv
+* grpconv
+* grpunconv
+
+This option allows the utilities to be chrooted when run under pseudo.
+They can then be used to manipulate user and group account information
+in target sysroots.
+
+Upstream-Status: Inappropriate [Other]
+Workaround is specific to our build system.
+
+Signed-off-by: Scott Garman <scott.a.gar...@intel.com>
+
+diff -urN shadow-4.1.4.3.orig//src/gpasswd.c shadow-4.1.4.3//src/gpasswd.c
+--- shadow-4.1.4.3.orig//src/gpasswd.c 2011-02-13 09:58:16.000000000 -0800
++++ shadow-4.1.4.3//src/gpasswd.c      2011-05-28 17:09:52.346013331 -0700
+@@ -63,6 +63,7 @@
+  * (/etc/gshadow present) */
+ static bool is_shadowgrp;
+ #endif
++static const char *newroot = "";
+ 
+ /* Flags set by options */
+ static bool aflg = false;
+@@ -97,6 +98,7 @@
+ static void usage (void);
+ static RETSIGTYPE catch_signals (int killed);
+ static bool is_valid_user_list (const char *users);
++static void process_root_flag (int argc, char **argv);
+ static void process_flags (int argc, char **argv);
+ static void check_flags (int argc, int opt_index);
+ static void open_files (void);
+@@ -136,6 +138,7 @@
+                  "Options:\n"
+                  "  -a, --add USER                add USER to GROUP\n"
+                  "  -d, --delete USER             remove USER from GROUP\n"
++                 "  -Q  --root CHROOT_DIR         directory to chroot into\n"
+                  "  -r, --remove-password         remove the GROUP's 
password\n"
+                  "  -R, --restrict                restrict access to GROUP to 
its members\n"
+                  "  -M, --members USER,...        set the list of members of 
GROUP\n"
+@@ -226,6 +229,55 @@
+ }
+ 
+ /*
++ * process_root_flag - chroot if given the --root option
++ *
++ * We do this outside of process_flags() because
++ * the is_shadow_pwd boolean needs to be set before
++ * process_flags(), and if we do need to chroot() we
++ * must do so before is_shadow_pwd gets set.
++ */
++static void process_root_flag (int argc, char **argv)
++{
++      /*
++       * Parse the command line options.
++       */
++      int flag;
++      int option_index = 0;
++      static struct option long_options[] = {
++              {"root", required_argument, NULL, 'Q'},
++              {NULL, 0, NULL, '\0'}
++      };
++
++      while ((flag = getopt_long (argc, argv, "a:A:d:gM:Q:rR", long_options, 
&option_index)) != -1) {
++              switch (flag) {
++              case 'Q':
++                      if ('/' != optarg[0]) {
++                              fprintf (stderr,
++                                       _("%s: invalid chroot path '%s'\n"),
++                                       Prog, optarg);
++                              exit (E_BAD_ARG);
++                      }
++                      newroot = optarg;
++
++                      if (access (newroot, F_OK) != 0) {
++                              fprintf(stderr,
++                                      _("%s: chroot directory %s does not 
exist\n"),
++                                      Prog, newroot);
++                              exit (E_BAD_ARG);
++                      }
++                      if ( chroot(newroot) != 0 ) {
++                              fprintf(stderr,
++                                      _("%s: unable to chroot to directory 
%s\n"),
++                                      Prog, newroot);
++                              exit (E_BAD_ARG);
++                      }
++                      break;
++              /* no-op on everything else - they will be hanled by 
process_flags() */
++              }
++      }
++}
++
++/*
+  * process_flags - process the command line options and arguments
+  */
+ static void process_flags (int argc, char **argv)
+@@ -235,6 +287,7 @@
+       static struct option long_options[] = {
+               {"add", required_argument, NULL, 'a'},
+               {"delete", required_argument, NULL, 'd'},
++              {"root", required_argument, NULL, 'Q'},
+               {"remove-password", no_argument, NULL, 'r'},
+               {"restrict", no_argument, NULL, 'R'},
+               {"administrators", required_argument, NULL, 'A'},
+@@ -242,7 +295,7 @@
+               {NULL, 0, NULL, '\0'}
+               };
+ 
+-      while ((flag = getopt_long (argc, argv, "a:A:d:gM:rR", long_options, 
&option_index)) != -1) {
++      while ((flag = getopt_long (argc, argv, "a:A:d:gM:Q:rR", long_options, 
&option_index)) != -1) {
+               switch (flag) {
+               case 'a':       /* add a user */
+                       aflg = true;
+@@ -283,6 +336,9 @@
+                       }
+                       Mflg = true;
+                       break;
++              case 'Q':
++                      /* no-op since we handled this in process_root_flag() 
earlier */
++                      break;
+               case 'r':       /* remove group password */
+                       rflg = true;
+                       break;
+@@ -995,6 +1051,8 @@
+       setbuf (stdout, NULL);
+       setbuf (stderr, NULL);
+ 
++      process_root_flag (argc, argv);
++
+ #ifdef SHADOWGRP
+       is_shadowgrp = sgr_file_present ();
+ #endif
+diff -urN shadow-4.1.4.3.orig//src/groupadd.c shadow-4.1.4.3//src/groupadd.c
+--- shadow-4.1.4.3.orig//src/groupadd.c        2011-02-13 09:58:16.000000000 
-0800
++++ shadow-4.1.4.3//src/groupadd.c     2011-05-28 17:09:52.346013331 -0700
+@@ -76,6 +76,7 @@
+ static gid_t group_id;
+ static /*@null@*/char *group_passwd;
+ static /*@null@*/char *empty_list = NULL;
++static const char *newroot = "";
+ 
+ static bool oflg = false;     /* permit non-unique group ID to be specified 
with -g */
+ static bool gflg = false;     /* ID value for the new group */
+@@ -120,6 +121,7 @@
+       (void) fputs (_("  -o, --non-unique              allow to create groups 
with duplicate\n"
+                       "                                (non-unique) GID\n"), 
stderr);
+       (void) fputs (_("  -p, --password PASSWORD       use this encrypted 
password for the new group\n"), stderr);
++      (void) fputs (_("  -R, --root CHROOT_DIR         directory to chroot 
into\n"), stderr);
+       (void) fputs (_("  -r, --system                  create a system 
account\n"), stderr);
+       (void) fputs ("\n", stderr);
+       exit (E_USAGE);
+@@ -383,12 +385,13 @@
+               {"key", required_argument, NULL, 'K'},
+               {"non-unique", no_argument, NULL, 'o'},
+               {"password", required_argument, NULL, 'p'},
++              {"root", required_argument, NULL, 'R'},
+               {"system", no_argument, NULL, 'r'},
+               {NULL, 0, NULL, '\0'}
+       };
+ 
+       while ((c =
+-              getopt_long (argc, argv, "fg:hK:op:r", long_options,
++              getopt_long (argc, argv, "fg:hK:op:R:r", long_options,
+                            &option_index)) != -1) {
+               switch (c) {
+               case 'f':
+@@ -440,6 +443,28 @@
+                       pflg = true;
+                       group_passwd = optarg;
+                       break;
++              case 'R':
++                      if ('/' != optarg[0]) {
++                              fprintf (stderr,
++                                       _("%s: invalid chroot path '%s'\n"),
++                                       Prog, optarg);
++                              exit (E_BAD_ARG);
++                      }
++                      newroot = optarg;
++
++                      if (access (newroot, F_OK) != 0) {
++                              fprintf(stderr,
++                                      _("%s: chroot directory %s does not 
exist\n"),
++                                      Prog, newroot);
++                              exit (E_BAD_ARG);
++                      }
++                      if ( chroot(newroot) != 0 ) {
++                              fprintf(stderr,
++                                      _("%s: unable to chroot to directory 
%s\n"),
++                                      Prog, newroot);
++                              exit (E_BAD_ARG);
++                      }
++                      break;
+               case 'r':
+                       rflg = true;
+                       break;
+diff -urN shadow-4.1.4.3.orig//src/groupdel.c shadow-4.1.4.3//src/groupdel.c
+--- shadow-4.1.4.3.orig//src/groupdel.c        2011-02-13 09:58:16.000000000 
-0800
++++ shadow-4.1.4.3//src/groupdel.c     2011-05-28 17:09:52.346013331 -0700
+@@ -36,6 +36,7 @@
+ 
+ #include <ctype.h>
+ #include <fcntl.h>
++#include <getopt.h>
+ #include <grp.h>
+ #include <pwd.h>
+ #ifdef ACCT_TOOLS_SETUID
+@@ -59,6 +60,7 @@
+ 
+ static char *group_name;
+ static gid_t group_id = -1;
++static const char *newroot = "";
+ 
+ #ifdef        SHADOWGRP
+ static bool is_shadow_grp;
+@@ -70,12 +72,14 @@
+ /*@-exitarg@*/
+ #define E_SUCCESS     0       /* success */
+ #define E_USAGE               2       /* invalid command syntax */
++#define E_BAD_ARG     3       /* invalid argument to option */
+ #define E_NOTFOUND    6       /* specified group doesn't exist */
+ #define E_GROUP_BUSY  8       /* can't remove user's primary group */
+ #define E_GRP_UPDATE  10      /* can't update group file */
+ 
+ /* local function prototypes */
+ static void usage (void);
++static void process_flags (int argc, char **argv);
+ static void grp_update (void);
+ static void close_files (void);
+ static void open_files (void);
+@@ -86,11 +90,78 @@
+  */
+ static void usage (void)
+ {
+-      fputs (_("Usage: groupdel group\n"), stderr);
++      (void) fprintf (stderr,
++                                      _("Usage: groupdel [options]\n"
++                                        "\n"
++                                        "Options:\n"),
++                                      Prog);
++      (void) fputs (_("  -g, --group GROUP            group name to 
delete\n"), stderr);
++      (void) fputs (_("  -h, --help                   display this help 
message and exit\n"), stderr);
++      (void) fputs (_("  -R, --root CHROOT_DIR        directory to chroot 
into\n"), stderr);
++      (void) fputs ("\n", stderr);
+       exit (E_USAGE);
+ }
+ 
+ /*
++ * process_flags - perform command line argument setting
++ *
++ *    process_flags() interprets the command line arguments and sets
++ *    the values that the user will be created with accordingly. The
++ *    values are checked for sanity.
++ */
++static void process_flags (int argc, char **argv)
++{
++      {
++              /*
++               * Parse the command line options.
++               */
++              int c;
++              static struct option long_options[] = {
++                      {"group", required_argument, NULL, 'g'},
++                      {"help", no_argument, NULL, 'h'},
++                      {"root", required_argument, NULL, 'R'},
++                      {NULL, 0, NULL, '\0'}
++              };
++              while ((c = getopt_long (argc, argv,
++                                                               "g:R:",
++                                                               long_options, 
NULL)) != -1) {
++                      switch (c) {
++                      case 'g':
++                              group_name = optarg;
++                              break;
++                      case 'h':
++                              usage ();
++                              break;
++                      case 'R':
++                              if ('/' != optarg[0]) {
++                                      fprintf (stderr,
++                                                      _("%s: invalid chroot 
path '%s'\n"),
++                                                      Prog, optarg);
++                                      exit (E_BAD_ARG);
++                              }
++                              newroot = optarg;
++
++                              if (access (newroot, F_OK) != 0) {
++                                      fprintf(stderr,
++                                                      _("%s: chroot directory 
%s does not exist\n"),
++                                                      Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              if ( chroot(newroot) != 0 ) {
++                                      fprintf(stderr,
++                                                      _("%s: unable to chroot 
to directory %s\n"),
++                                                      Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              break;
++                      default:
++                              usage ();
++                      }
++              }
++      }
++}
++
++/*
+  * grp_update - update group file entries
+  *
+  *    grp_update() writes the new records to the group files.
+@@ -328,14 +399,14 @@
+       (void) bindtextdomain (PACKAGE, LOCALEDIR);
+       (void) textdomain (PACKAGE);
+ 
+-      if (argc != 2) {
++   if (argc == 1) {
+               usage ();
+       }
+ 
+-      group_name = argv[1];
+-
+       OPENLOG ("groupdel");
+ 
++      process_flags (argc, argv);
++
+ #ifdef ACCT_TOOLS_SETUID
+ #ifdef USE_PAM
+       {
+diff -urN shadow-4.1.4.3.orig//src/groupmod.c shadow-4.1.4.3//src/groupmod.c
+--- shadow-4.1.4.3.orig//src/groupmod.c        2011-02-13 09:58:16.000000000 
-0800
++++ shadow-4.1.4.3//src/groupmod.c     2011-05-28 17:09:52.346013331 -0700
+@@ -79,6 +79,7 @@
+ static char *group_passwd;
+ static gid_t group_id;
+ static gid_t group_newid;
++static char *newroot = "";
+ 
+ struct cleanup_info_mod info_passwd;
+ struct cleanup_info_mod info_group;
+@@ -126,6 +127,7 @@
+       (void) fputs (_("  -o, --non-unique              allow to use a 
duplicate (non-unique) GID\n"), stderr);
+       (void) fputs (_("  -p, --password PASSWORD       change the password to 
this (encrypted)\n"
+                       "                                PASSWORD\n"), stderr);
++      (void) fputs (_("  -R, --root CHROOT_DIR         directory to chroot 
into\n"), stderr);
+       (void) fputs ("\n", stderr);
+       exit (E_USAGE);
+ }
+@@ -346,10 +348,11 @@
+               {"new-name", required_argument, NULL, 'n'},
+               {"non-unique", no_argument, NULL, 'o'},
+               {"password", required_argument, NULL, 'p'},
++              {"root", required_argument, NULL, 'R'},
+               {NULL, 0, NULL, '\0'}
+       };
+       while ((c =
+-              getopt_long (argc, argv, "g:hn:op:",
++              getopt_long (argc, argv, "g:hn:op:R:",
+                            long_options, &option_index)) != -1) {
+               switch (c) {
+               case 'g':
+@@ -373,6 +376,28 @@
+                       group_passwd = optarg;
+                       pflg = true;
+                       break;
++              case 'R':
++                      if ('/' != optarg[0]) {
++                              fprintf (stderr,
++                                       _("%s: invalid chroot path '%s'\n"),
++                                       Prog, optarg);
++                              exit (E_BAD_ARG);
++                      }
++                      newroot = optarg;
++
++                      if (access (newroot, F_OK) != 0) {
++                              fprintf(stderr,
++                                      _("%s: chroot directory %s does not 
exist\n"),
++                                      Prog, newroot);
++                              exit (E_BAD_ARG);
++                      }
++                      if ( chroot(newroot) != 0 ) {
++                              fprintf(stderr,
++                                      _("%s: unable to chroot to directory 
%s\n"),
++                                      Prog, newroot);
++                              exit (E_BAD_ARG);
++                      }
++                      break;
+               default:
+                       usage ();
+               }
+diff -urN shadow-4.1.4.3.orig//src/grpconv.c shadow-4.1.4.3//src/grpconv.c
+--- shadow-4.1.4.3.orig//src/grpconv.c 2011-02-13 09:58:16.000000000 -0800
++++ shadow-4.1.4.3//src/grpconv.c      2011-05-28 17:09:52.346013331 -0700
+@@ -39,6 +39,7 @@
+ 
+ #include <errno.h>
+ #include <fcntl.h>
++#include <getopt.h>
+ #include <grp.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+@@ -50,6 +51,14 @@
+ #ifdef SHADOWGRP
+ #include "groupio.h"
+ #include "sgroupio.h"
++
++/*
++ * exit status values
++ */
++/*@-exitarg@*/
++#define E_USAGE               2       /* invalid command syntax */
++#define E_BAD_ARG     3       /* invalid argument to option */
++
+ /*
+  * Global variables
+  */
+@@ -57,9 +66,12 @@
+ 
+ static bool gr_locked  = false;
+ static bool sgr_locked = false;
++static const char *newroot = "";
+ 
+ /* local function prototypes */
+ static void fail_exit (int status);
++static void usage (void);
++static void process_flags (int argc, char **argv);
+ 
+ static void fail_exit (int status)
+ {
+@@ -82,6 +94,77 @@
+       exit (status);
+ }
+ 
++/*
++ * usage - display usage message and exit
++ */
++static void usage (void)
++{
++      (void) fprintf (stderr,
++                                      _("Usage: grpconv [options]\n"
++                                        "\n"
++                                        "Options:\n"),
++                                      Prog);
++      (void) fputs (_("  -h, --help                    display this help 
message and exit\n"), stderr);
++      (void) fputs (_("  -R, --root CHROOT_DIR         directory to chroot 
into\n"), stderr);
++      (void) fputs ("\n", stderr);
++      exit (E_USAGE);
++}
++
++/*
++ * process_flags - perform command line argument setting
++ *
++ *    process_flags() interprets the command line arguments and sets
++ *    the values that the user will be created with accordingly. The
++ *    values are checked for sanity.
++ */
++static void process_flags (int argc, char **argv)
++{
++      {
++              /*
++               * Parse the command line options.
++               */
++              int c;
++              static struct option long_options[] = {
++                      {"help", no_argument, NULL, 'h'},
++                      {"root", required_argument, NULL, 'R'},
++                      {NULL, 0, NULL, '\0'}
++              };
++              while ((c = getopt_long (argc, argv,
++                                                               "R:",
++                                                               long_options, 
NULL)) != -1) {
++                      switch (c) {
++                      case 'h':
++                              usage ();
++                              break;
++                      case 'R':
++                              if ('/' != optarg[0]) {
++                                      fprintf (stderr,
++                                               _("%s: invalid chroot path 
'%s'\n"),
++                                               Prog, optarg);
++                                      exit (E_BAD_ARG);
++                              }
++                              newroot = optarg;
++
++                              if (access (newroot, F_OK) != 0) {
++                                      fprintf(stderr,
++                                              _("%s: chroot directory %s does 
not exist\n"),
++                                              Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              if ( chroot(newroot) != 0 ) {
++                                      fprintf(stderr,
++                                              _("%s: unable to chroot to 
directory %s\n"),
++                                              Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              break;
++                      default:
++                              usage ();
++                      }
++              }
++      }
++}
++
+ int main (int argc, char **argv)
+ {
+       const struct group *gr;
+@@ -100,6 +183,8 @@
+ 
+       OPENLOG ("grpconv");
+ 
++      process_flags (argc, argv);
++
+       if (gr_lock () == 0) {
+               fprintf (stderr,
+                        _("%s: cannot lock %s; try again later.\n"),
+diff -urN shadow-4.1.4.3.orig//src/grpunconv.c shadow-4.1.4.3//src/grpunconv.c
+--- shadow-4.1.4.3.orig//src/grpunconv.c       2011-02-13 09:58:16.000000000 
-0800
++++ shadow-4.1.4.3//src/grpunconv.c    2011-05-28 17:09:52.346013331 -0700
+@@ -43,6 +43,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <fcntl.h>
++#include <getopt.h>
+ #include <time.h>
+ #include <unistd.h>
+ #include <grp.h>
+@@ -51,6 +52,14 @@
+ #ifdef SHADOWGRP
+ #include "groupio.h"
+ #include "sgroupio.h"
++
++/*
++ * exit status values
++ */
++/*@-exitarg@*/
++#define E_USAGE               2       /* invalid command syntax */
++#define E_BAD_ARG     3       /* invalid argument to option */
++
+ /*
+  * Global variables
+  */
+@@ -58,9 +67,12 @@
+ 
+ static bool gr_locked  = false;
+ static bool sgr_locked = false;
++static const char *newroot = "";
+ 
+ /* local function prototypes */
+ static void fail_exit (int status);
++static void usage (void);
++static void process_flags (int argc, char **argv);
+ 
+ static void fail_exit (int status)
+ {
+@@ -83,6 +95,77 @@
+       exit (status);
+ }
+ 
++/*
++ * usage - display usage message and exit
++ */
++static void usage (void)
++{
++      (void) fprintf (stderr,
++                                      _("Usage: grpunconv [options]\n"
++                                        "\n"
++                                        "Options:\n"),
++                                      Prog);
++      (void) fputs (_("  -h, --help                    display this help 
message and exit\n"), stderr);
++      (void) fputs (_("  -R, --root CHROOT_DIR         directory to chroot 
into\n"), stderr);
++      (void) fputs ("\n", stderr);
++      exit (E_USAGE);
++}
++
++/*
++ * process_flags - perform command line argument setting
++ *
++ * process_flags() interprets the command line arguments and sets
++ * the values that the user will be created with accordingly. The
++ * values are checked for sanity.
++ */
++static void process_flags (int argc, char **argv)
++{
++      {
++              /*
++               * Parse the command line options.
++               */
++              int c;
++              static struct option long_options[] = {
++                      {"help", no_argument, NULL, 'h'},
++                      {"root", required_argument, NULL, 'R'},
++                      {NULL, 0, NULL, '\0'}
++              };
++              while ((c = getopt_long (argc, argv,
++                                                               "R:",
++                                                               long_options, 
NULL)) != -1) {
++                      switch (c) {
++                      case 'h':
++                              usage ();
++                              break;
++                      case 'R':
++                              if ('/' != optarg[0]) {
++                                      fprintf (stderr,
++                                               _("%s: invalid chroot path 
'%s'\n"),
++                                               Prog, optarg);
++                                      exit (E_BAD_ARG);
++                              }
++                              newroot = optarg;
++
++                              if (access (newroot, F_OK) != 0) {
++                                      fprintf(stderr,
++                                              _("%s: chroot directory %s does 
not exist\n"),
++                                              Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              if ( chroot(newroot) != 0 ) {
++                                      fprintf(stderr,
++                                              _("%s: unable to chroot to 
directory %s\n"),
++                                              Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              break;
++                      default:
++                              usage ();
++                      }
++              }
++      }
++}
++
+ int main (int argc, char **argv)
+ {
+       const struct group *gr;
+@@ -100,6 +183,8 @@
+ 
+       OPENLOG ("grpunconv");
+ 
++      process_flags (argc, argv);
++
+       if (sgr_file_present () == 0) {
+               exit (0);       /* no /etc/gshadow, nothing to do */
+       }
+diff -urN shadow-4.1.4.3.orig//src/passwd.c shadow-4.1.4.3//src/passwd.c
+--- shadow-4.1.4.3.orig//src/passwd.c  2011-02-13 09:58:16.000000000 -0800
++++ shadow-4.1.4.3//src/passwd.c       2011-05-28 17:09:52.346013331 -0700
+@@ -75,6 +75,7 @@
+ static char *name;            /* The name of user whose password is being 
changed */
+ static char *myname;          /* The current user's name */
+ static bool amroot;           /* The caller's real UID was 0 */
++static const char *newroot = "";
+ 
+ static bool
+     aflg = false,                     /* -a - show status for all users */
+@@ -174,6 +175,7 @@
+                "  -n, --mindays MIN_DAYS        set minimum number of days 
before password\n"
+                "                                change to MIN_DAYS\n"
+                "  -q, --quiet                   quiet mode\n"
++               "  -R, --root CHROOT_DIR         directory to chroot into\n"
+                "  -r, --repository REPOSITORY   change password in REPOSITORY 
repository\n"
+                "  -S, --status                  report password status on the 
named account\n"
+                "  -u, --unlock                  unlock the password of the 
named account\n"
+@@ -803,6 +805,7 @@
+                       {"lock", no_argument, NULL, 'l'},
+                       {"mindays", required_argument, NULL, 'n'},
+                       {"quiet", no_argument, NULL, 'q'},
++                      {"root", required_argument, NULL, 'R'},
+                       {"repository", required_argument, NULL, 'r'},
+                       {"status", no_argument, NULL, 'S'},
+                       {"unlock", no_argument, NULL, 'u'},
+@@ -811,7 +814,7 @@
+                       {NULL, 0, NULL, '\0'}
+               };
+ 
+-              while ((c = getopt_long (argc, argv, "adei:kln:qr:Suw:x:",
++              while ((c = getopt_long (argc, argv, "adei:kln:qR:r:Suw:x:",
+                                        long_options, &option_index)) != -1) {
+                       switch (c) {
+                       case 'a':
+@@ -858,6 +861,28 @@
+                       case 'q':
+                               qflg = true;    /* ok for users */
+                               break;
++                      case 'R':
++                              if ('/' != optarg[0]) {
++                                      fprintf (stderr,
++                                               _("%s: invalid chroot path 
'%s'\n"),
++                                               Prog, optarg);
++                                      exit (E_BAD_ARG);
++                              }
++                              newroot = optarg;
++
++                              if (access (newroot, F_OK) != 0) {
++                                      fprintf(stderr,
++                                              _("%s: chroot directory %s does 
not exist\n"),
++                                              Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              if ( chroot(newroot) != 0 ) {
++                                      fprintf(stderr,
++                                          _("%s: unable to chroot to 
directory %s\n"),
++                                              Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              break;
+                       case 'r':
+                               /* -r repository (files|nis|nisplus) */
+                               /* only "files" supported for now */
+diff -urN shadow-4.1.4.3.orig//src/pwconv.c shadow-4.1.4.3//src/pwconv.c
+--- shadow-4.1.4.3.orig//src/pwconv.c  2011-02-13 09:58:16.000000000 -0800
++++ shadow-4.1.4.3//src/pwconv.c       2011-05-28 17:09:52.346013331 -0700
+@@ -59,6 +59,7 @@
+ 
+ #include <errno.h>
+ #include <fcntl.h>
++#include <getopt.h>
+ #include <pwd.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+@@ -79,6 +80,7 @@
+ #define E_SUCCESS     0       /* success */
+ #define E_NOPERM      1       /* permission denied */
+ #define E_USAGE               2       /* invalid command syntax */
++#define E_BAD_ARG     3       /* invalid argument to option */
+ #define E_FAILURE     3       /* unexpected failure, nothing done */
+ #define E_MISSING     4       /* unexpected failure, passwd file missing */
+ #define E_PWDBUSY     5       /* passwd file(s) busy */
+@@ -90,9 +92,12 @@
+ 
+ static bool spw_locked = false;
+ static bool pw_locked = false;
++static const char *newroot = "";
+ 
+ /* local function prototypes */
+ static void fail_exit (int status);
++static void usage (void);
++static void process_flags (int argc, char **argv);
+ 
+ static void fail_exit (int status)
+ {
+@@ -115,6 +120,77 @@
+       exit (status);
+ }
+ 
++/*
++ * usage - display usage message and exit
++ */
++static void usage (void)
++{
++      (void) fprintf (stderr,
++                                      _("Usage: pwconv [options]\n"
++                                        "\n"
++                                        "Options:\n"),
++                                      Prog);
++      (void) fputs (_("  -h, --help                    display this help 
message and exit\n"), stderr);
++      (void) fputs (_("  -R, --root CHROOT_DIR         directory to chroot 
into\n"), stderr);
++      (void) fputs ("\n", stderr);
++      exit (E_USAGE);
++}
++
++/*
++ * process_flags - perform command line argument setting
++ *
++ *    process_flags() interprets the command line arguments and sets
++ *    the values that the user will be created with accordingly. The
++ *    values are checked for sanity.
++ */
++static void process_flags (int argc, char **argv)
++{
++      {
++              /*
++               * Parse the command line options.
++               */
++              int c;
++              static struct option long_options[] = {
++                      {"help", no_argument, NULL, 'h'},
++                      {"root", required_argument, NULL, 'R'},
++                      {NULL, 0, NULL, '\0'}
++              };
++              while ((c = getopt_long (argc, argv,
++                                                               "R:",
++                                                               long_options, 
NULL)) != -1) {
++                      switch (c) {
++                      case 'h':
++                              usage ();
++                              break;
++                      case 'R':
++                              if ('/' != optarg[0]) {
++                                      fprintf (stderr,
++                                               _("%s: invalid chroot path 
'%s'\n"),
++                                               Prog, optarg);
++                                      exit (E_BAD_ARG);
++                              }
++                              newroot = optarg;
++
++                              if (access (newroot, F_OK) != 0) {
++                                      fprintf(stderr,
++                                              _("%s: chroot directory %s does 
not exist\n"),
++                                              Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              if ( chroot(newroot) != 0 ) {
++                                      fprintf(stderr,
++                                              _("%s: unable to chroot to 
directory %s\n"),
++                                              Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              break;
++                      default:
++                              usage ();
++                      }
++              }
++      }
++}
++
+ int main (int argc, char **argv)
+ {
+       const struct passwd *pw;
+@@ -122,9 +198,6 @@
+       const struct spwd *sp;
+       struct spwd spent;
+ 
+-      if (1 != argc) {
+-              (void) fputs (_("Usage: pwconv\n"), stderr);
+-      }
+       Prog = Basename (argv[0]);
+ 
+       (void) setlocale (LC_ALL, "");
+@@ -133,6 +206,8 @@
+ 
+       OPENLOG ("pwconv");
+ 
++      process_flags (argc, argv);
++
+       if (pw_lock () == 0) {
+               fprintf (stderr,
+                        _("%s: cannot lock %s; try again later.\n"),
+diff -urN shadow-4.1.4.3.orig//src/pwunconv.c shadow-4.1.4.3//src/pwunconv.c
+--- shadow-4.1.4.3.orig//src/pwunconv.c        2011-02-13 09:58:16.000000000 
-0800
++++ shadow-4.1.4.3//src/pwunconv.c     2011-05-28 17:09:52.356013600 -0700
+@@ -35,6 +35,7 @@
+ #ident "$Id: pwunconv.c 2852 2009-04-30 21:44:35Z nekral-guest $"
+ 
+ #include <fcntl.h>
++#include <getopt.h>
+ #include <pwd.h>
+ #include <stdio.h>
+ #include <sys/types.h>
+@@ -46,15 +47,24 @@
+ #include "shadowio.h"
+ 
+ /*
++ * exit status values
++ */
++/*@-exitarg@*/
++#define E_USAGE               2       /* invalid command syntax */
++#define E_BAD_ARG     3       /* invalid argument to option */
++/*
+  * Global variables
+  */
+ char *Prog;
+ 
+ static bool spw_locked = false;
+ static bool pw_locked = false;
++static const char *newroot = "";
+ 
+ /* local function prototypes */
+ static void fail_exit (int status);
++static void usage (void);
++static void process_flags (int argc, char **argv);
+ 
+ static void fail_exit (int status)
+ {
+@@ -75,6 +85,76 @@
+       exit (status);
+ }
+ 
++/*
++ * usage - display usage message and exit
++ */
++static void usage (void)
++{
++      (void) fprintf (stderr,
++                                      _("Usage: pwunconv [options]\n"
++                                        "\n"
++                                        "Options:\n"),
++                                      Prog);
++      (void) fputs (_("  -h, --help                    display this help 
message and exit\n"), stderr);
++      (void) fputs (_("  -R, --root CHROOT_DIR         directory to chroot 
into\n"), stderr);
++      (void) fputs ("\n", stderr);
++      exit (E_USAGE);
++}
++
++/*
++ * process_flags - perform command line argument setting
++ *
++ * process_flags() interprets the command line arguments and sets
++ * the values that the user will be created with accordingly. The
++ * values are checked for sanity.
++ */
++static void process_flags (int argc, char **argv)
++{
++      {
++              /*
++               * Parse the command line options.
++               */
++              int c;
++              static struct option long_options[] = {
++                      {"help", no_argument, NULL, 'h'},
++                      {"root", required_argument, NULL, 'R'},
++                      {NULL, 0, NULL, '\0'}
++              };
++              while ((c = getopt_long (argc, argv,
++                                                               "R:",
++                                                               long_options, 
NULL)) != -1) {
++                      switch (c) {
++                      case 'h':
++                              usage ();
++                              break;
++                      case 'R':
++                              if ('/' != optarg[0]) {
++                                      fprintf (stderr,
++                                               _("%s: invalid chroot path 
'%s'\n"),
++                                               Prog, optarg);
++                                      exit (E_BAD_ARG);
++                              }
++                              newroot = optarg;
++
++                              if (access (newroot, F_OK) != 0) {
++                                      fprintf(stderr,
++                                              _("%s: chroot directory %s does 
not exist\n"),
++                                              Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              if ( chroot(newroot) != 0 ) {
++                                      fprintf(stderr,
++                                              _("%s: unable to chroot to 
directory %s\n"),
++                                              Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              break;
++                      default:
++                              usage ();
++                      }
++              }
++      }
++}
+ 
+ int main (int argc, char **argv)
+ {
+@@ -93,6 +173,8 @@
+ 
+       OPENLOG ("pwunconv");
+ 
++      process_flags (argc, argv);
++
+       if (!spw_file_present ()) {
+               /* shadow not installed, do nothing */
+               exit (0);
+diff -urN shadow-4.1.4.3.orig//src/useradd.c shadow-4.1.4.3//src/useradd.c
+--- shadow-4.1.4.3.orig//src/useradd.c 2011-02-13 09:58:16.000000000 -0800
++++ shadow-4.1.4.3//src/useradd.c      2011-05-28 17:10:25.446909971 -0700
+@@ -112,6 +112,7 @@
+ #ifdef WITH_SELINUX
+ static const char *user_selinux = "";
+ #endif
++static const char *newroot = "";
+ 
+ static long user_expire = -1;
+ static bool is_shadow_pwd;
+@@ -189,6 +190,7 @@
+ static void new_spent (struct spwd *);
+ static void grp_update (void);
+ 
++static void process_root_flag (int argc, char **argv);
+ static void process_flags (int argc, char **argv);
+ static void close_files (void);
+ static void open_files (void);
+@@ -711,6 +713,7 @@
+       (void) fputs (_("  -o, --non-unique              allow to create users 
with duplicate\n"
+                       "                                (non-unique) UID\n"), 
stderr);
+       (void) fputs (_("  -p, --password PASSWORD       encrypted password of 
the new account\n"), stderr);
++      (void) fputs (_("  -R, --root CHROOT_DIR         directory to chroot 
into\n"), stderr);
+       (void) fputs (_("  -r, --system                  create a system 
account\n"), stderr);
+       (void) fputs (_("  -s, --shell SHELL             login shell of the new 
account\n"), stderr);
+       (void) fputs (_("  -u, --uid UID                 user ID of the new 
account\n"), stderr);
+@@ -943,6 +946,59 @@
+ }
+ 
+ /*
++ * process_root_flag - chroot if given the --root option
++ *
++ * We do this outside of process_flags() because
++ * the is_shadow_pwd boolean needs to be set before
++ * process_flags(), and if we do need to chroot() we
++ * must do so before is_shadow_pwd gets set.
++ */
++static void process_root_flag (int argc, char **argv)
++{
++      /*
++       * Parse the command line options.
++       */
++      int c;
++      static struct option long_options[] = {
++              {"root", required_argument, NULL, 'R'},
++              {NULL, 0, NULL, '\0'}
++      };
++      while ((c = getopt_long (argc, argv,
++#ifdef WITH_SELINUX
++                               "b:c:d:De:f:g:G:k:K:lmMNop:R:rs:u:UZ:",
++#else
++                               "b:c:d:De:f:g:G:k:K:lmMNop:R:rs:u:U",
++#endif
++                               long_options, NULL)) != -1) {
++              switch (c) {
++              case 'R':
++                      if ('/' != optarg[0]) {
++                              fprintf (stderr,
++                                       _("%s: invalid chroot path '%s'\n"),
++                                       Prog, optarg);
++                              exit (E_BAD_ARG);
++                      }
++                      newroot = optarg;
++
++                      if (access (newroot, F_OK) != 0) {
++                              fprintf(stderr,
++                                      _("%s: chroot directory %s does not 
exist\n"),
++                                      Prog, newroot);
++                              exit (E_BAD_ARG);
++                      }
++                      if ( chroot(newroot) != 0 ) {
++                              fprintf(stderr,
++                                      _("%s: unable to chroot to directory 
%s\n"),
++                                      Prog, newroot);
++                              exit (E_BAD_ARG);
++                      }
++                      break;
++              /* no-op on everything else - they will be hanled by 
process_flags() */
++              }
++      }
++}
++
++/*
+  * process_flags - perform command line argument setting
+  *
+  *    process_flags() interprets the command line arguments and sets
+@@ -978,6 +1034,7 @@
+                       {"no-user-group", no_argument, NULL, 'N'},
+                       {"non-unique", no_argument, NULL, 'o'},
+                       {"password", required_argument, NULL, 'p'},
++                      {"root", required_argument, NULL, 'R'},
+                       {"system", no_argument, NULL, 'r'},
+                       {"shell", required_argument, NULL, 's'},
+ #ifdef WITH_SELINUX
+@@ -989,9 +1046,9 @@
+               };
+               while ((c = getopt_long (argc, argv,
+ #ifdef WITH_SELINUX
+-                                       "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:UZ:",
++                                       "b:c:d:De:f:g:G:k:K:lmMNop:R:rs:u:UZ:",
+ #else
+-                                       "b:c:d:De:f:g:G:k:K:lmMNop:rs:u:U",
++                                       "b:c:d:De:f:g:G:k:K:lmMNop:R:rs:u:U",
+ #endif
+                                        long_options, NULL)) != -1) {
+                       switch (c) {
+@@ -1156,6 +1213,9 @@
+                               }
+                               user_pass = optarg;
+                               break;
++                      case 'R':
++                              /* no-op since we handled this in 
process_root_flag() earlier */
++                              break;
+                       case 'r':
+                               rflg = true;
+                               break;
+@@ -1748,8 +1808,16 @@
+ #ifdef WITH_SELINUX
+               selinux_file_context (user_home);
+ #endif
+-              /* XXX - create missing parent directories.  --marekm */
+-              if (mkdir (user_home, 0) != 0) {
++              /* shell out to invoke mkdir -p 
++               * creating a subshell under pseudo's chroot() breaks the jail
++               * (bug in pseudo), so make sure we include the full host path
++               * to the sysroot when the --root option is in use.
++               */
++              int sysroot_path_len = strlen(newroot);
++              int home_path_len = strlen(user_home);
++              char cmd[sysroot_path_len + home_path_len + 10];
++              sprintf(cmd, "mkdir -p %s%s", newroot, user_home);
++              if (system (cmd) != 0) {
+                       fprintf (stderr,
+                                _("%s: cannot create directory %s\n"),
+                                Prog, user_home);
+@@ -1861,6 +1929,7 @@
+        */
+       user_groups[0] = (char *) 0;
+ 
++      process_root_flag (argc, argv);
+ 
+       is_shadow_pwd = spw_file_present ();
+ #ifdef SHADOWGRP
+diff -urN shadow-4.1.4.3.orig//src/userdel.c shadow-4.1.4.3//src/userdel.c
+--- shadow-4.1.4.3.orig//src/userdel.c 2011-02-13 09:58:16.000000000 -0800
++++ shadow-4.1.4.3//src/userdel.c      2011-05-28 17:09:52.356013600 -0700
+@@ -79,6 +79,7 @@
+ static char *user_name;
+ static uid_t user_id;
+ static char *user_home;
++static const char *newroot = "";
+ 
+ static bool fflg = false;
+ static bool rflg = false;
+@@ -119,6 +120,7 @@
+                "  -f, --force                   force removal of files,\n"
+                "                                even if not owned by user\n"
+                "  -h, --help                    display this help message and 
exit\n"
++               "  -R, --root CHROOT_DIR         directory to chroot into\n"
+                "  -r, --remove                  remove home directory and 
mail spool\n"
+                "\n"), stderr);
+       exit (E_USAGE);
+@@ -768,12 +770,34 @@
+                       {"remove", no_argument, NULL, 'r'},
+                       {NULL, 0, NULL, '\0'}
+               };
+-              while ((c = getopt_long (argc, argv, "fhr",
++              while ((c = getopt_long (argc, argv, "fhR:r",
+                                        long_options, NULL)) != -1) {
+                       switch (c) {
+                       case 'f':       /* force remove even if not owned by 
user */
+                               fflg = true;
+                               break;
++                      case 'R':
++                              if ('/' != optarg[0]) {
++                                      fprintf (stderr,
++                                               _("%s: invalid chroot path 
'%s'\n"),
++                                               Prog, optarg);
++                                      exit (E_BAD_ARG);
++                              }
++                              newroot = optarg;
++
++                              if (access (newroot, F_OK) != 0) {
++                                      fprintf(stderr,
++                                              _("%s: chroot directory %s does 
not exist\n"),
++                                              Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              if ( chroot(newroot) != 0 ) {
++                                      fprintf(stderr,
++                                              _("%s: unable to chroot to 
directory %s\n"),
++                                              Prog, newroot);
++                                      exit (E_BAD_ARG);
++                              }
++                              break;
+                       case 'r':       /* remove home dir and mailbox */
+                               rflg = true;
+                               break;
+diff -urN shadow-4.1.4.3.orig//src/usermod.c shadow-4.1.4.3//src/usermod.c
+--- shadow-4.1.4.3.orig//src/usermod.c 2011-02-13 09:58:16.000000000 -0800
++++ shadow-4.1.4.3//src/usermod.c      2011-05-28 17:09:52.356013600 -0700
+@@ -110,6 +110,7 @@
+ static long user_newinactive;
+ static long sys_ngroups;
+ static char **user_groups;    /* NULL-terminated list */
++static const char *newroot = "";
+ 
+ static bool
+     aflg = false,             /* append to existing secondary group set */
+@@ -164,6 +165,7 @@
+ #endif
+ static void grp_update (void);
+ 
++static void process_root_flag (int, char **);
+ static void process_flags (int, char **);
+ static void close_files (void);
+ static void open_files (void);
+@@ -323,6 +325,7 @@
+                "                                new location (use only with 
-d)\n"
+                "  -o, --non-unique              allow using duplicate 
(non-unique) UID\n"
+                "  -p, --password PASSWORD       use encrypted password for 
the new password\n"
++               "  -R  --root CHROOT_DIR         directory to chroot into\n"
+                "  -s, --shell SHELL             new login shell for the user 
account\n"
+                "  -u, --uid UID                 new UID for the user 
account\n"
+                "  -U, --unlock                  unlock the user account\n"
+@@ -802,6 +805,60 @@
+ }
+ 
+ /*
++ * process_root_flag - chroot if given the --root option
++ *
++ * We do this outside of process_flags() because
++ * the is_shadow_pwd boolean needs to be set before
++ * process_flags(), and if we do need to chroot() we
++ * must do so before is_shadow_pwd gets set.
++ */
++static void process_root_flag (int argc, char **argv)
++{
++      /*
++       * Parse the command line options.
++       */
++      int c;
++      static struct option long_options[] = {
++              {"root", required_argument, NULL, 'R'},
++              {NULL, 0, NULL, '\0'}
++      };
++      while ((c = getopt_long (argc, argv,
++#ifdef WITH_SELINUX
++                             "ac:d:e:f:g:G:hl:Lmop:R:s:u:UZ:",
++#else
++                               "ac:d:e:f:g:G:hl:Lmop:R:s:u:U",
++#endif
++                               long_options, NULL)) != -1) {
++              switch (c) {
++              case 'R':
++                      if (    (!VALID (optarg) ) 
++                              || (   ('/' != optarg[0]) ) ) {
++                              fprintf (stderr,
++                                       _("%s: invalid chroot path '%s'\n"),
++                                       Prog, optarg);
++                              exit (E_BAD_ARG);
++                      }
++                      newroot = optarg;
++
++                      if (access (newroot, F_OK) != 0) {
++                              fprintf(stderr,
++                                      _("%s: chroot directory %s does not 
exist\n"),
++                                      Prog, newroot);
++                              exit (E_BAD_ARG);
++                      }
++                      if ( chroot(newroot) != 0 ) {
++                              fprintf(stderr,
++                                      _("%s: unable to chroot to directory 
%s\n"),
++                                      Prog, newroot);
++                              exit (E_BAD_ARG);
++                      }
++                      break;
++              /* no-op on everything else - they will be hanled by 
process_flags() */
++              }
++      }
++}
++
++/*
+  * process_flags - perform command line argument setting
+  *
+  *    process_flags() interprets the command line arguments and sets the
+@@ -895,6 +952,7 @@
+                       {"move-home", no_argument, NULL, 'm'},
+                       {"non-unique", no_argument, NULL, 'o'},
+                       {"password", required_argument, NULL, 'p'},
++                      {"root", required_argument, NULL, 'R'},
+ #ifdef WITH_SELINUX
+                       {"selinux-user", required_argument, NULL, 'Z'},
+ #endif
+@@ -905,9 +963,9 @@
+               };
+               while ((c = getopt_long (argc, argv,
+ #ifdef WITH_SELINUX
+-                                       "ac:d:e:f:g:G:hl:Lmop:s:u:UZ:",
++                                       "ac:d:e:f:g:G:hl:Lmop:R:s:u:UZ:",
+ #else
+-                                       "ac:d:e:f:g:G:hl:Lmop:s:u:U",
++                                       "ac:d:e:f:g:G:hl:Lmop:R:s:u:U",
+ #endif
+                                        long_options, NULL)) != -1) {
+                       switch (c) {
+@@ -999,6 +1057,9 @@
+                               user_pass = optarg;
+                               pflg = true;
+                               break;
++                      case 'R':
++                              /* no-op since we handled this in 
process_root_flag() earlier */
++                              break;
+                       case 's':
+                               if (!VALID (optarg)) {
+                                       fprintf (stderr,
+@@ -1715,6 +1776,8 @@
+ 
+       OPENLOG ("usermod");
+ 
++      process_root_flag (argc, argv);
++
+       is_shadow_pwd = spw_file_present ();
+ #ifdef SHADOWGRP
+       is_shadow_grp = sgr_file_present ();
diff --git a/meta/recipes-extended/shadow/shadow-native_4.1.4.3.bb 
b/meta/recipes-extended/shadow/shadow-native_4.1.4.3.bb
new file mode 100644
index 0000000..2f93e05
--- /dev/null
+++ b/meta/recipes-extended/shadow/shadow-native_4.1.4.3.bb
@@ -0,0 +1,66 @@
+SUMMARY = "Tools to change and administer password and group data"
+DESCRIPTION = "Tools to change and administer password and group data"
+HOMEPAGE = "http://pkg-shadow.alioth.debian.org";
+BUGTRACKER = "https://alioth.debian.org/tracker/?group_id=30580";
+SECTION = "base utils"
+PRIORITY = "optional"
+LICENSE = "BSD | Artistic"
+LIC_FILES_CHKSUM = "file://COPYING;md5=08c553a87d4e51bbed50b20e0adcaede \
+                    
file://src/passwd.c;firstline=8;endline=30;md5=2899a045e90511d0e043b85a7db7e2fe"
+
+PR = "r0"
+
+SRC_URI = 
"ftp://pkg-shadow.alioth.debian.org/pub/pkg-shadow/shadow-${PV}.tar.bz2 \
+           file://shadow.automake-1.11.patch \
+           file://shadow-4.1.3-dots-in-usernames.patch \
+           file://shadow-4.1.4.2-env-reset-keep-locale.patch \
+           file://add_root_cmd_options.patch"
+
+SRC_URI[md5sum] = "b8608d8294ac88974f27b20f991c0e79"
+SRC_URI[sha256sum] = 
"633f5bb4ea0c88c55f3642c97f9d25cbef74f82e0b4cf8d54e7ad6f9f9caa778" 
+
+inherit autotools gettext native
+
+EXTRA_OECONF += "--without-audit \
+                 --without-libcrack \
+                 --without-libpam \
+                 --without-selinux"
+
+do_install_append() {
+       # Enable CREATE_HOME by default.
+       sed -i 's/#CREATE_HOME/CREATE_HOME/g' ${D}${sysconfdir}/login.defs
+
+       # As we are on an embedded system, ensure the users mailbox is in
+       # ~/ not /var/spool/mail by default, as who knows where or how big
+       # /var is. The system MDA will set this later anyway.
+       sed -i 's/MAIL_DIR/#MAIL_DIR/g' ${D}${sysconfdir}/login.defs
+       sed -i 's/#MAIL_FILE/MAIL_FILE/g' ${D}${sysconfdir}/login.defs
+
+       # Disable checking emails.
+       sed -i 's/MAIL_CHECK_ENAB/#MAIL_CHECK_ENAB/g' 
${D}${sysconfdir}/login.defs
+
+       # Now we don't have a mail system. Disable mail creation for now.
+       sed -i 's:/bin/bash:/bin/sh:g' ${D}${sysconfdir}/default/useradd
+       sed -i '/^CREATE_MAIL_SPOOL/ s:^:#:' ${D}${sysconfdir}/default/useradd
+
+       install -d ${D}${sbindir} ${D}${base_sbindir} ${D}${base_bindir} 
+       for i in passwd chfn newgrp chsh ; do
+               mv ${D}${bindir}/$i ${D}${bindir}/$i.${PN}
+       done
+
+       mv ${D}${sbindir}/chpasswd ${D}${sbindir}/chpasswd.${PN}
+}
+
+pkg_postinst_${PN} () {
+       update-alternatives --install ${bindir}/passwd passwd passwd.${PN} 200
+       update-alternatives --install ${sbindir}/chpasswd chpasswd 
chpasswd.${PN} 200
+       update-alternatives --install ${bindir}/chfn chfn chfn.${PN} 200
+       update-alternatives --install ${bindir}/newgrp newgrp newgrp.${PN} 200
+       update-alternatives --install ${bindir}/chsh chsh chsh.${PN} 200
+}
+
+pkg_prerm_${PN} () {
+       for i in passwd chpasswd chfn newgrp chsh ; do
+               update-alternatives --remove $i $i.${PN}
+       done
+}
-- 
1.7.1


_______________________________________________
Openembedded-core mailing list
Openembedded-core@lists.openembedded.org
http://lists.linuxtogo.org/cgi-bin/mailman/listinfo/openembedded-core

Reply via email to