xref: /freebsd/usr.sbin/pw/pw.c (revision d2d022b9fdebd6bfe2983bb688818ed8bfc422a6)
1d6f907dcSJoerg Wunsch /*-
2ad7cf975SJoerg Wunsch  * Copyright (C) 1996
3ad7cf975SJoerg Wunsch  *	David L. Nugent.  All rights reserved.
4d6f907dcSJoerg Wunsch  *
5d6f907dcSJoerg Wunsch  * Redistribution and use in source and binary forms, with or without
6d6f907dcSJoerg Wunsch  * modification, are permitted provided that the following conditions
7d6f907dcSJoerg Wunsch  * are met:
8d6f907dcSJoerg Wunsch  * 1. Redistributions of source code must retain the above copyright
9ad7cf975SJoerg Wunsch  *    notice, this list of conditions and the following disclaimer.
10d6f907dcSJoerg Wunsch  * 2. Redistributions in binary form must reproduce the above copyright
11d6f907dcSJoerg Wunsch  *    notice, this list of conditions and the following disclaimer in the
12d6f907dcSJoerg Wunsch  *    documentation and/or other materials provided with the distribution.
13d6f907dcSJoerg Wunsch  *
14ad7cf975SJoerg Wunsch  * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND
15d6f907dcSJoerg Wunsch  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16d6f907dcSJoerg Wunsch  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17ad7cf975SJoerg Wunsch  * ARE DISCLAIMED.  IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE
18d6f907dcSJoerg Wunsch  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19d6f907dcSJoerg Wunsch  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20d6f907dcSJoerg Wunsch  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21d6f907dcSJoerg Wunsch  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22d6f907dcSJoerg Wunsch  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23d6f907dcSJoerg Wunsch  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24d6f907dcSJoerg Wunsch  * SUCH DAMAGE.
25d6f907dcSJoerg Wunsch  */
26d6f907dcSJoerg Wunsch 
271dcc6ec7SPhilippe Charnier #ifndef lint
281dcc6ec7SPhilippe Charnier static const char rcsid[] =
2997d92980SPeter Wemm   "$FreeBSD$";
301dcc6ec7SPhilippe Charnier #endif /* not lint */
311dcc6ec7SPhilippe Charnier 
321dcc6ec7SPhilippe Charnier #include <err.h>
335e91a8acSNate Williams #include <fcntl.h>
34e7161f36SAndrey A. Chernov #include <locale.h>
35f1d684faSDavid Nugent #include <paths.h>
362cc63cd1SBaptiste Daroussin #include <stdbool.h>
37f1d684faSDavid Nugent #include <sys/wait.h>
385f12594aSDavid Nugent #include "pw.h"
39d6f907dcSJoerg Wunsch 
402399cd14SDavid Nugent const char     *Modes[] = {
412399cd14SDavid Nugent   "add", "del", "mod", "show", "next",
422399cd14SDavid Nugent   NULL};
43d6f907dcSJoerg Wunsch const char     *Which[] = {"user", "group", NULL};
4448aee7f3SJoerg Wunsch static const char *Combo1[] = {
4548aee7f3SJoerg Wunsch   "useradd", "userdel", "usermod", "usershow", "usernext",
462399cd14SDavid Nugent   "lock", "unlock",
4748aee7f3SJoerg Wunsch   "groupadd", "groupdel", "groupmod", "groupshow", "groupnext",
48d6f907dcSJoerg Wunsch   NULL};
4948aee7f3SJoerg Wunsch static const char *Combo2[] = {
5048aee7f3SJoerg Wunsch   "adduser", "deluser", "moduser", "showuser", "nextuser",
512399cd14SDavid Nugent   "lock", "unlock",
5248aee7f3SJoerg Wunsch   "addgroup", "delgroup", "modgroup", "showgroup", "nextgroup",
53d6f907dcSJoerg Wunsch   NULL};
54d6f907dcSJoerg Wunsch 
555f12594aSDavid Nugent struct pwf PWF =
565f12594aSDavid Nugent {
57ac72be28SBaptiste Daroussin 	PWF_REGULAR,
585f12594aSDavid Nugent 	setpwent,
595f12594aSDavid Nugent 	endpwent,
605f12594aSDavid Nugent 	getpwent,
615f12594aSDavid Nugent 	getpwuid,
625f12594aSDavid Nugent 	getpwnam,
635f12594aSDavid Nugent 	setgrent,
645f12594aSDavid Nugent 	endgrent,
655f12594aSDavid Nugent 	getgrent,
665f12594aSDavid Nugent 	getgrgid,
675f12594aSDavid Nugent 	getgrnam,
685f12594aSDavid Nugent 
695f12594aSDavid Nugent };
705f12594aSDavid Nugent struct pwf VPWF =
715f12594aSDavid Nugent {
72ac72be28SBaptiste Daroussin 	PWF_ALT,
735f12594aSDavid Nugent 	vsetpwent,
745f12594aSDavid Nugent 	vendpwent,
755f12594aSDavid Nugent 	vgetpwent,
765f12594aSDavid Nugent 	vgetpwuid,
775f12594aSDavid Nugent 	vgetpwnam,
785f12594aSDavid Nugent 	vsetgrent,
795f12594aSDavid Nugent 	vendgrent,
805f12594aSDavid Nugent 	vgetgrent,
815f12594aSDavid Nugent 	vgetgrgid,
825f12594aSDavid Nugent 	vgetgrnam,
835f12594aSDavid Nugent };
845f12594aSDavid Nugent 
85*d2d022b9SBaptiste Daroussin static int (*cmdfunc[W_NUM][M_NUM])(int argc, char **argv, char *_name) = {
86*d2d022b9SBaptiste Daroussin 	{ /* user */
87*d2d022b9SBaptiste Daroussin 		pw_user_add,
88*d2d022b9SBaptiste Daroussin 		pw_user_del,
89*d2d022b9SBaptiste Daroussin 		pw_user_mod,
90*d2d022b9SBaptiste Daroussin 		pw_user_show,
91*d2d022b9SBaptiste Daroussin 		pw_user_next,
92*d2d022b9SBaptiste Daroussin 		pw_user_lock,
93*d2d022b9SBaptiste Daroussin 		pw_user_unlock,
94*d2d022b9SBaptiste Daroussin 	},
95*d2d022b9SBaptiste Daroussin 	{ /* group */
96*d2d022b9SBaptiste Daroussin 		pw_group_add,
97*d2d022b9SBaptiste Daroussin 		pw_group_del,
98*d2d022b9SBaptiste Daroussin 		pw_group_mod,
99*d2d022b9SBaptiste Daroussin 		pw_group_show,
100*d2d022b9SBaptiste Daroussin 		pw_group_next,
101*d2d022b9SBaptiste Daroussin 	}
102*d2d022b9SBaptiste Daroussin };
1032cc63cd1SBaptiste Daroussin 
104*d2d022b9SBaptiste Daroussin struct pwconf conf;
105d6f907dcSJoerg Wunsch 
106d6f907dcSJoerg Wunsch static int	getindex(const char *words[], const char *word);
107d6f907dcSJoerg Wunsch static void	cmdhelp(int mode, int which);
108d6f907dcSJoerg Wunsch 
109d6f907dcSJoerg Wunsch int
110d6f907dcSJoerg Wunsch main(int argc, char *argv[])
111d6f907dcSJoerg Wunsch {
112*d2d022b9SBaptiste Daroussin 	int		mode = -1, which = -1, tmp;
11390edef4fSBaptiste Daroussin 	struct stat	st;
114*d2d022b9SBaptiste Daroussin 	char		arg, *arg1;
11582a3c75aSBaptiste Daroussin 	bool		relocated, nis;
116d6f907dcSJoerg Wunsch 
117*d2d022b9SBaptiste Daroussin 	arg1 = NULL;
11882a3c75aSBaptiste Daroussin 	relocated = nis = false;
119bbe09b2eSBaptiste Daroussin 	memset(&conf, 0, sizeof(conf));
12065730d93SBaptiste Daroussin 	strlcpy(conf.rootdir, "/", sizeof(conf.rootdir));
1212cc63cd1SBaptiste Daroussin 	strlcpy(conf.etcpath, _PATH_PWD, sizeof(conf.etcpath));
12211621f96SBaptiste Daroussin 	conf.fd = -1;
123a70fbf7eSBaptiste Daroussin 	conf.checkduplicate = true;
1242cc63cd1SBaptiste Daroussin 
125*d2d022b9SBaptiste Daroussin 	setlocale(LC_ALL, "");
126e7161f36SAndrey A. Chernov 
127d6f907dcSJoerg Wunsch 	/*
128d6f907dcSJoerg Wunsch 	 * Break off the first couple of words to determine what exactly
129d6f907dcSJoerg Wunsch 	 * we're being asked to do
130d6f907dcSJoerg Wunsch 	 */
1315f12594aSDavid Nugent 	while (argc > 1) {
1325f12594aSDavid Nugent 		if (*argv[1] == '-') {
1335f12594aSDavid Nugent 			/*
1345f12594aSDavid Nugent 			 * Special case, allow pw -V<dir> <operation> [args] for scripts etc.
1355f12594aSDavid Nugent 			 */
136ac72be28SBaptiste Daroussin 			arg = argv[1][1];
137ac72be28SBaptiste Daroussin 			if (arg == 'V' || arg == 'R') {
1382cc63cd1SBaptiste Daroussin 				if (relocated)
1392cc63cd1SBaptiste Daroussin 					errx(EXIT_FAILURE, "Both '-R' and '-V' "
1402cc63cd1SBaptiste Daroussin 					    "specified, only one accepted");
1412cc63cd1SBaptiste Daroussin 				relocated = true;
1425f12594aSDavid Nugent 				optarg = &argv[1][2];
1435f12594aSDavid Nugent 				if (*optarg == '\0') {
14490edef4fSBaptiste Daroussin 					if (stat(argv[2], &st) != 0)
14590edef4fSBaptiste Daroussin 						errx(EX_OSFILE, \
14690edef4fSBaptiste Daroussin 						    "no such directory `%s'",
14790edef4fSBaptiste Daroussin 						    argv[2]);
14890edef4fSBaptiste Daroussin 					if (!S_ISDIR(st.st_mode))
14990edef4fSBaptiste Daroussin 						errx(EX_OSFILE, "`%s' not a "
15090edef4fSBaptiste Daroussin 						    "directory", argv[2]);
1515f12594aSDavid Nugent 					optarg = argv[2];
1525f12594aSDavid Nugent 					++argv;
1535f12594aSDavid Nugent 					--argc;
1545f12594aSDavid Nugent 				}
1552cc63cd1SBaptiste Daroussin 				memcpy(&PWF, &VPWF, sizeof PWF);
1562cc63cd1SBaptiste Daroussin 				if (arg == 'R') {
1572cc63cd1SBaptiste Daroussin 					strlcpy(conf.rootdir, optarg,
1582cc63cd1SBaptiste Daroussin 					    sizeof(conf.rootdir));
1592cc63cd1SBaptiste Daroussin 					PWF._altdir = PWF_ROOTDIR;
1602cc63cd1SBaptiste Daroussin 				}
1612cc63cd1SBaptiste Daroussin 				snprintf(conf.etcpath, sizeof(conf.etcpath),
1622cc63cd1SBaptiste Daroussin 				    "%s%s", optarg, arg == 'R' ? "/etc" : "");
163e3921b27SDavid Nugent 			} else
1645f12594aSDavid Nugent 				break;
1655f12594aSDavid Nugent 		}
166c4e667b9SDavid Nugent 		else if (mode == -1 && (tmp = getindex(Modes, argv[1])) != -1)
167d6f907dcSJoerg Wunsch 			mode = tmp;
168c4e667b9SDavid Nugent 		else if (which == -1 && (tmp = getindex(Which, argv[1])) != -1)
169d6f907dcSJoerg Wunsch 			which = tmp;
170c4e667b9SDavid Nugent 		else if ((mode == -1 && which == -1) &&
171c4e667b9SDavid Nugent 			 ((tmp = getindex(Combo1, argv[1])) != -1 ||
172c4e667b9SDavid Nugent 			  (tmp = getindex(Combo2, argv[1])) != -1)) {
173d6f907dcSJoerg Wunsch 			which = tmp / M_NUM;
174d6f907dcSJoerg Wunsch 			mode = tmp % M_NUM;
175c4e667b9SDavid Nugent 		} else if (strcmp(argv[1], "help") == 0 && argv[2] == NULL)
176d6f907dcSJoerg Wunsch 			cmdhelp(mode, which);
177*d2d022b9SBaptiste Daroussin 		else if (which != -1 && mode != -1)
178*d2d022b9SBaptiste Daroussin 				arg1 = argv[1];
179*d2d022b9SBaptiste Daroussin 		else
1801dcc6ec7SPhilippe Charnier 			errx(EX_USAGE, "unknown keyword `%s'", argv[1]);
181d6f907dcSJoerg Wunsch 		++argv;
182d6f907dcSJoerg Wunsch 		--argc;
183d6f907dcSJoerg Wunsch 	}
184d6f907dcSJoerg Wunsch 
185d6f907dcSJoerg Wunsch 	/*
186d6f907dcSJoerg Wunsch 	 * Bail out unless the user is specific!
187d6f907dcSJoerg Wunsch 	 */
188d6f907dcSJoerg Wunsch 	if (mode == -1 || which == -1)
189d6f907dcSJoerg Wunsch 		cmdhelp(mode, which);
190d6f907dcSJoerg Wunsch 
19165730d93SBaptiste Daroussin 	conf.rootfd = open(conf.rootdir, O_DIRECTORY|O_CLOEXEC);
19265730d93SBaptiste Daroussin 	if (conf.rootfd == -1)
19365730d93SBaptiste Daroussin 		errx(EXIT_FAILURE, "Unable to open '%s'", conf.rootdir);
194d6f907dcSJoerg Wunsch 
195*d2d022b9SBaptiste Daroussin 	return (cmdfunc[which][mode](argc, argv, arg1));
196d6f907dcSJoerg Wunsch }
197d6f907dcSJoerg Wunsch 
1985e91a8acSNate Williams 
199d6f907dcSJoerg Wunsch static int
200d6f907dcSJoerg Wunsch getindex(const char *words[], const char *word)
201d6f907dcSJoerg Wunsch {
202d6f907dcSJoerg Wunsch 	int	i = 0;
203d6f907dcSJoerg Wunsch 
204d6f907dcSJoerg Wunsch 	while (words[i]) {
205d6f907dcSJoerg Wunsch 		if (strcmp(words[i], word) == 0)
206*d2d022b9SBaptiste Daroussin 			return (i);
207d6f907dcSJoerg Wunsch 		i++;
208d6f907dcSJoerg Wunsch 	}
209*d2d022b9SBaptiste Daroussin 	return (-1);
210d6f907dcSJoerg Wunsch }
211d6f907dcSJoerg Wunsch 
212d6f907dcSJoerg Wunsch 
213d6f907dcSJoerg Wunsch /*
214d6f907dcSJoerg Wunsch  * This is probably an overkill for a cmdline help system, but it reflects
215d6f907dcSJoerg Wunsch  * the complexity of the command line.
216d6f907dcSJoerg Wunsch  */
217d6f907dcSJoerg Wunsch 
218d6f907dcSJoerg Wunsch static void
219d6f907dcSJoerg Wunsch cmdhelp(int mode, int which)
220d6f907dcSJoerg Wunsch {
221d6f907dcSJoerg Wunsch 	if (which == -1)
2222399cd14SDavid Nugent 		fprintf(stderr, "usage:\n  pw [user|group|lock|unlock] [add|del|mod|show|next] [help|switches/values]\n");
223d6f907dcSJoerg Wunsch 	else if (mode == -1)
2242399cd14SDavid Nugent 		fprintf(stderr, "usage:\n  pw %s [add|del|mod|show|next] [help|switches/values]\n", Which[which]);
225d6f907dcSJoerg Wunsch 	else {
226d6f907dcSJoerg Wunsch 
227d6f907dcSJoerg Wunsch 		/*
228d6f907dcSJoerg Wunsch 		 * We need to give mode specific help
229d6f907dcSJoerg Wunsch 		 */
230d6f907dcSJoerg Wunsch 		static const char *help[W_NUM][M_NUM] =
231d6f907dcSJoerg Wunsch 		{
232d6f907dcSJoerg Wunsch 			{
2331dcc6ec7SPhilippe Charnier 				"usage: pw useradd [name] [switches]\n"
2345f12594aSDavid Nugent 				"\t-V etcdir      alternate /etc location\n"
235ac72be28SBaptiste Daroussin 				"\t-R rootir      alternate root directory\n"
236d6f907dcSJoerg Wunsch 				"\t-C config      configuration file\n"
237d6f907dcSJoerg Wunsch 				"\t-q             quiet operation\n"
238d6f907dcSJoerg Wunsch 				"  Adding users:\n"
239d6f907dcSJoerg Wunsch 				"\t-n name        login name\n"
240d6f907dcSJoerg Wunsch 				"\t-u uid         user id\n"
241d6f907dcSJoerg Wunsch 				"\t-c comment     user name/comment\n"
242d6f907dcSJoerg Wunsch 				"\t-d directory   home directory\n"
243d6f907dcSJoerg Wunsch 				"\t-e date        account expiry date\n"
244d6f907dcSJoerg Wunsch 				"\t-p date        password expiry date\n"
245d6f907dcSJoerg Wunsch 				"\t-g grp         initial group\n"
246d6f907dcSJoerg Wunsch 				"\t-G grp1,grp2   additional groups\n"
247d6f907dcSJoerg Wunsch 				"\t-m [ -k dir ]  create and set up home\n"
2481dd634b0SLukas Ertl 				"\t-M mode        home directory permissions\n"
249d6f907dcSJoerg Wunsch 				"\t-s shell       name of login shell\n"
250d6f907dcSJoerg Wunsch 				"\t-o             duplicate uid ok\n"
251d6f907dcSJoerg Wunsch 				"\t-L class       user class\n"
252d6f907dcSJoerg Wunsch 				"\t-h fd          read password on fd\n"
25387d6b5caSIan Dowse 				"\t-H fd          read encrypted password on fd\n"
254f1d684faSDavid Nugent 				"\t-Y             update NIS maps\n"
25548aee7f3SJoerg Wunsch 				"\t-N             no update\n"
256d6f907dcSJoerg Wunsch 				"  Setting defaults:\n"
2575f12594aSDavid Nugent 				"\t-V etcdir      alternate /etc location\n"
258ac72be28SBaptiste Daroussin 				"\t-R rootir      alternate root directory\n"
259d6f907dcSJoerg Wunsch 				"\t-D             set user defaults\n"
260d6f907dcSJoerg Wunsch 				"\t-b dir         default home root dir\n"
261d6f907dcSJoerg Wunsch 				"\t-e period      default expiry period\n"
262d6f907dcSJoerg Wunsch 				"\t-p period      default password change period\n"
263d6f907dcSJoerg Wunsch 				"\t-g group       default group\n"
264d6f907dcSJoerg Wunsch 				"\t-G grp1,grp2   additional groups\n"
265d6f907dcSJoerg Wunsch 				"\t-L class       default user class\n"
266d6f907dcSJoerg Wunsch 				"\t-k dir         default home skeleton\n"
26785204142SLukas Ertl 				"\t-M mode        home directory permissions\n"
268d6f907dcSJoerg Wunsch 				"\t-u min,max     set min,max uids\n"
269d6f907dcSJoerg Wunsch 				"\t-i min,max     set min,max gids\n"
270d6f907dcSJoerg Wunsch 				"\t-w method      set default password method\n"
271f1d684faSDavid Nugent 				"\t-s shell       default shell\n"
272f1d684faSDavid Nugent 				"\t-y path        set NIS passwd file path\n",
2731dcc6ec7SPhilippe Charnier 				"usage: pw userdel [uid|name] [switches]\n"
2745f12594aSDavid Nugent 				"\t-V etcdir      alternate /etc location\n"
275ac72be28SBaptiste Daroussin 				"\t-R rootir      alternate root directory\n"
276d6f907dcSJoerg Wunsch 				"\t-n name        login name\n"
277d6f907dcSJoerg Wunsch 				"\t-u uid         user id\n"
278f1d684faSDavid Nugent 				"\t-Y             update NIS maps\n"
279*d2d022b9SBaptiste Daroussin 				"\t-y path        set NIS passwd file path\n"
280d6f907dcSJoerg Wunsch 				"\t-r             remove home & contents\n",
2811dcc6ec7SPhilippe Charnier 				"usage: pw usermod [uid|name] [switches]\n"
2825f12594aSDavid Nugent 				"\t-V etcdir      alternate /etc location\n"
283ac72be28SBaptiste Daroussin 				"\t-R rootir      alternate root directory\n"
284d6f907dcSJoerg Wunsch 				"\t-C config      configuration file\n"
285d6f907dcSJoerg Wunsch 				"\t-q             quiet operation\n"
286d6f907dcSJoerg Wunsch 				"\t-F             force add if no user\n"
287d6f907dcSJoerg Wunsch 				"\t-n name        login name\n"
288d6f907dcSJoerg Wunsch 				"\t-u uid         user id\n"
289d6f907dcSJoerg Wunsch 				"\t-c comment     user name/comment\n"
290d6f907dcSJoerg Wunsch 				"\t-d directory   home directory\n"
291d6f907dcSJoerg Wunsch 				"\t-e date        account expiry date\n"
292d6f907dcSJoerg Wunsch 				"\t-p date        password expiry date\n"
293d6f907dcSJoerg Wunsch 				"\t-g grp         initial group\n"
294d6f907dcSJoerg Wunsch 				"\t-G grp1,grp2   additional groups\n"
295d6f907dcSJoerg Wunsch 				"\t-l name        new login name\n"
296d6f907dcSJoerg Wunsch 				"\t-L class       user class\n"
297d6f907dcSJoerg Wunsch 				"\t-m [ -k dir ]  create and set up home\n"
2981dd634b0SLukas Ertl 				"\t-M mode        home directory permissions\n"
299d6f907dcSJoerg Wunsch 				"\t-s shell       name of login shell\n"
30048aee7f3SJoerg Wunsch 				"\t-w method      set new password using method\n"
30148aee7f3SJoerg Wunsch 				"\t-h fd          read password on fd\n"
30287d6b5caSIan Dowse 				"\t-H fd          read encrypted password on fd\n"
303f1d684faSDavid Nugent 				"\t-Y             update NIS maps\n"
304*d2d022b9SBaptiste Daroussin 				"\t-y path        set NIS passwd file path\n"
30548aee7f3SJoerg Wunsch 				"\t-N             no update\n",
3061dcc6ec7SPhilippe Charnier 				"usage: pw usershow [uid|name] [switches]\n"
3075f12594aSDavid Nugent 				"\t-V etcdir      alternate /etc location\n"
308ac72be28SBaptiste Daroussin 				"\t-R rootir      alternate root directory\n"
309d6f907dcSJoerg Wunsch 				"\t-n name        login name\n"
310d6f907dcSJoerg Wunsch 				"\t-u uid         user id\n"
311d6f907dcSJoerg Wunsch 				"\t-F             force print\n"
31248aee7f3SJoerg Wunsch 				"\t-P             prettier format\n"
313f3522722SDavid Nugent 				"\t-a             print all users\n"
314f3522722SDavid Nugent 				"\t-7             print in v7 format\n",
3151dcc6ec7SPhilippe Charnier 				"usage: pw usernext [switches]\n"
3165f12594aSDavid Nugent 				"\t-V etcdir      alternate /etc location\n"
317ac72be28SBaptiste Daroussin 				"\t-R rootir      alternate root directory\n"
3183bfc59e8SBaptiste Daroussin 				"\t-C config      configuration file\n"
3193bfc59e8SBaptiste Daroussin 				"\t-q             quiet operation\n",
320ed6fd55aSDima Dorfman 				"usage pw: lock [switches]\n"
321ed6fd55aSDima Dorfman 				"\t-V etcdir      alternate /etc locations\n"
322ed6fd55aSDima Dorfman 				"\t-C config      configuration file\n"
323ed6fd55aSDima Dorfman 				"\t-q             quiet operation\n",
324ed6fd55aSDima Dorfman 				"usage pw: unlock [switches]\n"
325ed6fd55aSDima Dorfman 				"\t-V etcdir      alternate /etc locations\n"
326ed6fd55aSDima Dorfman 				"\t-C config      configuration file\n"
327ed6fd55aSDima Dorfman 				"\t-q             quiet operation\n"
328d6f907dcSJoerg Wunsch 			},
329d6f907dcSJoerg Wunsch 			{
3301dcc6ec7SPhilippe Charnier 				"usage: pw groupadd [group|gid] [switches]\n"
3315f12594aSDavid Nugent 				"\t-V etcdir      alternate /etc location\n"
332ac72be28SBaptiste Daroussin 				"\t-R rootir      alternate root directory\n"
333d6f907dcSJoerg Wunsch 				"\t-C config      configuration file\n"
334d6f907dcSJoerg Wunsch 				"\t-q             quiet operation\n"
335d6f907dcSJoerg Wunsch 				"\t-n group       group name\n"
336d6f907dcSJoerg Wunsch 				"\t-g gid         group id\n"
33748aee7f3SJoerg Wunsch 				"\t-M usr1,usr2   add users as group members\n"
33848aee7f3SJoerg Wunsch 				"\t-o             duplicate gid ok\n"
339f1d684faSDavid Nugent 				"\t-Y             update NIS maps\n"
34048aee7f3SJoerg Wunsch 				"\t-N             no update\n",
3411dcc6ec7SPhilippe Charnier 				"usage: pw groupdel [group|gid] [switches]\n"
3425f12594aSDavid Nugent 				"\t-V etcdir      alternate /etc location\n"
343ac72be28SBaptiste Daroussin 				"\t-R rootir      alternate root directory\n"
344d6f907dcSJoerg Wunsch 				"\t-n name        group name\n"
345f1d684faSDavid Nugent 				"\t-g gid         group id\n"
346f1d684faSDavid Nugent 				"\t-Y             update NIS maps\n",
3471dcc6ec7SPhilippe Charnier 				"usage: pw groupmod [group|gid] [switches]\n"
3485f12594aSDavid Nugent 				"\t-V etcdir      alternate /etc location\n"
349ac72be28SBaptiste Daroussin 				"\t-R rootir      alternate root directory\n"
350d6f907dcSJoerg Wunsch 				"\t-C config      configuration file\n"
351d6f907dcSJoerg Wunsch 				"\t-q             quiet operation\n"
352d6f907dcSJoerg Wunsch 				"\t-F             force add if not exists\n"
353d6f907dcSJoerg Wunsch 				"\t-n name        group name\n"
354d6f907dcSJoerg Wunsch 				"\t-g gid         group id\n"
35548aee7f3SJoerg Wunsch 				"\t-M usr1,usr2   replaces users as group members\n"
35648aee7f3SJoerg Wunsch 				"\t-m usr1,usr2   add users as group members\n"
357bc991a6dSSean Farley 				"\t-d usr1,usr2   delete users as group members\n"
35848aee7f3SJoerg Wunsch 				"\t-l name        new group name\n"
359f1d684faSDavid Nugent 				"\t-Y             update NIS maps\n"
36048aee7f3SJoerg Wunsch 				"\t-N             no update\n",
3611dcc6ec7SPhilippe Charnier 				"usage: pw groupshow [group|gid] [switches]\n"
3625f12594aSDavid Nugent 				"\t-V etcdir      alternate /etc location\n"
363ac72be28SBaptiste Daroussin 				"\t-R rootir      alternate root directory\n"
364d6f907dcSJoerg Wunsch 				"\t-n name        group name\n"
365d6f907dcSJoerg Wunsch 				"\t-g gid         group id\n"
366d6f907dcSJoerg Wunsch 				"\t-F             force print\n"
36748aee7f3SJoerg Wunsch 				"\t-P             prettier format\n"
36848aee7f3SJoerg Wunsch 				"\t-a             print all accounting groups\n",
3691dcc6ec7SPhilippe Charnier 				"usage: pw groupnext [switches]\n"
3705f12594aSDavid Nugent 				"\t-V etcdir      alternate /etc location\n"
371ac72be28SBaptiste Daroussin 				"\t-R rootir      alternate root directory\n"
37248aee7f3SJoerg Wunsch 				"\t-C config      configuration file\n"
3733bfc59e8SBaptiste Daroussin 				"\t-q             quiet operation\n"
374d6f907dcSJoerg Wunsch 			}
375d6f907dcSJoerg Wunsch 		};
376d6f907dcSJoerg Wunsch 
377cab0fb4eSKris Kennaway 		fprintf(stderr, "%s", help[which][mode]);
378d6f907dcSJoerg Wunsch 	}
37948aee7f3SJoerg Wunsch 	exit(EXIT_FAILURE);
380d6f907dcSJoerg Wunsch }
381