xref: /freebsd/usr.sbin/pw/pw.c (revision 48aee7f33a5dce843b51b7907af59573f8d3a7c4)
1d6f907dcSJoerg Wunsch /*-
2d6f907dcSJoerg Wunsch  * Copyright (c) 1996 by David L. Nugent <davidn@blaze.net.au>.
3d6f907dcSJoerg Wunsch  * 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
9d6f907dcSJoerg Wunsch  *    notice, this list of conditions and the following disclaimer as
10d6f907dcSJoerg Wunsch  *    the first lines of this file unmodified.
11d6f907dcSJoerg Wunsch  * 2. Redistributions in binary form must reproduce the above copyright
12d6f907dcSJoerg Wunsch  *    notice, this list of conditions and the following disclaimer in the
13d6f907dcSJoerg Wunsch  *    documentation and/or other materials provided with the distribution.
14d6f907dcSJoerg Wunsch  * 3. All advertising materials mentioning features or use of this software
15d6f907dcSJoerg Wunsch  *    must display the following acknowledgement:
16d6f907dcSJoerg Wunsch  *	This product includes software developed by David L. Nugent.
17d6f907dcSJoerg Wunsch  * 4. The name of the author may not be used to endorse or promote products
18d6f907dcSJoerg Wunsch  *    derived from this software without specific prior written permission.
19d6f907dcSJoerg Wunsch  *
20d6f907dcSJoerg Wunsch  * THIS SOFTWARE IS PROVIDED BY THE DAVID L. NUGENT ``AS IS'' AND
21d6f907dcSJoerg Wunsch  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22d6f907dcSJoerg Wunsch  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23d6f907dcSJoerg Wunsch  * ARE DISCLAIMED.  IN NO EVENT SHALL DAVID L. NUGENT BE LIABLE
24d6f907dcSJoerg Wunsch  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25d6f907dcSJoerg Wunsch  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26d6f907dcSJoerg Wunsch  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27d6f907dcSJoerg Wunsch  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28d6f907dcSJoerg Wunsch  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29d6f907dcSJoerg Wunsch  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30d6f907dcSJoerg Wunsch  * SUCH DAMAGE.
31d6f907dcSJoerg Wunsch  *
32d6f907dcSJoerg Wunsch  *	$Id$
33d6f907dcSJoerg Wunsch  */
34d6f907dcSJoerg Wunsch 
35d6f907dcSJoerg Wunsch #include "pw.h"
36d6f907dcSJoerg Wunsch 
37d6f907dcSJoerg Wunsch static char    *progname = "pw";
38d6f907dcSJoerg Wunsch 
3948aee7f3SJoerg Wunsch const char     *Modes[] = {"add", "del", "mod", "show", "next", NULL};
40d6f907dcSJoerg Wunsch const char     *Which[] = {"user", "group", NULL};
4148aee7f3SJoerg Wunsch static const char *Combo1[] = {
4248aee7f3SJoerg Wunsch   "useradd", "userdel", "usermod", "usershow", "usernext",
4348aee7f3SJoerg Wunsch   "groupadd", "groupdel", "groupmod", "groupshow", "groupnext",
44d6f907dcSJoerg Wunsch   NULL};
4548aee7f3SJoerg Wunsch static const char *Combo2[] = {
4648aee7f3SJoerg Wunsch   "adduser", "deluser", "moduser", "showuser", "nextuser",
4748aee7f3SJoerg Wunsch   "addgroup", "delgroup", "modgroup", "showgroup", "nextgroup",
48d6f907dcSJoerg Wunsch NULL};
49d6f907dcSJoerg Wunsch 
50d6f907dcSJoerg Wunsch static struct cargs arglist;
51d6f907dcSJoerg Wunsch 
52d6f907dcSJoerg Wunsch static int      getindex(const char *words[], const char *word);
53d6f907dcSJoerg Wunsch static void     cmdhelp(int mode, int which);
54d6f907dcSJoerg Wunsch 
55d6f907dcSJoerg Wunsch 
56d6f907dcSJoerg Wunsch int
57d6f907dcSJoerg Wunsch main(int argc, char *argv[])
58d6f907dcSJoerg Wunsch {
59d6f907dcSJoerg Wunsch 	int             ch;
60d6f907dcSJoerg Wunsch 	int             mode = -1;
61d6f907dcSJoerg Wunsch 	int             which = -1;
62d6f907dcSJoerg Wunsch 	struct userconf *cnf;
63d6f907dcSJoerg Wunsch 
64d6f907dcSJoerg Wunsch 	static const char *opts[W_NUM][M_NUM] =
65d6f907dcSJoerg Wunsch 	{
6648aee7f3SJoerg Wunsch 		{ /* user */
6748aee7f3SJoerg Wunsch 			"C:qn:u:c:d:e:p:g:G:mk:s:oL:i:w:h:Db:NP",
6848aee7f3SJoerg Wunsch 			"C:qn:u:r",
6948aee7f3SJoerg Wunsch 			"C:qn:u:c:d:e:p:g:G:mk:s:w:L:h:FNP",
7048aee7f3SJoerg Wunsch 			"C:qn:u:FPa",
7148aee7f3SJoerg Wunsch 			"C:q"
7248aee7f3SJoerg Wunsch 		},
7348aee7f3SJoerg Wunsch 		{ /* grp  */
7448aee7f3SJoerg Wunsch 			"C:qn:g:h:M:pNP",
7548aee7f3SJoerg Wunsch 			"C:qn:g:",
7648aee7f3SJoerg Wunsch 			"C:qn:g:l:h:FM:m:NP",
7748aee7f3SJoerg Wunsch 			"C:qn:g:FPa",
7848aee7f3SJoerg Wunsch 			"C:q"
7948aee7f3SJoerg Wunsch 		 }
80d6f907dcSJoerg Wunsch 	};
81d6f907dcSJoerg Wunsch 
82d6f907dcSJoerg Wunsch 	static int      (*funcs[W_NUM]) (struct userconf * _cnf, int _mode, struct cargs * _args) =
83d6f907dcSJoerg Wunsch 	{			/* Request handlers */
84d6f907dcSJoerg Wunsch 		pw_user,
85d6f907dcSJoerg Wunsch 		pw_group
86d6f907dcSJoerg Wunsch 	};
87d6f907dcSJoerg Wunsch 
88d6f907dcSJoerg Wunsch 	umask(0);		/* We wish to handle this manually */
89d6f907dcSJoerg Wunsch 	progname = strrchr(argv[0], '/');
90d6f907dcSJoerg Wunsch 	if (progname != NULL)
91d6f907dcSJoerg Wunsch 		++progname;
92d6f907dcSJoerg Wunsch 	else
93d6f907dcSJoerg Wunsch 		progname = argv[0];
94d6f907dcSJoerg Wunsch 
95d6f907dcSJoerg Wunsch 	LIST_INIT(&arglist);
96d6f907dcSJoerg Wunsch 
97d6f907dcSJoerg Wunsch 	/*
98d6f907dcSJoerg Wunsch 	 * Break off the first couple of words to determine what exactly
99d6f907dcSJoerg Wunsch 	 * we're being asked to do
100d6f907dcSJoerg Wunsch 	 */
101d6f907dcSJoerg Wunsch 	while (argc > 1 && *argv[1] != '-') {
102d6f907dcSJoerg Wunsch 		int             tmp;
103d6f907dcSJoerg Wunsch 
104d6f907dcSJoerg Wunsch 		if ((tmp = getindex(Modes, argv[1])) != -1)
105d6f907dcSJoerg Wunsch 			mode = tmp;
106d6f907dcSJoerg Wunsch 		else if ((tmp = getindex(Which, argv[1])) != -1)
107d6f907dcSJoerg Wunsch 			which = tmp;
108d6f907dcSJoerg Wunsch 		else if ((tmp = getindex(Combo1, argv[1])) != -1 || (tmp = getindex(Combo2, argv[1])) != -1) {
109d6f907dcSJoerg Wunsch 			which = tmp / M_NUM;
110d6f907dcSJoerg Wunsch 			mode = tmp % M_NUM;
111d6f907dcSJoerg Wunsch 		} else if (strcmp(argv[1], "help") == 0)
112d6f907dcSJoerg Wunsch 			cmdhelp(mode, which);
113d6f907dcSJoerg Wunsch 		else if (which != -1 && mode != -1 && arglist.lh_first == NULL)
114d6f907dcSJoerg Wunsch 			addarg(&arglist, 'n', argv[1]);
115d6f907dcSJoerg Wunsch 		else
11648aee7f3SJoerg Wunsch 			cmderr(EX_USAGE, "Unknown keyword `%s'\n", argv[1]);
117d6f907dcSJoerg Wunsch 		++argv;
118d6f907dcSJoerg Wunsch 		--argc;
119d6f907dcSJoerg Wunsch 	}
120d6f907dcSJoerg Wunsch 
121d6f907dcSJoerg Wunsch 	/*
122d6f907dcSJoerg Wunsch 	 * Bail out unless the user is specific!
123d6f907dcSJoerg Wunsch 	 */
124d6f907dcSJoerg Wunsch 	if (mode == -1 || which == -1)
125d6f907dcSJoerg Wunsch 		cmdhelp(mode, which);
126d6f907dcSJoerg Wunsch 
127d6f907dcSJoerg Wunsch 	/*
128d6f907dcSJoerg Wunsch 	 * We know which mode we're in and what we're about to do, so now
129d6f907dcSJoerg Wunsch 	 * let's dispatch the remaining command line args in a genric way.
130d6f907dcSJoerg Wunsch 	 */
131d6f907dcSJoerg Wunsch 	argv[0] = progname;	/* Preserve this */
132d6f907dcSJoerg Wunsch 	optarg = NULL;
133d6f907dcSJoerg Wunsch 
134d6f907dcSJoerg Wunsch 	while ((ch = getopt(argc, argv, opts[which][mode])) != -1) {
135d6f907dcSJoerg Wunsch 		if (ch == '?')
13648aee7f3SJoerg Wunsch 			cmderr(EX_USAGE, NULL);
137d6f907dcSJoerg Wunsch 		else
138d6f907dcSJoerg Wunsch 			addarg(&arglist, ch, optarg);
139d6f907dcSJoerg Wunsch 		optarg = NULL;
140d6f907dcSJoerg Wunsch 	}
141d6f907dcSJoerg Wunsch 
142d6f907dcSJoerg Wunsch 	/*
14348aee7f3SJoerg Wunsch 	 * Must be root to attempt an update
14448aee7f3SJoerg Wunsch 	 */
14548aee7f3SJoerg Wunsch 	if (getuid() != 0 && mode != M_PRINT && mode != M_NEXT && getarg(&arglist, 'N')==NULL)
14648aee7f3SJoerg Wunsch 		cmderr(EX_NOPERM, "you must be root to run this program\n");
14748aee7f3SJoerg Wunsch 
14848aee7f3SJoerg Wunsch 	/*
149d6f907dcSJoerg Wunsch 	 * We should immediately look for the -q 'quiet' switch so that we
150d6f907dcSJoerg Wunsch 	 * don't bother with extraneous errors
151d6f907dcSJoerg Wunsch 	 */
152d6f907dcSJoerg Wunsch 	if (getarg(&arglist, 'q') != NULL)
153d6f907dcSJoerg Wunsch 		freopen("/dev/null", "w", stderr);
154d6f907dcSJoerg Wunsch 
155d6f907dcSJoerg Wunsch 	/*
156d6f907dcSJoerg Wunsch 	 * Now, let's do the common initialisation
157d6f907dcSJoerg Wunsch 	 */
158d6f907dcSJoerg Wunsch 	cnf = read_userconfig(getarg(&arglist, 'C') ? getarg(&arglist, 'C')->val : NULL);
15948aee7f3SJoerg Wunsch 	return funcs[which] (cnf, mode, &arglist);
160d6f907dcSJoerg Wunsch }
161d6f907dcSJoerg Wunsch 
162d6f907dcSJoerg Wunsch static int
163d6f907dcSJoerg Wunsch getindex(const char *words[], const char *word)
164d6f907dcSJoerg Wunsch {
165d6f907dcSJoerg Wunsch 	int             i = 0;
166d6f907dcSJoerg Wunsch 
167d6f907dcSJoerg Wunsch 	while (words[i]) {
168d6f907dcSJoerg Wunsch 		if (strcmp(words[i], word) == 0)
169d6f907dcSJoerg Wunsch 			return i;
170d6f907dcSJoerg Wunsch 		i++;
171d6f907dcSJoerg Wunsch 	}
172d6f907dcSJoerg Wunsch 	return -1;
173d6f907dcSJoerg Wunsch }
174d6f907dcSJoerg Wunsch 
175d6f907dcSJoerg Wunsch 
176d6f907dcSJoerg Wunsch /*
177d6f907dcSJoerg Wunsch  * This is probably an overkill for a cmdline help system, but it reflects
178d6f907dcSJoerg Wunsch  * the complexity of the command line.
179d6f907dcSJoerg Wunsch  */
180d6f907dcSJoerg Wunsch 
181d6f907dcSJoerg Wunsch static void
182d6f907dcSJoerg Wunsch banner(void)
183d6f907dcSJoerg Wunsch {
184d6f907dcSJoerg Wunsch 	fprintf(stderr, "%s: ", progname);
185d6f907dcSJoerg Wunsch }
186d6f907dcSJoerg Wunsch 
187d6f907dcSJoerg Wunsch void
188d6f907dcSJoerg Wunsch cmderr(int ec, char const * fmt,...)
189d6f907dcSJoerg Wunsch {
190d6f907dcSJoerg Wunsch 	if (fmt != NULL) {
191d6f907dcSJoerg Wunsch 		va_list         argp;
192d6f907dcSJoerg Wunsch 
193d6f907dcSJoerg Wunsch 		banner();
194d6f907dcSJoerg Wunsch 		va_start(argp, fmt);
195d6f907dcSJoerg Wunsch 		vfprintf(stderr, fmt, argp);
196d6f907dcSJoerg Wunsch 		va_end(argp);
197d6f907dcSJoerg Wunsch 	}
198d6f907dcSJoerg Wunsch 	exit(ec);
199d6f907dcSJoerg Wunsch }
200d6f907dcSJoerg Wunsch 
201d6f907dcSJoerg Wunsch static void
202d6f907dcSJoerg Wunsch cmdhelp(int mode, int which)
203d6f907dcSJoerg Wunsch {
204d6f907dcSJoerg Wunsch 	banner();
205d6f907dcSJoerg Wunsch 	if (which == -1)
20648aee7f3SJoerg Wunsch 		fprintf(stderr, "usage: %s [user|group] [add|del|mod|show|next] [ help | switches/values ]\n", progname);
207d6f907dcSJoerg Wunsch 	else if (mode == -1)
20848aee7f3SJoerg Wunsch 		fprintf(stderr, "usage: %s %s [add|del|mod|show|next] [ help | switches/values ]\n", progname, Which[which]);
209d6f907dcSJoerg Wunsch 	else {
210d6f907dcSJoerg Wunsch 
211d6f907dcSJoerg Wunsch 		/*
212d6f907dcSJoerg Wunsch 		 * We need to give mode specific help
213d6f907dcSJoerg Wunsch 		 */
214d6f907dcSJoerg Wunsch 		static const char *help[W_NUM][M_NUM] =
215d6f907dcSJoerg Wunsch 		{
216d6f907dcSJoerg Wunsch 			{
217d6f907dcSJoerg Wunsch 				"usage: %s useradd [name] [switches]\n"
218d6f907dcSJoerg Wunsch 				"\t-C config      configuration file\n"
219d6f907dcSJoerg Wunsch 				"\t-q             quiet operation\n"
220d6f907dcSJoerg Wunsch 				"  Adding users:\n"
221d6f907dcSJoerg Wunsch 				"\t-n name        login name\n"
222d6f907dcSJoerg Wunsch 				"\t-u uid         user id\n"
223d6f907dcSJoerg Wunsch 				"\t-c comment     user name/comment\n"
224d6f907dcSJoerg Wunsch 				"\t-d directory   home directory\n"
225d6f907dcSJoerg Wunsch 				"\t-e date        account expiry date\n"
226d6f907dcSJoerg Wunsch 				"\t-p date        password expiry date\n"
227d6f907dcSJoerg Wunsch 				"\t-g grp         initial group\n"
228d6f907dcSJoerg Wunsch 				"\t-G grp1,grp2   additional groups\n"
229d6f907dcSJoerg Wunsch 				"\t-m [ -k dir ]  create and set up home\n"
230d6f907dcSJoerg Wunsch 				"\t-s shell       name of login shell\n"
231d6f907dcSJoerg Wunsch 				"\t-o             duplicate uid ok\n"
232d6f907dcSJoerg Wunsch 				"\t-L class       user class\n"
233d6f907dcSJoerg Wunsch 				"\t-h fd          read password on fd\n"
23448aee7f3SJoerg Wunsch 				"\t-N             no update\n"
235d6f907dcSJoerg Wunsch 				"  Setting defaults:\n"
236d6f907dcSJoerg Wunsch 				"\t-D             set user defaults\n"
237d6f907dcSJoerg Wunsch 				"\t-b dir         default home root dir\n"
238d6f907dcSJoerg Wunsch 				"\t-e period      default expiry period\n"
239d6f907dcSJoerg Wunsch 				"\t-p period      default password change period\n"
240d6f907dcSJoerg Wunsch 				"\t-g group       default group\n"
241d6f907dcSJoerg Wunsch 				"\t-G grp1,grp2   additional groups\n"
242d6f907dcSJoerg Wunsch 				"\t-L class       default user class\n"
243d6f907dcSJoerg Wunsch 				"\t-k dir         default home skeleton\n"
244d6f907dcSJoerg Wunsch 				"\t-u min,max     set min,max uids\n"
245d6f907dcSJoerg Wunsch 				"\t-i min,max     set min,max gids\n"
246d6f907dcSJoerg Wunsch 				"\t-w method      set default password method\n"
247d6f907dcSJoerg Wunsch 				"\t-s shell       default shell\n",
248d6f907dcSJoerg Wunsch 				"usage: %s userdel [uid|name] [switches]\n"
249d6f907dcSJoerg Wunsch 				"\t-n name        login name\n"
250d6f907dcSJoerg Wunsch 				"\t-u uid         user id\n"
251d6f907dcSJoerg Wunsch 				"\t-r             remove home & contents\n",
252d6f907dcSJoerg Wunsch 				"usage: %s usermod [uid|name] [switches]\n"
253d6f907dcSJoerg Wunsch 				"\t-C config      configuration file\n"
254d6f907dcSJoerg Wunsch 				"\t-q             quiet operation\n"
255d6f907dcSJoerg Wunsch 				"\t-F             force add if no user\n"
256d6f907dcSJoerg Wunsch 				"\t-n name        login name\n"
257d6f907dcSJoerg Wunsch 				"\t-u uid         user id\n"
258d6f907dcSJoerg Wunsch 				"\t-c comment     user name/comment\n"
259d6f907dcSJoerg Wunsch 				"\t-d directory   home directory\n"
260d6f907dcSJoerg Wunsch 				"\t-e date        account expiry date\n"
261d6f907dcSJoerg Wunsch 				"\t-p date        password expiry date\n"
262d6f907dcSJoerg Wunsch 				"\t-g grp         initial group\n"
263d6f907dcSJoerg Wunsch 				"\t-G grp1,grp2   additional groups\n"
264d6f907dcSJoerg Wunsch 				"\t-l name        new login name\n"
265d6f907dcSJoerg Wunsch 				"\t-L class       user class\n"
266d6f907dcSJoerg Wunsch 				"\t-m [ -k dir ]  create and set up home\n"
267d6f907dcSJoerg Wunsch 				"\t-s shell       name of login shell\n"
26848aee7f3SJoerg Wunsch 				"\t-w method      set new password using method\n"
26948aee7f3SJoerg Wunsch 				"\t-h fd          read password on fd\n"
27048aee7f3SJoerg Wunsch 				"\t-N             no update\n",
271d6f907dcSJoerg Wunsch 				"usage: %s usershow [uid|name] [switches]\n"
272d6f907dcSJoerg Wunsch 				"\t-n name        login name\n"
273d6f907dcSJoerg Wunsch 				"\t-u uid         user id\n"
274d6f907dcSJoerg Wunsch 				"\t-F             force print\n"
27548aee7f3SJoerg Wunsch 				"\t-P             prettier format\n"
27648aee7f3SJoerg Wunsch 				"\t-a             print all users\n",
27748aee7f3SJoerg Wunsch 				"usage: %s usernext [switches]\n"
27848aee7f3SJoerg Wunsch 				"\t-C config      configuration file\n"
279d6f907dcSJoerg Wunsch 			},
280d6f907dcSJoerg Wunsch 			{
281d6f907dcSJoerg Wunsch 				"usage: %s groupadd [group|gid] [switches]\n"
282d6f907dcSJoerg Wunsch 				"\t-C config      configuration file\n"
283d6f907dcSJoerg Wunsch 				"\t-q             quiet operation\n"
284d6f907dcSJoerg Wunsch 				"\t-n group       group name\n"
285d6f907dcSJoerg Wunsch 				"\t-g gid         group id\n"
28648aee7f3SJoerg Wunsch 				"\t-M usr1,usr2   add users as group members\n"
28748aee7f3SJoerg Wunsch 				"\t-o             duplicate gid ok\n"
28848aee7f3SJoerg Wunsch 				"\t-N             no update\n",
289d6f907dcSJoerg Wunsch 				"usage: %s groupdel [group|gid] [switches]\n"
290d6f907dcSJoerg Wunsch 				"\t-n name        group name\n"
291d6f907dcSJoerg Wunsch 				"\t-g gid         group id\n",
292d6f907dcSJoerg Wunsch 				"usage: %s groupmod [group|gid] [switches]\n"
293d6f907dcSJoerg Wunsch 				"\t-C config      configuration file\n"
294d6f907dcSJoerg Wunsch 				"\t-q             quiet operation\n"
295d6f907dcSJoerg Wunsch 				"\t-F             force add if not exists\n"
296d6f907dcSJoerg Wunsch 				"\t-n name        group name\n"
297d6f907dcSJoerg Wunsch 				"\t-g gid         group id\n"
29848aee7f3SJoerg Wunsch 				"\t-M usr1,usr2   replaces users as group members\n"
29948aee7f3SJoerg Wunsch 				"\t-m usr1,usr2   add users as group members\n"
30048aee7f3SJoerg Wunsch 				"\t-l name        new group name\n"
30148aee7f3SJoerg Wunsch 				"\t-N             no update\n",
302d6f907dcSJoerg Wunsch 				"usage: %s groupshow [group|gid] [switches]\n"
303d6f907dcSJoerg Wunsch 				"\t-n name        group name\n"
304d6f907dcSJoerg Wunsch 				"\t-g gid         group id\n"
305d6f907dcSJoerg Wunsch 				"\t-F             force print\n"
30648aee7f3SJoerg Wunsch 				"\t-P             prettier format\n"
30748aee7f3SJoerg Wunsch 				"\t-a             print all accounting groups\n",
30848aee7f3SJoerg Wunsch 				"usage: %s groupnext [switches]\n"
30948aee7f3SJoerg Wunsch 				"\t-C config      configuration file\n"
310d6f907dcSJoerg Wunsch 			}
311d6f907dcSJoerg Wunsch 		};
312d6f907dcSJoerg Wunsch 
313d6f907dcSJoerg Wunsch 		fprintf(stderr, help[which][mode], progname);
314d6f907dcSJoerg Wunsch 	}
31548aee7f3SJoerg Wunsch 	exit(EXIT_FAILURE);
316d6f907dcSJoerg Wunsch }
317d6f907dcSJoerg Wunsch 
318d6f907dcSJoerg Wunsch struct carg    *
319d6f907dcSJoerg Wunsch getarg(struct cargs * _args, int ch)
320d6f907dcSJoerg Wunsch {
321d6f907dcSJoerg Wunsch 	struct carg    *c = _args->lh_first;
322d6f907dcSJoerg Wunsch 
323d6f907dcSJoerg Wunsch 	while (c != NULL && c->ch != ch)
324d6f907dcSJoerg Wunsch 		c = c->list.le_next;
325d6f907dcSJoerg Wunsch 	return c;
326d6f907dcSJoerg Wunsch }
327d6f907dcSJoerg Wunsch 
328d6f907dcSJoerg Wunsch struct carg    *
329d6f907dcSJoerg Wunsch addarg(struct cargs * _args, int ch, char *argstr)
330d6f907dcSJoerg Wunsch {
331d6f907dcSJoerg Wunsch 	struct carg    *ca = malloc(sizeof(struct carg));
332d6f907dcSJoerg Wunsch 
333d6f907dcSJoerg Wunsch 	if (ca == NULL)
33448aee7f3SJoerg Wunsch 		cmderr(EX_OSERR, "Abort - out of memory\n");
335d6f907dcSJoerg Wunsch 	ca->ch = ch;
336d6f907dcSJoerg Wunsch 	ca->val = argstr;
337d6f907dcSJoerg Wunsch 	LIST_INSERT_HEAD(_args, ca, list);
338d6f907dcSJoerg Wunsch 	return ca;
339d6f907dcSJoerg Wunsch }
340