1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2013 Gary Mills
  23  *
  24  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  25  * Use is subject to license terms.
  26  */
  27 
  28 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  29 /*        All Rights Reserved   */
  30 
  31 /*
  32  * Copyright (c) 2013 RackTop Systems.
  33  */
  34 
  35 #include        <sys/types.h>
  36 #include        <sys/stat.h>
  37 #include        <sys/param.h>
  38 #include        <stdio.h>
  39 #include        <stdlib.h>
  40 #include        <ctype.h>
  41 #include        <limits.h>
  42 #include        <string.h>
  43 #include        <userdefs.h>
  44 #include        <errno.h>
  45 #include        <project.h>
  46 #include        <unistd.h>
  47 #include        <user_attr.h>
  48 #include        <libcmdutils.h>
  49 #include        "users.h"
  50 #include        "messages.h"
  51 #include        "userdisp.h"
  52 #include        "funcs.h"
  53 
  54 /*
  55  *  useradd [-u uid [-o] | -g group | -G group [[, group]...]
  56  *              | -d dir [-m [-z|Z]]
  57  *              | -s shell | -c comment | -k skel_dir | -b base_dir] ]
  58  *              [ -A authorization [, authorization ...]]
  59  *              [ -P profile [, profile ...]]
  60  *              [ -K key=value ]
  61  *              [ -R role [, role ...]] [-p project [, project ...]] login
  62  *  useradd -D [ -g group ] [ -b base_dir | -f inactive | -e expire |
  63  *              -s shell | -k skel_dir ]
  64  *              [ -A authorization [, authorization ...]]
  65  *              [ -P profile [, profile ...]] [ -K key=value ]
  66  *              [ -R role [, role ...]] [-p project [, project ...]] login
  67  *
  68  *      This command adds new user logins to the system.  Arguments are:
  69  *
  70  *      uid - an integer
  71  *      group - an existing group's integer ID or char string name
  72  *      dir - home directory
  73  *      shell - a program to be used as a shell
  74  *      comment - any text string
  75  *      skel_dir - a skeleton directory
  76  *      base_dir - a directory
  77  *      login - a string of printable chars except colon(:)
  78  *      authorization - One or more comma separated authorizations defined
  79  *                      in auth_attr(4).
  80  *      profile - One or more comma separated execution profiles defined
  81  *                in prof_attr(4)
  82  *      role - One or more comma-separated role names defined in user_attr(4)
  83  *      project - One or more comma-separated project names or numbers
  84  *
  85  */
  86 
  87 extern struct userdefs *getusrdef();
  88 extern void dispusrdef();
  89 
  90 static void cleanup();
  91 
  92 extern int check_perm(), valid_expire();
  93 extern int putusrdef(), valid_uid();
  94 extern int call_passmgmt(), edit_group(), create_home();
  95 extern int edit_project();
  96 extern int **valid_lgroup();
  97 extern projid_t **valid_lproject();
  98 extern void update_def(struct userdefs *);
  99 extern void import_def(struct userdefs *);
 100 extern int get_default_zfs_flags();
 101 
 102 static uid_t uid;                       /* new uid */
 103 static char *logname;                   /* login name to add */
 104 static struct userdefs *usrdefs;        /* defaults for useradd */
 105 
 106 char *cmdname;
 107 
 108 static char homedir[ PATH_MAX + 1 ];    /* home directory */
 109 static char gidstring[32];              /* group id string representation */
 110 static gid_t gid;                       /* gid of new login */
 111 static char uidstring[32];              /* user id string representation */
 112 static char *uidstr = NULL;             /* uid from command line */
 113 static char *base_dir = NULL;           /* base_dir from command line */
 114 static char *group = NULL;              /* group from command line */
 115 static char *grps = NULL;               /* multi groups from command line */
 116 static char *dir = NULL;                /* home dir from command line */
 117 static char *shell = NULL;              /* shell from command line */
 118 static char *comment = NULL;            /* comment from command line */
 119 static char *skel_dir = NULL;           /* skel dir from command line */
 120 static long inact;                      /* inactive days */
 121 static char *inactstr = NULL;           /* inactive from command line */
 122 static char inactstring[10];            /* inactivity string representation */
 123 static char *expirestr = NULL;          /* expiration date from command line */
 124 static char *projects = NULL;           /* project id's from command line */
 125 
 126 static char *usertype = NULL;   /* type of user, either role or normal */
 127 
 128 typedef enum {
 129         BASEDIR = 0,
 130         SKELDIR,
 131         SHELL
 132 } path_opt_t;
 133 
 134 
 135 static void valid_input(path_opt_t, const char *);
 136 
 137 int
 138 main(argc, argv)
 139 int argc;
 140 char *argv[];
 141 {
 142         int ch, ret, mflag = 0, oflag = 0, Dflag = 0;
 143         int zflag = 0, Zflag = 0, **gidlist = NULL;
 144         projid_t **projlist = NULL;
 145         char *ptr;                      /* loc in a str, may be set by strtol */
 146         struct group *g_ptr;
 147         struct project p_ptr;
 148         char mybuf[PROJECT_BUFSZ];
 149         struct stat statbuf;            /* status buffer for stat */
 150         int warning;
 151         int busy = 0;
 152         char **nargv;                   /* arguments for execvp of passmgmt */
 153         int argindex;                   /* argument index into nargv */
 154         int zfs_flags = 0;                      /* create_home flags */
 155 
 156         cmdname = argv[0];
 157 
 158         if (geteuid() != 0) {
 159                 errmsg(M_PERM_DENIED);
 160                 exit(EX_NO_PERM);
 161         }
 162 
 163         opterr = 0;                     /* no print errors from getopt */
 164         usertype = getusertype(argv[0]);
 165 
 166         change_key(USERATTR_TYPE_KW, usertype);
 167 
 168         while ((ch = getopt(argc, argv,
 169                     "b:c:Dd:e:f:G:g:k:mzZop:s:u:A:P:R:K:")) != EOF)
 170                 switch (ch) {
 171                 case 'b':
 172                         base_dir = optarg;
 173                         break;
 174 
 175                 case 'c':
 176                         comment = optarg;
 177                         break;
 178 
 179                 case 'D':
 180                         Dflag++;
 181                         break;
 182 
 183                 case 'd':
 184                         dir = optarg;
 185                         break;
 186 
 187                 case 'e':
 188                         expirestr = optarg;
 189                         break;
 190 
 191                 case 'f':
 192                         inactstr = optarg;
 193                         break;
 194 
 195                 case 'G':
 196                         grps = optarg;
 197                         break;
 198 
 199                 case 'g':
 200                         group = optarg;
 201                         break;
 202 
 203                 case 'k':
 204                         skel_dir = optarg;
 205                         break;
 206 
 207                 case 'm':
 208                         mflag++;
 209                         break;
 210 
 211                 case 'o':
 212                         oflag++;
 213                         break;
 214 
 215                 case 'p':
 216                         projects = optarg;
 217                         break;
 218 
 219                 case 's':
 220                         shell = optarg;
 221                         break;
 222 
 223                 case 'u':
 224                         uidstr = optarg;
 225                         break;
 226 
 227                 case 'Z':
 228                         Zflag++;
 229                         break;
 230 
 231                 case 'z':
 232                         zflag++;
 233                         break;
 234 
 235                 case 'A':
 236                         change_key(USERATTR_AUTHS_KW, optarg);
 237                         break;
 238 
 239                 case 'P':
 240                         change_key(USERATTR_PROFILES_KW, optarg);
 241                         break;
 242 
 243                 case 'R':
 244                         if (is_role(usertype)) {
 245                                 errmsg(M_ARUSAGE);
 246                                 exit(EX_SYNTAX);
 247                         }
 248                         change_key(USERATTR_ROLES_KW, optarg);
 249                         break;
 250 
 251                 case 'K':
 252                         change_key(NULL, optarg);
 253                         break;
 254 
 255                 default:
 256                 case '?':
 257                         if (is_role(usertype))
 258                                 errmsg(M_ARUSAGE);
 259                         else
 260                                 errmsg(M_AUSAGE);
 261                         exit(EX_SYNTAX);
 262                 }
 263 
 264         if (((!mflag) && (zflag || Zflag)) || (zflag && Zflag) ||
 265             (mflag > 1 && (zflag || Zflag))) {
 266                 if (is_role(usertype))
 267                         errmsg(M_ARUSAGE);
 268                 else
 269                         errmsg(M_AUSAGE);
 270                 exit(EX_SYNTAX);
 271         }
 272 
 273 
 274         /* get defaults for adding new users */
 275         usrdefs = getusrdef(usertype);
 276 
 277         if (Dflag) {
 278                 /* DISPLAY mode */
 279 
 280                 /* check syntax */
 281                 if (optind != argc) {
 282                         if (is_role(usertype))
 283                                 errmsg(M_ARUSAGE);
 284                         else
 285                                 errmsg(M_AUSAGE);
 286                         exit(EX_SYNTAX);
 287                 }
 288 
 289                 if (uidstr != NULL || oflag || grps != NULL ||
 290                     dir != NULL || mflag || comment != NULL) {
 291                         if (is_role(usertype))
 292                                 errmsg(M_ARUSAGE);
 293                         else
 294                                 errmsg(M_AUSAGE);
 295                         exit(EX_SYNTAX);
 296                 }
 297 
 298                 /* Group must be an existing group */
 299                 if (group != NULL) {
 300                         switch (valid_group(group, &g_ptr, &warning)) {
 301                         case INVALID:
 302                                 errmsg(M_INVALID, group, "group id");
 303                                 exit(EX_BADARG);
 304                                 /*NOTREACHED*/
 305                         case TOOBIG:
 306                                 errmsg(M_TOOBIG, "gid", group);
 307                                 exit(EX_BADARG);
 308                                 /*NOTREACHED*/
 309                         case RESERVED:
 310                         case UNIQUE:
 311                                 errmsg(M_GRP_NOTUSED, group);
 312                                 exit(EX_NAME_NOT_EXIST);
 313                         }
 314                         if (warning)
 315                                 warningmsg(warning, group);
 316 
 317                         usrdefs->defgroup = g_ptr->gr_gid;
 318                         usrdefs->defgname = g_ptr->gr_name;
 319 
 320                 }
 321 
 322                 /* project must be an existing project */
 323                 if (projects != NULL) {
 324                         switch (valid_project(projects, &p_ptr, mybuf,
 325                             sizeof (mybuf), &warning)) {
 326                         case INVALID:
 327                                 errmsg(M_INVALID, projects, "project id");
 328                                 exit(EX_BADARG);
 329                                 /*NOTREACHED*/
 330                         case TOOBIG:
 331                                 errmsg(M_TOOBIG, "projid", projects);
 332                                 exit(EX_BADARG);
 333                                 /*NOTREACHED*/
 334                         case UNIQUE:
 335                                 errmsg(M_PROJ_NOTUSED, projects);
 336                                 exit(EX_NAME_NOT_EXIST);
 337                         }
 338                         if (warning)
 339                                 warningmsg(warning, projects);
 340 
 341                         usrdefs->defproj = p_ptr.pj_projid;
 342                         usrdefs->defprojname = p_ptr.pj_name;
 343                 }
 344 
 345                 /* base_dir must be an existing directory */
 346                 if (base_dir != NULL) {
 347                         valid_input(BASEDIR, base_dir);
 348                         usrdefs->defparent = base_dir;
 349                 }
 350 
 351                 /* inactivity period is an integer */
 352                 if (inactstr != NULL) {
 353                         /* convert inactstr to integer */
 354                         inact = strtol(inactstr, &ptr, 10);
 355                         if (*ptr || inact < 0) {
 356                                 errmsg(M_INVALID, inactstr,
 357                                     "inactivity period");
 358                                 exit(EX_BADARG);
 359                         }
 360 
 361                         usrdefs->definact = inact;
 362                 }
 363 
 364                 /* expiration string is a date, newer than today */
 365                 if (expirestr != NULL) {
 366                         if (*expirestr) {
 367                                 if (valid_expire(expirestr, (time_t *)0)
 368                                     == INVALID) {
 369                                         errmsg(M_INVALID, expirestr,
 370                                             "expiration date");
 371                                         exit(EX_BADARG);
 372                                 }
 373                                 usrdefs->defexpire = expirestr;
 374                         } else
 375                                 /* Unset the expiration date */
 376                                 usrdefs->defexpire = "";
 377                 }
 378 
 379                 if (shell != NULL) {
 380                         valid_input(SHELL, shell);
 381                         usrdefs->defshell = shell;
 382                 }
 383                 if (skel_dir != NULL) {
 384                         valid_input(SKELDIR, skel_dir);
 385                         usrdefs->defskel = skel_dir;
 386                 }
 387                 update_def(usrdefs);
 388 
 389                 /* change defaults for useradd */
 390                 if (putusrdef(usrdefs, usertype) < 0) {
 391                         errmsg(M_UPDATE, "created");
 392                         exit(EX_UPDATE);
 393                 }
 394 
 395                 /* Now, display */
 396                 dispusrdef(stdout, (D_ALL & ~D_RID), usertype);
 397                 exit(EX_SUCCESS);
 398 
 399         }
 400 
 401         /* ADD mode */
 402 
 403         /* check syntax */
 404         if (optind != argc - 1 || (skel_dir != NULL && !mflag)) {
 405                 if (is_role(usertype))
 406                         errmsg(M_ARUSAGE);
 407                 else
 408                         errmsg(M_AUSAGE);
 409                 exit(EX_SYNTAX);
 410         }
 411 
 412         logname = argv[optind];
 413         switch (valid_login(logname, (struct passwd **)NULL, &warning)) {
 414         case INVALID:
 415                 errmsg(M_INVALID, logname, "login name");
 416                 exit(EX_BADARG);
 417                 /*NOTREACHED*/
 418 
 419         case NOTUNIQUE:
 420                 errmsg(M_USED, logname);
 421                 exit(EX_NAME_EXISTS);
 422                 /*NOTREACHED*/
 423 
 424         case LONGNAME:
 425                 errmsg(M_TOO_LONG, logname);
 426                 exit(EX_BADARG);
 427                 /*NOTREACHED*/
 428         }
 429 
 430         if (warning)
 431                 warningmsg(warning, logname);
 432         if (uidstr != NULL) {
 433                 /* convert uidstr to integer */
 434                 errno = 0;
 435                 uid = (uid_t)strtol(uidstr, &ptr, (int)10);
 436                 if (*ptr || errno == ERANGE) {
 437                         errmsg(M_INVALID, uidstr, "user id");
 438                         exit(EX_BADARG);
 439                 }
 440 
 441                 switch (valid_uid(uid, NULL)) {
 442                 case NOTUNIQUE:
 443                         if (!oflag) {
 444                                 /* override not specified */
 445                                 errmsg(M_UID_USED, uid);
 446                                 exit(EX_ID_EXISTS);
 447                         }
 448                         break;
 449                 case RESERVED:
 450                         errmsg(M_RESERVED, uid);
 451                         break;
 452                 case TOOBIG:
 453                         errmsg(M_TOOBIG, "uid", uid);
 454                         exit(EX_BADARG);
 455                         break;
 456                 }
 457 
 458         } else {
 459 
 460                 if (findnextuid(DEFRID+1, MAXUID, &uid) != 0) {
 461                         errmsg(M_INVALID, "default id", "user id");
 462                         exit(EX_ID_EXISTS);
 463                 }
 464         }
 465 
 466         if (group != NULL) {
 467                 switch (valid_group(group, &g_ptr, &warning)) {
 468                 case INVALID:
 469                         errmsg(M_INVALID, group, "group id");
 470                         exit(EX_BADARG);
 471                         /*NOTREACHED*/
 472                 case TOOBIG:
 473                         errmsg(M_TOOBIG, "gid", group);
 474                         exit(EX_BADARG);
 475                         /*NOTREACHED*/
 476                 case RESERVED:
 477                 case UNIQUE:
 478                         errmsg(M_GRP_NOTUSED, group);
 479                         exit(EX_NAME_NOT_EXIST);
 480                         /*NOTREACHED*/
 481                 }
 482 
 483                 if (warning)
 484                         warningmsg(warning, group);
 485                 gid = g_ptr->gr_gid;
 486 
 487         } else gid = usrdefs->defgroup;
 488 
 489         if (grps != NULL) {
 490                 if (!*grps)
 491                         /* ignore -G "" */
 492                         grps = (char *)0;
 493                 else if (!(gidlist = valid_lgroup(grps, gid)))
 494                         exit(EX_BADARG);
 495         }
 496 
 497         if (projects != NULL) {
 498                 if (! *projects)
 499                         projects = (char *)0;
 500                 else if (! (projlist = valid_lproject(projects)))
 501                         exit(EX_BADARG);
 502         }
 503 
 504         /* if base_dir is provided, check its validity; otherwise default */
 505         if (base_dir != NULL)
 506                 valid_input(BASEDIR, base_dir);
 507         else
 508                 base_dir = usrdefs->defparent;
 509 
 510         if (dir == NULL) {
 511                 /* set homedir to home directory made from base_dir */
 512                 (void) sprintf(homedir, "%s/%s", base_dir, logname);
 513 
 514         } else if (REL_PATH(dir)) {
 515                 errmsg(M_RELPATH, dir);
 516                 exit(EX_BADARG);
 517 
 518         } else
 519                 (void) strcpy(homedir, dir);
 520 
 521         if (mflag) {
 522                 /* Does home dir. already exist? */
 523                 if (stat(homedir, &statbuf) == 0) {
 524                         /* directory exists - don't try to create */
 525                         mflag = 0;
 526 
 527                         if (check_perm(statbuf, uid, gid, S_IXOTH) != 0)
 528                                 errmsg(M_NO_PERM, logname, homedir);
 529                 }
 530         }
 531         /*
 532          * if shell, skel_dir are provided, check their validity.
 533          * Otherwise default.
 534          */
 535         if (shell != NULL)
 536                 valid_input(SHELL, shell);
 537         else
 538                 shell = usrdefs->defshell;
 539 
 540         if (skel_dir != NULL)
 541                 valid_input(SKELDIR, skel_dir);
 542         else
 543                 skel_dir = usrdefs->defskel;
 544 
 545         if (inactstr != NULL) {
 546                 /* convert inactstr to integer */
 547                 inact = strtol(inactstr, &ptr, 10);
 548                 if (*ptr || inact < 0) {
 549                         errmsg(M_INVALID, inactstr, "inactivity period");
 550                         exit(EX_BADARG);
 551                 }
 552         } else inact = usrdefs->definact;
 553 
 554         /* expiration string is a date, newer than today */
 555         if (expirestr != NULL) {
 556                 if (*expirestr) {
 557                         if (valid_expire(expirestr, (time_t *)0) == INVALID) {
 558                                 errmsg(M_INVALID, expirestr, "expiration date");
 559                                 exit(EX_BADARG);
 560                         }
 561                         usrdefs->defexpire = expirestr;
 562                 } else
 563                         /* Unset the expiration date */
 564                         expirestr = (char *)0;
 565 
 566         } else expirestr = usrdefs->defexpire;
 567 
 568         import_def(usrdefs);
 569 
 570         /* must now call passmgmt */
 571 
 572         /* set up arguments to  passmgmt in nargv array */
 573         nargv = malloc((30 + nkeys * 2) * sizeof (char *));
 574         argindex = 0;
 575         nargv[argindex++] = PASSMGMT;
 576         nargv[argindex++] = "-a";       /* add */
 577 
 578         if (comment != NULL) {
 579                 /* comment */
 580                 nargv[argindex++] = "-c";
 581                 nargv[argindex++] = comment;
 582         }
 583 
 584         /* flags for home directory */
 585         nargv[argindex++] = "-h";
 586         nargv[argindex++] = homedir;
 587 
 588         /* set gid flag */
 589         nargv[argindex++] = "-g";
 590         (void) sprintf(gidstring, "%u", gid);
 591         nargv[argindex++] = gidstring;
 592 
 593         /* shell */
 594         nargv[argindex++] = "-s";
 595         nargv[argindex++] = shell;
 596 
 597         /* set inactive */
 598         nargv[argindex++] = "-f";
 599         (void) sprintf(inactstring, "%ld", inact);
 600         nargv[argindex++] = inactstring;
 601 
 602         /* set expiration date */
 603         if (expirestr != NULL) {
 604                 nargv[argindex++] = "-e";
 605                 nargv[argindex++] = expirestr;
 606         }
 607 
 608         /* set uid flag */
 609         nargv[argindex++] = "-u";
 610         (void) sprintf(uidstring, "%u", uid);
 611         nargv[argindex++] = uidstring;
 612 
 613         if (oflag) nargv[argindex++] = "-o";
 614 
 615         if (nkeys > 1)
 616                 addkey_args(nargv, &argindex);
 617 
 618         /* finally - login name */
 619         nargv[argindex++] = logname;
 620 
 621         /* set the last to null */
 622         nargv[argindex++] = NULL;
 623 
 624         /* now call passmgmt */
 625         ret = PEX_FAILED;
 626         /*
 627          * If call_passmgmt fails for any reason other than PEX_BADUID, exit
 628          * is invoked with an appropriate error message. If PEX_BADUID is
 629          * returned, then if the user specified the ID, exit is invoked
 630          * with an appropriate error message. Otherwise we try to pick a
 631          * different ID and try again. If we run out of IDs, i.e. no more
 632          * users can be created, then -1 is returned and we terminate via exit.
 633          * If PEX_BUSY is returned we increment a count, since we will stop
 634          * trying if PEX_BUSY reaches 3. For PEX_SUCCESS we immediately
 635          * terminate the loop.
 636          */
 637         while (busy < 3 && ret != PEX_SUCCESS) {
 638                 switch (ret = call_passmgmt(nargv)) {
 639                 case PEX_SUCCESS:
 640                         break;
 641                 case PEX_BUSY:
 642                         busy++;
 643                         break;
 644                 case PEX_HOSED_FILES:
 645                         errmsg(M_HOSED_FILES);
 646                         exit(EX_INCONSISTENT);
 647                         break;
 648 
 649                 case PEX_SYNTAX:
 650                 case PEX_BADARG:
 651                         /* should NEVER occur that passmgmt usage is wrong */
 652                         if (is_role(usertype))
 653                                 errmsg(M_ARUSAGE);
 654                         else
 655                                 errmsg(M_AUSAGE);
 656                         exit(EX_SYNTAX);
 657                         break;
 658 
 659                 case PEX_BADUID:
 660                         /*
 661                          * The uid has been taken. If it was specified by a
 662                          * user, then we must fail. Otherwise, keep trying
 663                          * to get a good uid until we run out of IDs.
 664                          */
 665                         if (uidstr != NULL) {
 666                                 errmsg(M_UID_USED, uid);
 667                                 exit(EX_ID_EXISTS);
 668                         } else {
 669                                 if (findnextuid(DEFRID+1, MAXUID, &uid) != 0) {
 670                                         errmsg(M_INVALID, "default id",
 671                                             "user id");
 672                                         exit(EX_ID_EXISTS);
 673                                 }
 674                                 (void) sprintf(uidstring, "%u", uid);
 675                         }
 676                         break;
 677 
 678                 case PEX_BADNAME:
 679                         /* invalid loname */
 680                         errmsg(M_USED, logname);
 681                         exit(EX_NAME_EXISTS);
 682                         break;
 683 
 684                 default:
 685                         errmsg(M_UPDATE, "created");
 686                         exit(ret);
 687                         break;
 688                 }
 689         }
 690         if (busy == 3) {
 691                 errmsg(M_UPDATE, "created");
 692                 exit(ret);
 693         }
 694 
 695         /* add group entry */
 696         if ((grps != NULL) && edit_group(logname, (char *)0, gidlist, 0)) {
 697                 errmsg(M_UPDATE, "created");
 698                 cleanup(logname);
 699                 exit(EX_UPDATE);
 700         }
 701 
 702         /* update project database */
 703         if ((projects != NULL) &&
 704             edit_project(logname, (char *)NULL, projlist, 0)) {
 705                 errmsg(M_UPDATE, "created");
 706                 cleanup(logname);
 707                 exit(EX_UPDATE);
 708         }
 709 
 710         /* create home directory */
 711         if (mflag) {
 712                 zfs_flags = get_default_zfs_flags();
 713 
 714                 if (zflag || mflag > 1)
 715                         zfs_flags |= CHANGE_ZFS_FS;
 716                 else if (Zflag)
 717                         zfs_flags &= ~CHANGE_ZFS_FS;
 718                 ret = create_home(homedir, skel_dir, uid, gid, zfs_flags);
 719         }
 720         if (ret != EX_SUCCESS) {
 721                 (void) edit_project(logname, (char *)NULL, (projid_t **)NULL,
 722                     0);
 723                 (void) edit_group(logname, (char *)0, (int **)0, 1);
 724                 cleanup(logname);
 725                 exit(EX_HOMEDIR);
 726         }
 727 
 728         return (ret);
 729 }
 730 
 731 static void
 732 cleanup(logname)
 733 char *logname;
 734 {
 735         char *nargv[4];
 736 
 737         nargv[0] = PASSMGMT;
 738         nargv[1] = "-d";
 739         nargv[2] = logname;
 740         nargv[3] = NULL;
 741 
 742         switch (call_passmgmt(nargv)) {
 743         case PEX_SUCCESS:
 744                 break;
 745 
 746         case PEX_SYNTAX:
 747                 /* should NEVER occur that passmgmt usage is wrong */
 748                 if (is_role(usertype))
 749                         errmsg(M_ARUSAGE);
 750                 else
 751                         errmsg(M_AUSAGE);
 752                 break;
 753 
 754         case PEX_BADUID:
 755                 /* uid is used - shouldn't happen but print message anyway */
 756                 errmsg(M_UID_USED, uid);
 757                 break;
 758 
 759         case PEX_BADNAME:
 760                 /* invalid loname */
 761                 errmsg(M_USED, logname);
 762                 break;
 763 
 764         default:
 765                 errmsg(M_UPDATE, "created");
 766                 break;
 767         }
 768 }
 769 
 770 /* Check the validity for shell, base_dir and skel_dir */
 771 
 772 void
 773 valid_input(path_opt_t opt, const char *input)
 774 {
 775         struct stat     statbuf;
 776 
 777         if (REL_PATH(input)) {
 778                 errmsg(M_RELPATH, input);
 779                 exit(EX_BADARG);
 780         }
 781         if (stat(input, &statbuf) == -1) {
 782                 errmsg(M_INVALID, input, "path");
 783                 exit(EX_BADARG);
 784         }
 785         if (opt == SHELL) {
 786                 if (!S_ISREG(statbuf.st_mode) ||
 787                     (statbuf.st_mode & 0555) != 0555) {
 788                         errmsg(M_INVALID, input, "shell");
 789                         exit(EX_BADARG);
 790                 }
 791         } else {
 792                 if (!S_ISDIR(statbuf.st_mode)) {
 793                         errmsg(M_INVALID, input, "directory");
 794                         exit(EX_BADARG);
 795                 }
 796         }
 797 }