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[] = 29e3921b27SDavid Nugent "$Id: pw.c,v 1.12 1999/02/23 07:15:10 davidn Exp $"; 301dcc6ec7SPhilippe Charnier #endif /* not lint */ 311dcc6ec7SPhilippe Charnier 321dcc6ec7SPhilippe Charnier #include <err.h> 335e91a8acSNate Williams #include <fcntl.h> 34f1d684faSDavid Nugent #include <paths.h> 35f1d684faSDavid Nugent #include <sys/wait.h> 365f12594aSDavid Nugent #include "pw.h" 37d6f907dcSJoerg Wunsch 3848aee7f3SJoerg Wunsch const char *Modes[] = {"add", "del", "mod", "show", "next", NULL}; 39d6f907dcSJoerg Wunsch const char *Which[] = {"user", "group", NULL}; 4048aee7f3SJoerg Wunsch static const char *Combo1[] = { 4148aee7f3SJoerg Wunsch "useradd", "userdel", "usermod", "usershow", "usernext", 4248aee7f3SJoerg Wunsch "groupadd", "groupdel", "groupmod", "groupshow", "groupnext", 43d6f907dcSJoerg Wunsch NULL}; 4448aee7f3SJoerg Wunsch static const char *Combo2[] = { 4548aee7f3SJoerg Wunsch "adduser", "deluser", "moduser", "showuser", "nextuser", 4648aee7f3SJoerg Wunsch "addgroup", "delgroup", "modgroup", "showgroup", "nextgroup", 47d6f907dcSJoerg Wunsch NULL}; 48d6f907dcSJoerg Wunsch 495f12594aSDavid Nugent struct pwf PWF = 505f12594aSDavid Nugent { 515f12594aSDavid Nugent 0, 525f12594aSDavid Nugent setpwent, 535f12594aSDavid Nugent endpwent, 545f12594aSDavid Nugent getpwent, 555f12594aSDavid Nugent getpwuid, 565f12594aSDavid Nugent getpwnam, 575f12594aSDavid Nugent pwdb, 585f12594aSDavid Nugent setgrent, 595f12594aSDavid Nugent endgrent, 605f12594aSDavid Nugent getgrent, 615f12594aSDavid Nugent getgrgid, 625f12594aSDavid Nugent getgrnam, 635f12594aSDavid Nugent grdb 645f12594aSDavid Nugent 655f12594aSDavid Nugent }; 665f12594aSDavid Nugent struct pwf VPWF = 675f12594aSDavid Nugent { 685f12594aSDavid Nugent 1, 695f12594aSDavid Nugent vsetpwent, 705f12594aSDavid Nugent vendpwent, 715f12594aSDavid Nugent vgetpwent, 725f12594aSDavid Nugent vgetpwuid, 735f12594aSDavid Nugent vgetpwnam, 745f12594aSDavid Nugent vpwdb, 755f12594aSDavid Nugent vsetgrent, 765f12594aSDavid Nugent vendgrent, 775f12594aSDavid Nugent vgetgrent, 785f12594aSDavid Nugent vgetgrgid, 795f12594aSDavid Nugent vgetgrnam, 805f12594aSDavid Nugent vgrdb 815f12594aSDavid Nugent }; 825f12594aSDavid Nugent 83d6f907dcSJoerg Wunsch static struct cargs arglist; 84d6f907dcSJoerg Wunsch 85d6f907dcSJoerg Wunsch static int getindex(const char *words[], const char *word); 86d6f907dcSJoerg Wunsch static void cmdhelp(int mode, int which); 87d6f907dcSJoerg Wunsch 88d6f907dcSJoerg Wunsch 89d6f907dcSJoerg Wunsch int 90d6f907dcSJoerg Wunsch main(int argc, char *argv[]) 91d6f907dcSJoerg Wunsch { 92d6f907dcSJoerg Wunsch int ch; 93d6f907dcSJoerg Wunsch int mode = -1; 94d6f907dcSJoerg Wunsch int which = -1; 955f12594aSDavid Nugent char *config = NULL; 96d6f907dcSJoerg Wunsch struct userconf *cnf; 97d6f907dcSJoerg Wunsch 98d6f907dcSJoerg Wunsch static const char *opts[W_NUM][M_NUM] = 99d6f907dcSJoerg Wunsch { 10048aee7f3SJoerg Wunsch { /* user */ 101e3921b27SDavid Nugent "V:C:qn:u:c:d:e:p:g:G:mk:s:oL:i:w:h:Db:NPy:Y", 102e3921b27SDavid Nugent "V:C:qn:u:rY", 103e3921b27SDavid Nugent "V:C:qn:u:c:d:e:p:g:G:ml:k:s:w:L:h:FNPY", 104e3921b27SDavid Nugent "V:C:qn:u:FPa", 105e3921b27SDavid Nugent "V:C:q" 10648aee7f3SJoerg Wunsch }, 10748aee7f3SJoerg Wunsch { /* grp */ 108e3921b27SDavid Nugent "V:C:qn:g:h:M:pNPY", 109e3921b27SDavid Nugent "V:C:qn:g:Y", 110e3921b27SDavid Nugent "V:C:qn:g:l:h:FM:m:NPY", 111e3921b27SDavid Nugent "V:C:qn:g:FPa", 112e3921b27SDavid Nugent "V:C:q" 11348aee7f3SJoerg Wunsch } 114d6f907dcSJoerg Wunsch }; 115d6f907dcSJoerg Wunsch 116d6f907dcSJoerg Wunsch static int (*funcs[W_NUM]) (struct userconf * _cnf, int _mode, struct cargs * _args) = 117d6f907dcSJoerg Wunsch { /* Request handlers */ 118d6f907dcSJoerg Wunsch pw_user, 119d6f907dcSJoerg Wunsch pw_group 120d6f907dcSJoerg Wunsch }; 121d6f907dcSJoerg Wunsch 122d6f907dcSJoerg Wunsch umask(0); /* We wish to handle this manually */ 123d6f907dcSJoerg Wunsch LIST_INIT(&arglist); 124d6f907dcSJoerg Wunsch 125d6f907dcSJoerg Wunsch /* 126d6f907dcSJoerg Wunsch * Break off the first couple of words to determine what exactly 127d6f907dcSJoerg Wunsch * we're being asked to do 128d6f907dcSJoerg Wunsch */ 1295f12594aSDavid Nugent while (argc > 1) { 130d6f907dcSJoerg Wunsch int tmp; 131d6f907dcSJoerg Wunsch 1325f12594aSDavid Nugent if (*argv[1] == '-') { 1335f12594aSDavid Nugent /* 1345f12594aSDavid Nugent * Special case, allow pw -V<dir> <operation> [args] for scripts etc. 1355f12594aSDavid Nugent */ 1365f12594aSDavid Nugent if (argv[1][1] == 'V') { 1375f12594aSDavid Nugent optarg = &argv[1][2]; 1385f12594aSDavid Nugent if (*optarg == '\0') { 1395f12594aSDavid Nugent optarg = argv[2]; 1405f12594aSDavid Nugent ++argv; 1415f12594aSDavid Nugent --argc; 1425f12594aSDavid Nugent } 1435f12594aSDavid Nugent addarg(&arglist, 'V', optarg); 144e3921b27SDavid Nugent } else 1455f12594aSDavid Nugent break; 1465f12594aSDavid Nugent } 1475f12594aSDavid Nugent else if ((tmp = getindex(Modes, argv[1])) != -1) 148d6f907dcSJoerg Wunsch mode = tmp; 149d6f907dcSJoerg Wunsch else if ((tmp = getindex(Which, argv[1])) != -1) 150d6f907dcSJoerg Wunsch which = tmp; 151d6f907dcSJoerg Wunsch else if ((tmp = getindex(Combo1, argv[1])) != -1 || (tmp = getindex(Combo2, argv[1])) != -1) { 152d6f907dcSJoerg Wunsch which = tmp / M_NUM; 153d6f907dcSJoerg Wunsch mode = tmp % M_NUM; 154d6f907dcSJoerg Wunsch } else if (strcmp(argv[1], "help") == 0) 155d6f907dcSJoerg Wunsch cmdhelp(mode, which); 156d6f907dcSJoerg Wunsch else if (which != -1 && mode != -1 && arglist.lh_first == NULL) 157d6f907dcSJoerg Wunsch addarg(&arglist, 'n', argv[1]); 158d6f907dcSJoerg Wunsch else 1591dcc6ec7SPhilippe Charnier errx(EX_USAGE, "unknown keyword `%s'", argv[1]); 160d6f907dcSJoerg Wunsch ++argv; 161d6f907dcSJoerg Wunsch --argc; 162d6f907dcSJoerg Wunsch } 163d6f907dcSJoerg Wunsch 164d6f907dcSJoerg Wunsch /* 165d6f907dcSJoerg Wunsch * Bail out unless the user is specific! 166d6f907dcSJoerg Wunsch */ 167d6f907dcSJoerg Wunsch if (mode == -1 || which == -1) 168d6f907dcSJoerg Wunsch cmdhelp(mode, which); 169d6f907dcSJoerg Wunsch 170d6f907dcSJoerg Wunsch /* 171d6f907dcSJoerg Wunsch * We know which mode we're in and what we're about to do, so now 172d6f907dcSJoerg Wunsch * let's dispatch the remaining command line args in a genric way. 173d6f907dcSJoerg Wunsch */ 174d6f907dcSJoerg Wunsch optarg = NULL; 175d6f907dcSJoerg Wunsch 176d6f907dcSJoerg Wunsch while ((ch = getopt(argc, argv, opts[which][mode])) != -1) { 177d6f907dcSJoerg Wunsch if (ch == '?') 1781dcc6ec7SPhilippe Charnier errx(EX_USAGE, NULL); 179d6f907dcSJoerg Wunsch else 180d6f907dcSJoerg Wunsch addarg(&arglist, ch, optarg); 181d6f907dcSJoerg Wunsch optarg = NULL; 182d6f907dcSJoerg Wunsch } 183d6f907dcSJoerg Wunsch 184d6f907dcSJoerg Wunsch /* 18548aee7f3SJoerg Wunsch * Must be root to attempt an update 18648aee7f3SJoerg Wunsch */ 187fa7e83d4SDavid Nugent if (geteuid() != 0 && mode != M_PRINT && mode != M_NEXT && getarg(&arglist, 'N')==NULL) 1881dcc6ec7SPhilippe Charnier errx(EX_NOPERM, "you must be root to run this program"); 18948aee7f3SJoerg Wunsch 19048aee7f3SJoerg Wunsch /* 191d6f907dcSJoerg Wunsch * We should immediately look for the -q 'quiet' switch so that we 192d6f907dcSJoerg Wunsch * don't bother with extraneous errors 193d6f907dcSJoerg Wunsch */ 194d6f907dcSJoerg Wunsch if (getarg(&arglist, 'q') != NULL) 195d6f907dcSJoerg Wunsch freopen("/dev/null", "w", stderr); 196d6f907dcSJoerg Wunsch 197d6f907dcSJoerg Wunsch /* 1985f12594aSDavid Nugent * Set our base working path if not overridden 1995f12594aSDavid Nugent */ 2005f12594aSDavid Nugent 2015f12594aSDavid Nugent config = getarg(&arglist, 'C') ? getarg(&arglist, 'C')->val : NULL; 2025f12594aSDavid Nugent 2035f12594aSDavid Nugent if (getarg(&arglist, 'V') != NULL) { 2045f12594aSDavid Nugent char * etcpath = getarg(&arglist, 'V')->val; 2055f12594aSDavid Nugent if (*etcpath) { 2065f12594aSDavid Nugent if (config == NULL) { /* Only override config location if -C not specified */ 2075f12594aSDavid Nugent config = malloc(MAXPATHLEN); 2085f12594aSDavid Nugent snprintf(config, MAXPATHLEN, "%s/pw.conf", etcpath); 2095f12594aSDavid Nugent } 2105f12594aSDavid Nugent memcpy(&PWF, &VPWF, sizeof PWF); 2115f12594aSDavid Nugent setpwdir(etcpath); 2125f12594aSDavid Nugent setgrdir(etcpath); 2135f12594aSDavid Nugent } 2145f12594aSDavid Nugent } 2155f12594aSDavid Nugent 2165f12594aSDavid Nugent /* 217d6f907dcSJoerg Wunsch * Now, let's do the common initialisation 218d6f907dcSJoerg Wunsch */ 2195f12594aSDavid Nugent cnf = read_userconfig(config); 2205e91a8acSNate Williams 221f1d684faSDavid Nugent ch = funcs[which] (cnf, mode, &arglist); 222f1d684faSDavid Nugent 223f1d684faSDavid Nugent /* 224f1d684faSDavid Nugent * If everything went ok, and we've been asked to update 225f1d684faSDavid Nugent * the NIS maps, then do it now 226f1d684faSDavid Nugent */ 227f1d684faSDavid Nugent if (ch == EXIT_SUCCESS && getarg(&arglist, 'Y') != NULL) { 228f1d684faSDavid Nugent pid_t pid; 229f1d684faSDavid Nugent 230f1d684faSDavid Nugent fflush(NULL); 231f1d684faSDavid Nugent if (chdir(_PATH_YP) == -1) 2321dcc6ec7SPhilippe Charnier warn("chdir(" _PATH_YP ")"); 233f1d684faSDavid Nugent else if ((pid = fork()) == -1) 2341dcc6ec7SPhilippe Charnier warn("fork()"); 235f1d684faSDavid Nugent else if (pid == 0) { 236f1d684faSDavid Nugent /* Is make anywhere else? */ 237f1d684faSDavid Nugent execlp("/usr/bin/make", "make", NULL); 238f1d684faSDavid Nugent _exit(1); 239f1d684faSDavid Nugent } else { 240f1d684faSDavid Nugent int i; 241f1d684faSDavid Nugent waitpid(pid, &i, 0); 242f1d684faSDavid Nugent if ((i = WEXITSTATUS(i)) != 0) 2431dcc6ec7SPhilippe Charnier errx(ch, "make exited with status %d", i); 244f1d684faSDavid Nugent else 245f1d684faSDavid Nugent pw_log(cnf, mode, which, "NIS maps updated"); 246f1d684faSDavid Nugent } 247f1d684faSDavid Nugent } 248f1d684faSDavid Nugent return ch; 249d6f907dcSJoerg Wunsch } 250d6f907dcSJoerg Wunsch 2515e91a8acSNate Williams 252d6f907dcSJoerg Wunsch static int 253d6f907dcSJoerg Wunsch getindex(const char *words[], const char *word) 254d6f907dcSJoerg Wunsch { 255d6f907dcSJoerg Wunsch int i = 0; 256d6f907dcSJoerg Wunsch 257d6f907dcSJoerg Wunsch while (words[i]) { 258d6f907dcSJoerg Wunsch if (strcmp(words[i], word) == 0) 259d6f907dcSJoerg Wunsch return i; 260d6f907dcSJoerg Wunsch i++; 261d6f907dcSJoerg Wunsch } 262d6f907dcSJoerg Wunsch return -1; 263d6f907dcSJoerg Wunsch } 264d6f907dcSJoerg Wunsch 265d6f907dcSJoerg Wunsch 266d6f907dcSJoerg Wunsch /* 267d6f907dcSJoerg Wunsch * This is probably an overkill for a cmdline help system, but it reflects 268d6f907dcSJoerg Wunsch * the complexity of the command line. 269d6f907dcSJoerg Wunsch */ 270d6f907dcSJoerg Wunsch 271d6f907dcSJoerg Wunsch static void 272d6f907dcSJoerg Wunsch cmdhelp(int mode, int which) 273d6f907dcSJoerg Wunsch { 274d6f907dcSJoerg Wunsch if (which == -1) 2751dcc6ec7SPhilippe Charnier fprintf(stderr, "usage: pw [user|group] [add|del|mod|show|next] [ help | switches/values ]\n"); 276d6f907dcSJoerg Wunsch else if (mode == -1) 2771dcc6ec7SPhilippe Charnier fprintf(stderr, "usage: pw %s [add|del|mod|show|next] [ help | switches/values ]\n", Which[which]); 278d6f907dcSJoerg Wunsch else { 279d6f907dcSJoerg Wunsch 280d6f907dcSJoerg Wunsch /* 281d6f907dcSJoerg Wunsch * We need to give mode specific help 282d6f907dcSJoerg Wunsch */ 283d6f907dcSJoerg Wunsch static const char *help[W_NUM][M_NUM] = 284d6f907dcSJoerg Wunsch { 285d6f907dcSJoerg Wunsch { 2861dcc6ec7SPhilippe Charnier "usage: pw useradd [name] [switches]\n" 2875f12594aSDavid Nugent "\t-V etcdir alternate /etc location\n" 288d6f907dcSJoerg Wunsch "\t-C config configuration file\n" 289d6f907dcSJoerg Wunsch "\t-q quiet operation\n" 290d6f907dcSJoerg Wunsch " Adding users:\n" 291d6f907dcSJoerg Wunsch "\t-n name login name\n" 292d6f907dcSJoerg Wunsch "\t-u uid user id\n" 293d6f907dcSJoerg Wunsch "\t-c comment user name/comment\n" 294d6f907dcSJoerg Wunsch "\t-d directory home directory\n" 295d6f907dcSJoerg Wunsch "\t-e date account expiry date\n" 296d6f907dcSJoerg Wunsch "\t-p date password expiry date\n" 297d6f907dcSJoerg Wunsch "\t-g grp initial group\n" 298d6f907dcSJoerg Wunsch "\t-G grp1,grp2 additional groups\n" 299d6f907dcSJoerg Wunsch "\t-m [ -k dir ] create and set up home\n" 300d6f907dcSJoerg Wunsch "\t-s shell name of login shell\n" 301d6f907dcSJoerg Wunsch "\t-o duplicate uid ok\n" 302d6f907dcSJoerg Wunsch "\t-L class user class\n" 303d6f907dcSJoerg Wunsch "\t-h fd read password on fd\n" 304f1d684faSDavid Nugent "\t-Y update NIS maps\n" 30548aee7f3SJoerg Wunsch "\t-N no update\n" 306d6f907dcSJoerg Wunsch " Setting defaults:\n" 3075f12594aSDavid Nugent "\t-V etcdir alternate /etc location\n" 308d6f907dcSJoerg Wunsch "\t-D set user defaults\n" 309d6f907dcSJoerg Wunsch "\t-b dir default home root dir\n" 310d6f907dcSJoerg Wunsch "\t-e period default expiry period\n" 311d6f907dcSJoerg Wunsch "\t-p period default password change period\n" 312d6f907dcSJoerg Wunsch "\t-g group default group\n" 313d6f907dcSJoerg Wunsch "\t-G grp1,grp2 additional groups\n" 314d6f907dcSJoerg Wunsch "\t-L class default user class\n" 315d6f907dcSJoerg Wunsch "\t-k dir default home skeleton\n" 316d6f907dcSJoerg Wunsch "\t-u min,max set min,max uids\n" 317d6f907dcSJoerg Wunsch "\t-i min,max set min,max gids\n" 318d6f907dcSJoerg Wunsch "\t-w method set default password method\n" 319f1d684faSDavid Nugent "\t-s shell default shell\n" 320f1d684faSDavid Nugent "\t-y path set NIS passwd file path\n", 3211dcc6ec7SPhilippe Charnier "usage: pw userdel [uid|name] [switches]\n" 3225f12594aSDavid Nugent "\t-V etcdir alternate /etc location\n" 323d6f907dcSJoerg Wunsch "\t-n name login name\n" 324d6f907dcSJoerg Wunsch "\t-u uid user id\n" 325f1d684faSDavid Nugent "\t-Y update NIS maps\n" 326d6f907dcSJoerg Wunsch "\t-r remove home & contents\n", 3271dcc6ec7SPhilippe Charnier "usage: pw usermod [uid|name] [switches]\n" 3285f12594aSDavid Nugent "\t-V etcdir alternate /etc location\n" 329d6f907dcSJoerg Wunsch "\t-C config configuration file\n" 330d6f907dcSJoerg Wunsch "\t-q quiet operation\n" 331d6f907dcSJoerg Wunsch "\t-F force add if no user\n" 332d6f907dcSJoerg Wunsch "\t-n name login name\n" 333d6f907dcSJoerg Wunsch "\t-u uid user id\n" 334d6f907dcSJoerg Wunsch "\t-c comment user name/comment\n" 335d6f907dcSJoerg Wunsch "\t-d directory home directory\n" 336d6f907dcSJoerg Wunsch "\t-e date account expiry date\n" 337d6f907dcSJoerg Wunsch "\t-p date password expiry date\n" 338d6f907dcSJoerg Wunsch "\t-g grp initial group\n" 339d6f907dcSJoerg Wunsch "\t-G grp1,grp2 additional groups\n" 340d6f907dcSJoerg Wunsch "\t-l name new login name\n" 341d6f907dcSJoerg Wunsch "\t-L class user class\n" 342d6f907dcSJoerg Wunsch "\t-m [ -k dir ] create and set up home\n" 343d6f907dcSJoerg Wunsch "\t-s shell name of login shell\n" 34448aee7f3SJoerg Wunsch "\t-w method set new password using method\n" 34548aee7f3SJoerg Wunsch "\t-h fd read password on fd\n" 346f1d684faSDavid Nugent "\t-Y update NIS maps\n" 34748aee7f3SJoerg Wunsch "\t-N no update\n", 3481dcc6ec7SPhilippe Charnier "usage: pw usershow [uid|name] [switches]\n" 3495f12594aSDavid Nugent "\t-V etcdir alternate /etc location\n" 350d6f907dcSJoerg Wunsch "\t-n name login name\n" 351d6f907dcSJoerg Wunsch "\t-u uid user id\n" 352d6f907dcSJoerg Wunsch "\t-F force print\n" 35348aee7f3SJoerg Wunsch "\t-P prettier format\n" 35448aee7f3SJoerg Wunsch "\t-a print all users\n", 3551dcc6ec7SPhilippe Charnier "usage: pw usernext [switches]\n" 3565f12594aSDavid Nugent "\t-V etcdir alternate /etc location\n" 35748aee7f3SJoerg Wunsch "\t-C config configuration file\n" 358d6f907dcSJoerg Wunsch }, 359d6f907dcSJoerg Wunsch { 3601dcc6ec7SPhilippe Charnier "usage: pw groupadd [group|gid] [switches]\n" 3615f12594aSDavid Nugent "\t-V etcdir alternate /etc location\n" 362d6f907dcSJoerg Wunsch "\t-C config configuration file\n" 363d6f907dcSJoerg Wunsch "\t-q quiet operation\n" 364d6f907dcSJoerg Wunsch "\t-n group group name\n" 365d6f907dcSJoerg Wunsch "\t-g gid group id\n" 36648aee7f3SJoerg Wunsch "\t-M usr1,usr2 add users as group members\n" 36748aee7f3SJoerg Wunsch "\t-o duplicate gid ok\n" 368f1d684faSDavid Nugent "\t-Y update NIS maps\n" 36948aee7f3SJoerg Wunsch "\t-N no update\n", 3701dcc6ec7SPhilippe Charnier "usage: pw groupdel [group|gid] [switches]\n" 3715f12594aSDavid Nugent "\t-V etcdir alternate /etc location\n" 372d6f907dcSJoerg Wunsch "\t-n name group name\n" 373f1d684faSDavid Nugent "\t-g gid group id\n" 374f1d684faSDavid Nugent "\t-Y update NIS maps\n", 3751dcc6ec7SPhilippe Charnier "usage: pw groupmod [group|gid] [switches]\n" 3765f12594aSDavid Nugent "\t-V etcdir alternate /etc location\n" 377d6f907dcSJoerg Wunsch "\t-C config configuration file\n" 378d6f907dcSJoerg Wunsch "\t-q quiet operation\n" 379d6f907dcSJoerg Wunsch "\t-F force add if not exists\n" 380d6f907dcSJoerg Wunsch "\t-n name group name\n" 381d6f907dcSJoerg Wunsch "\t-g gid group id\n" 38248aee7f3SJoerg Wunsch "\t-M usr1,usr2 replaces users as group members\n" 38348aee7f3SJoerg Wunsch "\t-m usr1,usr2 add users as group members\n" 38448aee7f3SJoerg Wunsch "\t-l name new group name\n" 385f1d684faSDavid Nugent "\t-Y update NIS maps\n" 38648aee7f3SJoerg Wunsch "\t-N no update\n", 3871dcc6ec7SPhilippe Charnier "usage: pw groupshow [group|gid] [switches]\n" 3885f12594aSDavid Nugent "\t-V etcdir alternate /etc location\n" 389d6f907dcSJoerg Wunsch "\t-n name group name\n" 390d6f907dcSJoerg Wunsch "\t-g gid group id\n" 391d6f907dcSJoerg Wunsch "\t-F force print\n" 39248aee7f3SJoerg Wunsch "\t-P prettier format\n" 39348aee7f3SJoerg Wunsch "\t-a print all accounting groups\n", 3941dcc6ec7SPhilippe Charnier "usage: pw groupnext [switches]\n" 3955f12594aSDavid Nugent "\t-V etcdir alternate /etc location\n" 39648aee7f3SJoerg Wunsch "\t-C config configuration file\n" 397d6f907dcSJoerg Wunsch } 398d6f907dcSJoerg Wunsch }; 399d6f907dcSJoerg Wunsch 4001dcc6ec7SPhilippe Charnier fprintf(stderr, help[which][mode]); 401d6f907dcSJoerg Wunsch } 40248aee7f3SJoerg Wunsch exit(EXIT_FAILURE); 403d6f907dcSJoerg Wunsch } 404d6f907dcSJoerg Wunsch 405d6f907dcSJoerg Wunsch struct carg * 406d6f907dcSJoerg Wunsch getarg(struct cargs * _args, int ch) 407d6f907dcSJoerg Wunsch { 408d6f907dcSJoerg Wunsch struct carg *c = _args->lh_first; 409d6f907dcSJoerg Wunsch 410d6f907dcSJoerg Wunsch while (c != NULL && c->ch != ch) 411d6f907dcSJoerg Wunsch c = c->list.le_next; 412d6f907dcSJoerg Wunsch return c; 413d6f907dcSJoerg Wunsch } 414d6f907dcSJoerg Wunsch 415d6f907dcSJoerg Wunsch struct carg * 416d6f907dcSJoerg Wunsch addarg(struct cargs * _args, int ch, char *argstr) 417d6f907dcSJoerg Wunsch { 418d6f907dcSJoerg Wunsch struct carg *ca = malloc(sizeof(struct carg)); 419d6f907dcSJoerg Wunsch 420d6f907dcSJoerg Wunsch if (ca == NULL) 4211dcc6ec7SPhilippe Charnier errx(EX_OSERR, "out of memory"); 422d6f907dcSJoerg Wunsch ca->ch = ch; 423d6f907dcSJoerg Wunsch ca->val = argstr; 424d6f907dcSJoerg Wunsch LIST_INSERT_HEAD(_args, ca, list); 425d6f907dcSJoerg Wunsch return ca; 426d6f907dcSJoerg Wunsch } 427