#include <sys/wait.h>
#include "pw.h"
-#if !defined(_PATH_YP)
-#define _PATH_YP "/var/yp/"
-#endif
const char *Modes[] = {
"add", "del", "mod", "show", "next",
NULL};
vgetgrnam,
};
-struct pwconf conf;
-
-static struct cargs arglist;
+static int (*cmdfunc[W_NUM][M_NUM])(int argc, char **argv, char *_name) = {
+ { /* user */
+ pw_user_add,
+ pw_user_del,
+ pw_user_mod,
+ pw_user_show,
+ pw_user_next,
+ pw_user_lock,
+ pw_user_unlock,
+ },
+ { /* group */
+ pw_group_add,
+ pw_group_del,
+ pw_group_mod,
+ pw_group_show,
+ pw_group_next,
+ }
+};
-static int getindex(const char *words[], const char *word);
-static void cmdhelp(int mode, int which);
+struct pwconf conf;
+static int getindex(const char *words[], const char *word);
+static void cmdhelp(int mode, int which);
int
main(int argc, char *argv[])
{
- int ch;
- int mode = -1;
- int which = -1;
- char *config = NULL;
+ int mode = -1, which = -1, tmp;
struct stat st;
- char arg;
+ char arg, *arg1;
bool relocated, nis;
- static const char *opts[W_NUM][M_NUM] =
- {
- { /* user */
- "R:V:C:qn:u:c:d:e:p:g:G:mM:k:s:oL:i:w:h:H:Db:NPy:Y",
- "R:V:C:qn:u:rY",
- "R:V:C:qn:u:c:d:e:p:g:G:mM:l:k:s:w:L:h:H:FNPY",
- "R:V:C:qn:u:FPa7",
- "R:V:C:q",
- "R:V:C:q",
- "R:V:C:q"
- },
- { /* grp */
- "R:V:C:qn:g:h:H:M:opNPY",
- "R:V:C:qn:g:Y",
- "R:V:C:qn:d:g:l:h:H:FM:m:NPY",
- "R:V:C:qn:g:FPa",
- "R:V:C:q"
- }
- };
-
- static int (*funcs[W_NUM]) (int _mode, struct cargs * _args) =
- { /* Request handlers */
- pw_user,
- pw_group
- };
-
+ arg1 = NULL;
relocated = nis = false;
- conf.rootdir[0] = '\0';
- conf.dryrun = false;
+ memset(&conf, 0, sizeof(conf));
+ strlcpy(conf.rootdir, "/", sizeof(conf.rootdir));
strlcpy(conf.etcpath, _PATH_PWD, sizeof(conf.etcpath));
+ conf.fd = -1;
+ conf.checkduplicate = true;
- LIST_INIT(&arglist);
-
- (void)setlocale(LC_ALL, "");
+ setlocale(LC_ALL, "");
/*
* Break off the first couple of words to determine what exactly
* we're being asked to do
*/
while (argc > 1) {
- int tmp;
-
if (*argv[1] == '-') {
/*
* Special case, allow pw -V<dir> <operation> [args] for scripts etc.
} else if (strcmp(argv[1], "help") == 0 && argv[2] == NULL)
cmdhelp(mode, which);
else if (which != -1 && mode != -1)
- addarg(&arglist, 'n', argv[1]);
+ arg1 = argv[1];
else
errx(EX_USAGE, "unknown keyword `%s'", argv[1]);
++argv;
if (mode == -1 || which == -1)
cmdhelp(mode, which);
- /*
- * We know which mode we're in and what we're about to do, so now
- * let's dispatch the remaining command line args in a genric way.
- */
- optarg = NULL;
-
- while ((ch = getopt(argc, argv, opts[which][mode])) != -1) {
- switch (ch) {
- case '?':
- errx(EX_USAGE, "unknown switch");
- break;
- case 'C':
- config = optarg;
- break;
- case 'N':
- conf.dryrun = true;
- break;
- case 'Y':
- nis = true;
- break;
- default:
- addarg(&arglist, ch, optarg);
- break;
- }
- optarg = NULL;
- }
-
- /*
- * Must be root to attempt an update
- */
- if (geteuid() != 0 && mode != M_PRINT && mode != M_NEXT && !conf.dryrun)
- errx(EX_NOPERM, "you must be root to run this program");
-
- /*
- * We should immediately look for the -q 'quiet' switch so that we
- * don't bother with extraneous errors
- */
- if (getarg(&arglist, 'q') != NULL)
- freopen(_PATH_DEVNULL, "w", stderr);
-
- /*
- * Set our base working path if not overridden
- */
-
- if (config == NULL) { /* Only override config location if -C not specified */
- asprintf(&config, "%s/pw.conf", conf.etcpath);
- if (config == NULL)
- errx(EX_OSERR, "out of memory");
- }
-
- /*
- * Now, let's do the common initialisation
- */
- conf.userconf = read_userconfig(config);
-
- ch = funcs[which] (mode, &arglist);
-
- /*
- * If everything went ok, and we've been asked to update
- * the NIS maps, then do it now
- */
- if (ch == EXIT_SUCCESS && nis) {
- pid_t pid;
+ conf.rootfd = open(conf.rootdir, O_DIRECTORY|O_CLOEXEC);
+ if (conf.rootfd == -1)
+ errx(EXIT_FAILURE, "Unable to open '%s'", conf.rootdir);
- fflush(NULL);
- if (chdir(_PATH_YP) == -1)
- warn("chdir(" _PATH_YP ")");
- else if ((pid = fork()) == -1)
- warn("fork()");
- else if (pid == 0) {
- /* Is make anywhere else? */
- execlp("/usr/bin/make", "make", (char *)NULL);
- _exit(1);
- } else {
- int i;
- waitpid(pid, &i, 0);
- if ((i = WEXITSTATUS(i)) != 0)
- errx(ch, "make exited with status %d", i);
- else
- pw_log(conf.userconf, mode, which, "NIS maps updated");
- }
- }
- return ch;
+ return (cmdfunc[which][mode](argc, argv, arg1));
}
static int
getindex(const char *words[], const char *word)
{
- int i = 0;
+ int i = 0;
while (words[i]) {
if (strcmp(words[i], word) == 0)
- return i;
+ return (i);
i++;
}
- return -1;
+ return (-1);
}
" Setting defaults:\n"
"\t-V etcdir alternate /etc location\n"
"\t-R rootir alternate root directory\n"
- "\t-D set user defaults\n"
+ "\t-D set user defaults\n"
"\t-b dir default home root dir\n"
"\t-e period default expiry period\n"
"\t-p period default password change period\n"
"\t-n name login name\n"
"\t-u uid user id\n"
"\t-Y update NIS maps\n"
+ "\t-y path set NIS passwd file path\n"
"\t-r remove home & contents\n",
"usage: pw usermod [uid|name] [switches]\n"
"\t-V etcdir alternate /etc location\n"
"\t-h fd read password on fd\n"
"\t-H fd read encrypted password on fd\n"
"\t-Y update NIS maps\n"
+ "\t-y path set NIS passwd file path\n"
"\t-N no update\n",
"usage: pw usershow [uid|name] [switches]\n"
"\t-V etcdir alternate /etc location\n"
}
exit(EXIT_FAILURE);
}
-
-struct carg *
-getarg(struct cargs * _args, int ch)
-{
- struct carg *c = LIST_FIRST(_args);
-
- while (c != NULL && c->ch != ch)
- c = LIST_NEXT(c, list);
- return c;
-}
-
-struct carg *
-addarg(struct cargs * _args, int ch, char *argstr)
-{
- struct carg *ca = malloc(sizeof(struct carg));
-
- if (ca == NULL)
- errx(EX_OSERR, "out of memory");
- ca->ch = ch;
- ca->val = argstr;
- LIST_INSERT_HEAD(_args, ca, list);
- return ca;
-}