summaryrefslogtreecommitdiffstats
path: root/pw/pw.c
diff options
context:
space:
mode:
Diffstat (limited to 'pw/pw.c')
-rw-r--r--pw/pw.c296
1 files changed, 35 insertions, 261 deletions
diff --git a/pw/pw.c b/pw/pw.c
index 88c83db..b13db70 100644
--- a/pw/pw.c
+++ b/pw/pw.c
@@ -37,9 +37,6 @@ static const char rcsid[] =
#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};
@@ -85,55 +82,39 @@ struct pwf VPWF =
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;
- long id = -1;
- char *config = NULL;
+ int mode = -1, which = -1, tmp;
struct stat st;
- const char *errstr;
- char arg, *name;
+ 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, char *_name, long _id,
- struct cargs * _args) =
- { /* Request handlers */
- pw_user,
- pw_group
- };
-
- name = NULL;
+ arg1 = NULL;
relocated = nis = false;
memset(&conf, 0, sizeof(conf));
strlcpy(conf.rootdir, "/", sizeof(conf.rootdir));
@@ -141,17 +122,13 @@ main(int argc, char *argv[])
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.
@@ -197,15 +174,9 @@ main(int argc, char *argv[])
mode = tmp % M_NUM;
} else if (strcmp(argv[1], "help") == 0 && argv[2] == NULL)
cmdhelp(mode, which);
- else if (which != -1 && mode != -1) {
- if (strspn(argv[1], "0123456789") == strlen(argv[1])) {
- id = strtounum(argv[1], 0, UID_MAX, &errstr);
- if (errstr != NULL)
- errx(EX_USAGE, "Bad id '%s': %s",
- argv[1], errstr);
- } else
- name = argv[1];
- } else
+ else if (which != -1 && mode != -1)
+ arg1 = argv[1];
+ else
errx(EX_USAGE, "unknown keyword `%s'", argv[1]);
++argv;
--argc;
@@ -220,193 +191,22 @@ main(int argc, char *argv[])
conf.rootfd = open(conf.rootdir, O_DIRECTORY|O_CLOEXEC);
if (conf.rootfd == -1)
errx(EXIT_FAILURE, "Unable to open '%s'", conf.rootdir);
- conf.which = 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 '7':
- conf.v7 = true;
- break;
- case 'C':
- conf.config = optarg;
- config = conf.config;
- break;
- case 'F':
- conf.force = true;
- break;
- case 'N':
- conf.dryrun = true;
- break;
- case 'l':
- if (strlen(optarg) >= MAXLOGNAME)
- errx(EX_USAGE, "new name too long: %s", optarg);
- conf.newname = optarg;
- break;
- case 'P':
- conf.pretty = true;
- break;
- case 'Y':
- nis = true;
- break;
- case 'a':
- conf.all = true;
- break;
- case 'c':
- conf.gecos = pw_checkname(optarg, 1);
- break;
- case 'g':
- if (which == 0) { /* for user* */
- addarg(&arglist, 'g', optarg);
- break;
- }
- if (strspn(optarg, "0123456789") != strlen(optarg))
- errx(EX_USAGE, "-g expects a number");
- id = strtounum(optarg, 0, GID_MAX, &errstr);
- if (errstr != NULL)
- errx(EX_USAGE, "Bad id '%s': %s", optarg,
- errstr);
- break;
- case 'u':
- if (strspn(optarg, "0123456789,") != strlen(optarg))
- errx(EX_USAGE, "-u expects a number");
- if (strchr(optarg, ',') != NULL) {
- addarg(&arglist, 'u', optarg);
- break;
- }
- id = strtounum(optarg, 0, UID_MAX, &errstr);
- if (errstr != NULL)
- errx(EX_USAGE, "Bad id '%s': %s", optarg,
- errstr);
- break;
- case 'n':
- name = optarg;
- break;
- case 'H':
- if (conf.fd != -1)
- errx(EX_USAGE, "'-h' and '-H' are mutually "
- "exclusive options");
- conf.precrypted = true;
- if (strspn(optarg, "0123456789") != strlen(optarg))
- errx(EX_USAGE, "'-H' expects a file descriptor");
-
- conf.fd = strtonum(optarg, 0, INT_MAX, &errstr);
- if (errstr != NULL)
- errx(EX_USAGE, "Bad file descriptor '%s': %s",
- optarg, errstr);
- break;
- case 'h':
- if (conf.fd != -1)
- errx(EX_USAGE, "'-h' and '-H' are mutually "
- "exclusive options");
-
- if (strcmp(optarg, "-") == 0)
- conf.fd = '-';
- else if (strspn(optarg, "0123456789") == strlen(optarg)) {
- conf.fd = strtonum(optarg, 0, INT_MAX, &errstr);
- if (errstr != NULL)
- errx(EX_USAGE, "'-h' expects a "
- "file descriptor or '-'");
- } else
- errx(EX_USAGE, "'-h' expects a file "
- "descriptor or '-'");
- break;
- case 'o':
- conf.checkduplicate = false;
- break;
- case 'q':
- conf.quiet = true;
- break;
- case 'r':
- conf.deletehome = true;
- break;
- default:
- addarg(&arglist, ch, optarg);
- break;
- }
- optarg = NULL;
- }
-
- if (name != NULL && strlen(name) >= MAXLOGNAME)
- errx(EX_USAGE, "name too long: %s", name);
-
- /*
- * 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 (conf.quiet)
- 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, name, id, &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;
-
- 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);
}
@@ -456,7 +256,7 @@ cmdhelp(int mode, int which)
" 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"
@@ -476,6 +276,7 @@ cmdhelp(int mode, int which)
"\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"
@@ -500,6 +301,7 @@ cmdhelp(int mode, int which)
"\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"
@@ -576,31 +378,3 @@ cmdhelp(int mode, int which)
}
exit(EXIT_FAILURE);
}
-
-struct carg *
-getarg(struct cargs * _args, int ch)
-{
- struct carg *c;
-
- if (_args == NULL)
- return (NULL);
-
- 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;
-}