int ch;
int mode = -1;
int which = -1;
+ long id = -1;
char *config = NULL;
struct stat st;
- char arg;
+ const char *errstr;
+ char arg, *name;
bool relocated, nis;
static const char *opts[W_NUM][M_NUM] =
}
};
- static int (*funcs[W_NUM]) (int _mode, struct cargs * _args) =
+ static int (*funcs[W_NUM]) (int _mode, char *_name, long _id,
+ struct cargs * _args) =
{ /* Request handlers */
pw_user,
pw_group
};
+ name = NULL;
relocated = nis = 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);
mode = tmp % M_NUM;
} else if (strcmp(argv[1], "help") == 0 && argv[2] == NULL)
cmdhelp(mode, which);
- else if (which != -1 && mode != -1)
- addarg(&arglist, 'n', argv[1]);
- else
+ else if (which != -1 && mode != -1) {
+ if (strspn(argv[1], "0123456789") == strlen(argv[1])) {
+ id = strtonum(argv[1], 0, LONG_MAX, &errstr);
+ if (errstr != NULL)
+ errx(EX_USAGE, "Bad id '%s': %s",
+ argv[1], errstr);
+ } else
+ name = argv[1];
+ } else
errx(EX_USAGE, "unknown keyword `%s'", argv[1]);
++argv;
--argc;
if (mode == -1 || which == -1)
cmdhelp(mode, which);
+ 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.
conf.v7 = true;
break;
case 'C':
- config = optarg;
+ 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 = strtonum(optarg, 0, LONG_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 = strtonum(optarg, 0, LONG_MAX, &errstr);
+ if (errstr != NULL)
+ errx(EX_USAGE, "Bad id '%s': %s", optarg,
+ errstr);
+ break;
+ case 'n':
+ if (strspn(optarg, "0123456789") != strlen(optarg)) {
+ name = optarg;
+ break;
+ }
+ id = strtonum(optarg, 0, LONG_MAX, &errstr);
+ if (errstr != NULL)
+ errx(EX_USAGE, "Bad id '%s': %s", optarg,
+ errstr);
+ 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
*/
* We should immediately look for the -q 'quiet' switch so that we
* don't bother with extraneous errors
*/
- if (getarg(&arglist, 'q') != NULL)
+ if (conf.quiet)
freopen(_PATH_DEVNULL, "w", stderr);
/*
*/
conf.userconf = read_userconfig(config);
- ch = funcs[which] (mode, &arglist);
+ ch = funcs[which] (mode, name, id, &arglist);
/*
* If everything went ok, and we've been asked to update
struct carg *
getarg(struct cargs * _args, int ch)
{
- struct carg *c = LIST_FIRST(_args);
+ struct carg *c;
+
+ if (_args == NULL)
+ return (NULL);
+
+ c = LIST_FIRST(_args);
while (c != NULL && c->ch != ch)
c = LIST_NEXT(c, list);