pw_conf.c revision 326848
120253Sjoerg/*- 220302Sjoerg * Copyright (C) 1996 320302Sjoerg * David L. Nugent. All rights reserved. 420253Sjoerg * 520253Sjoerg * Redistribution and use in source and binary forms, with or without 620253Sjoerg * modification, are permitted provided that the following conditions 720253Sjoerg * are met: 820253Sjoerg * 1. Redistributions of source code must retain the above copyright 920302Sjoerg * notice, this list of conditions and the following disclaimer. 1020253Sjoerg * 2. Redistributions in binary form must reproduce the above copyright 1120253Sjoerg * notice, this list of conditions and the following disclaimer in the 1220253Sjoerg * documentation and/or other materials provided with the distribution. 1320253Sjoerg * 1420302Sjoerg * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND 1520253Sjoerg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1620253Sjoerg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1720302Sjoerg * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE 1820253Sjoerg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1920253Sjoerg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2020253Sjoerg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2120253Sjoerg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2220253Sjoerg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2320253Sjoerg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2420253Sjoerg * SUCH DAMAGE. 2520253Sjoerg */ 2620253Sjoerg 2730259Scharnier#ifndef lint 2830259Scharnierstatic const char rcsid[] = 2950479Speter "$FreeBSD: stable/11/usr.sbin/pw/pw_conf.c 326848 2017-12-14 13:06:41Z eugen $"; 3030259Scharnier#endif /* not lint */ 3130259Scharnier 32282681Sbapt#include <sys/types.h> 33282681Sbapt#include <sys/sbuf.h> 34286201Sbapt 35286201Sbapt#include <err.h> 36286201Sbapt#include <fcntl.h> 3720253Sjoerg#include <string.h> 38286201Sbapt#include <unistd.h> 3920253Sjoerg 4020253Sjoerg#include "pw.h" 4120253Sjoerg 4220253Sjoerg#define debugging 0 4320253Sjoerg 4420253Sjoergenum { 4520253Sjoerg _UC_NONE, 4620253Sjoerg _UC_DEFAULTPWD, 4720253Sjoerg _UC_REUSEUID, 4820253Sjoerg _UC_REUSEGID, 4921330Sdavidn _UC_NISPASSWD, 5020253Sjoerg _UC_DOTDIR, 5120253Sjoerg _UC_NEWMAIL, 5220253Sjoerg _UC_LOGFILE, 5320253Sjoerg _UC_HOMEROOT, 54168044Sle _UC_HOMEMODE, 5520253Sjoerg _UC_SHELLPATH, 5620253Sjoerg _UC_SHELLS, 5720253Sjoerg _UC_DEFAULTSHELL, 5820253Sjoerg _UC_DEFAULTGROUP, 5920253Sjoerg _UC_EXTRAGROUPS, 6020253Sjoerg _UC_DEFAULTCLASS, 6120253Sjoerg _UC_MINUID, 6220253Sjoerg _UC_MAXUID, 6320253Sjoerg _UC_MINGID, 6420253Sjoerg _UC_MAXGID, 6520253Sjoerg _UC_EXPIRE, 6620253Sjoerg _UC_PASSWORD, 6720253Sjoerg _UC_FIELDS 6820253Sjoerg}; 6920253Sjoerg 7020253Sjoergstatic char bourne_shell[] = "sh"; 7120253Sjoerg 7220253Sjoergstatic char *system_shells[_UC_MAXSHELLS] = 7320253Sjoerg{ 7420253Sjoerg bourne_shell, 7563239Sdavidn "csh", 7663239Sdavidn "tcsh" 7720253Sjoerg}; 7820253Sjoerg 7920253Sjoergstatic char const *booltrue[] = 8020253Sjoerg{ 8120253Sjoerg "yes", "true", "1", "on", NULL 8220253Sjoerg}; 8320253Sjoergstatic char const *boolfalse[] = 8420253Sjoerg{ 8520253Sjoerg "no", "false", "0", "off", NULL 8620253Sjoerg}; 8720253Sjoerg 8820253Sjoergstatic struct userconf config = 8920253Sjoerg{ 9020253Sjoerg 0, /* Default password for new users? (nologin) */ 9120253Sjoerg 0, /* Reuse uids? */ 9220253Sjoerg 0, /* Reuse gids? */ 9321330Sdavidn NULL, /* NIS version of the passwd file */ 9420253Sjoerg "/usr/share/skel", /* Where to obtain skeleton files */ 9520253Sjoerg NULL, /* Mail to send to new accounts */ 9620253Sjoerg "/var/log/userlog", /* Where to log changes */ 9720253Sjoerg "/home", /* Where to create home directory */ 98219408Sjkim _DEF_DIRMODE, /* Home directory perms, modified by umask */ 9920253Sjoerg "/bin", /* Where shells are located */ 10020253Sjoerg system_shells, /* List of shells (first is default) */ 10120253Sjoerg bourne_shell, /* Default shell */ 10220253Sjoerg NULL, /* Default group name */ 10320747Sdavidn NULL, /* Default (additional) groups */ 10420253Sjoerg NULL, /* Default login class */ 10520253Sjoerg 1000, 32000, /* Allowed range of uids */ 10620253Sjoerg 1000, 32000, /* Allowed range of gids */ 10720253Sjoerg 0, /* Days until account expires */ 108285412Sbapt 0 /* Days until password expires */ 10920253Sjoerg}; 11020253Sjoerg 11120253Sjoergstatic char const *comments[_UC_FIELDS] = 11220253Sjoerg{ 11320253Sjoerg "#\n# pw.conf - user/group configuration defaults\n#\n", 11420253Sjoerg "\n# Password for new users? no=nologin yes=loginid none=blank random=random\n", 11520253Sjoerg "\n# Reuse gaps in uid sequence? (yes or no)\n", 11620253Sjoerg "\n# Reuse gaps in gid sequence? (yes or no)\n", 11721330Sdavidn "\n# Path to the NIS passwd file (blank or 'no' for none)\n", 11820253Sjoerg "\n# Obtain default dotfiles from this directory\n", 11920253Sjoerg "\n# Mail this file to new user (/etc/newuser.msg or no)\n", 12020253Sjoerg "\n# Log add/change/remove information in this file\n", 12120253Sjoerg "\n# Root directory in which $HOME directory is created\n", 122168044Sle "\n# Mode for the new $HOME directory, will be modified by umask\n", 12320253Sjoerg "\n# Colon separated list of directories containing valid shells\n", 12470133Sdougb "\n# Comma separated list of available shells (without paths)\n", 12520253Sjoerg "\n# Default shell (without path)\n", 12620253Sjoerg "\n# Default group (leave blank for new group per user)\n", 12720253Sjoerg "\n# Extra groups for new users\n", 12820253Sjoerg "\n# Default login class for new users\n", 12920253Sjoerg "\n# Range of valid default user ids\n", 13020253Sjoerg NULL, 13120253Sjoerg "\n# Range of valid default group ids\n", 13220253Sjoerg NULL, 13320253Sjoerg "\n# Days after which account expires (0=disabled)\n", 13420253Sjoerg "\n# Days after which password expires (0=disabled)\n" 13520253Sjoerg}; 13620253Sjoerg 13720253Sjoergstatic char const *kwds[] = 13820253Sjoerg{ 13920253Sjoerg "", 14020253Sjoerg "defaultpasswd", 14120253Sjoerg "reuseuids", 14220253Sjoerg "reusegids", 14321330Sdavidn "nispasswd", 14420253Sjoerg "skeleton", 14520253Sjoerg "newmail", 14620253Sjoerg "logfile", 14720253Sjoerg "home", 148168044Sle "homemode", 14920253Sjoerg "shellpath", 15020253Sjoerg "shells", 15120253Sjoerg "defaultshell", 15220253Sjoerg "defaultgroup", 15320253Sjoerg "extragroups", 15420253Sjoerg "defaultclass", 15520253Sjoerg "minuid", 15620253Sjoerg "maxuid", 15720253Sjoerg "mingid", 15820253Sjoerg "maxgid", 15920253Sjoerg "expire_days", 16020253Sjoerg "password_days", 16120253Sjoerg NULL 16220253Sjoerg}; 16320253Sjoerg 16420253Sjoergstatic char * 16520253Sjoergunquote(char const * str) 16620253Sjoerg{ 16720253Sjoerg if (str && (*str == '"' || *str == '\'')) { 16820253Sjoerg char *p = strchr(str + 1, *str); 16920253Sjoerg 17020253Sjoerg if (p != NULL) 17120253Sjoerg *p = '\0'; 17220253Sjoerg return (char *) (*++str ? str : NULL); 17320253Sjoerg } 17420253Sjoerg return (char *) str; 17520253Sjoerg} 17620253Sjoerg 17720253Sjoergint 17820253Sjoergboolean_val(char const * str, int dflt) 17920253Sjoerg{ 18020253Sjoerg if ((str = unquote(str)) != NULL) { 18120253Sjoerg int i; 18220253Sjoerg 18320253Sjoerg for (i = 0; booltrue[i]; i++) 18420253Sjoerg if (strcmp(str, booltrue[i]) == 0) 18520253Sjoerg return 1; 18620253Sjoerg for (i = 0; boolfalse[i]; i++) 18720253Sjoerg if (strcmp(str, boolfalse[i]) == 0) 18820253Sjoerg return 0; 189305741Sasomers } 190305741Sasomers return dflt; 191305741Sasomers} 19220253Sjoerg 193305741Sasomersint 194305741Sasomerspasswd_val(char const * str, int dflt) 195305741Sasomers{ 196305741Sasomers if ((str = unquote(str)) != NULL) { 197305741Sasomers int i; 198305741Sasomers 199305741Sasomers for (i = 0; booltrue[i]; i++) 200305741Sasomers if (strcmp(str, booltrue[i]) == 0) 201326848Seugen return P_YES; 202305741Sasomers for (i = 0; boolfalse[i]; i++) 203305741Sasomers if (strcmp(str, boolfalse[i]) == 0) 204326848Seugen return P_NO; 205305741Sasomers 20620253Sjoerg /* 20720253Sjoerg * Special cases for defaultpassword 20820253Sjoerg */ 20920253Sjoerg if (strcmp(str, "random") == 0) 210326848Seugen return P_RANDOM; 21120253Sjoerg if (strcmp(str, "none") == 0) 212326848Seugen return P_NONE; 213305741Sasomers 214305741Sasomers errx(1, "Invalid value for default password"); 21520253Sjoerg } 21620253Sjoerg return dflt; 21720253Sjoerg} 21820253Sjoerg 21920253Sjoergchar const * 22020253Sjoergboolean_str(int val) 22120253Sjoerg{ 22220253Sjoerg if (val == -1) 22320253Sjoerg return "random"; 22420253Sjoerg else if (val == -2) 22520253Sjoerg return "none"; 22620253Sjoerg else 22720253Sjoerg return val ? booltrue[0] : boolfalse[0]; 22820253Sjoerg} 22920253Sjoerg 23020253Sjoergchar * 23120253Sjoergnewstr(char const * p) 23220253Sjoerg{ 233282718Sbapt char *q; 23420253Sjoerg 235282718Sbapt if ((p = unquote(p)) == NULL) 236282718Sbapt return (NULL); 23720253Sjoerg 238282719Sbapt if ((q = strdup(p)) == NULL) 239282719Sbapt err(1, "strdup()"); 240282718Sbapt 241282718Sbapt return (q); 24220253Sjoerg} 24320253Sjoerg 24420253Sjoergstruct userconf * 24520253Sjoergread_userconfig(char const * file) 24620253Sjoerg{ 247264781Sbapt FILE *fp; 248264781Sbapt char *buf, *p; 249286154Sbapt const char *errstr; 250264781Sbapt size_t linecap; 251264781Sbapt ssize_t linelen; 25220253Sjoerg 253264781Sbapt buf = NULL; 254264781Sbapt linecap = 0; 255264781Sbapt 25620253Sjoerg if (file == NULL) 25720253Sjoerg file = _PATH_PW_CONF; 258264781Sbapt 259283815Sbapt if ((fp = fopen(file, "r")) == NULL) 260283815Sbapt return (&config); 26120747Sdavidn 262283815Sbapt while ((linelen = getline(&buf, &linecap, fp)) > 0) { 263283815Sbapt if (*buf && (p = strtok(buf, " \t\r\n=")) != NULL && *p != '#') { 264283815Sbapt static char const toks[] = " \t\r\n,="; 265283815Sbapt char *q = strtok(NULL, toks); 266283815Sbapt int i = 0; 267283815Sbapt mode_t *modeset; 268283815Sbapt 269283815Sbapt while (i < _UC_FIELDS && strcmp(p, kwds[i]) != 0) 270283815Sbapt ++i; 27120253Sjoerg#if debugging 272283815Sbapt if (i == _UC_FIELDS) 273283815Sbapt printf("Got unknown kwd `%s' val=`%s'\n", p, q ? q : ""); 274283815Sbapt else 275283815Sbapt printf("Got kwd[%s]=%s\n", p, q); 27620253Sjoerg#endif 277283815Sbapt switch (i) { 278283815Sbapt case _UC_DEFAULTPWD: 279305741Sasomers config.default_password = passwd_val(q, 1); 280283815Sbapt break; 281283815Sbapt case _UC_REUSEUID: 282283815Sbapt config.reuse_uids = boolean_val(q, 0); 283283815Sbapt break; 284283815Sbapt case _UC_REUSEGID: 285283815Sbapt config.reuse_gids = boolean_val(q, 0); 286283815Sbapt break; 287283815Sbapt case _UC_NISPASSWD: 288283815Sbapt config.nispasswd = (q == NULL || !boolean_val(q, 1)) 289283815Sbapt ? NULL : newstr(q); 290283815Sbapt break; 291283815Sbapt case _UC_DOTDIR: 292283815Sbapt config.dotdir = (q == NULL || !boolean_val(q, 1)) 293283815Sbapt ? NULL : newstr(q); 294283815Sbapt break; 29520747Sdavidn case _UC_NEWMAIL: 296283815Sbapt config.newmail = (q == NULL || !boolean_val(q, 1)) 297283815Sbapt ? NULL : newstr(q); 298283815Sbapt break; 299283815Sbapt case _UC_LOGFILE: 300283815Sbapt config.logfile = (q == NULL || !boolean_val(q, 1)) 301283815Sbapt ? NULL : newstr(q); 302283815Sbapt break; 303283815Sbapt case _UC_HOMEROOT: 304283815Sbapt config.home = (q == NULL || !boolean_val(q, 1)) 305283815Sbapt ? "/home" : newstr(q); 306283815Sbapt break; 307283815Sbapt case _UC_HOMEMODE: 308283815Sbapt modeset = setmode(q); 309283815Sbapt config.homemode = (q == NULL || !boolean_val(q, 1)) 310283815Sbapt ? _DEF_DIRMODE : getmode(modeset, _DEF_DIRMODE); 311283815Sbapt free(modeset); 312283815Sbapt break; 313283815Sbapt case _UC_SHELLPATH: 314283815Sbapt config.shelldir = (q == NULL || !boolean_val(q, 1)) 315283815Sbapt ? "/bin" : newstr(q); 316283815Sbapt break; 317283815Sbapt case _UC_SHELLS: 318283815Sbapt for (i = 0; i < _UC_MAXSHELLS && q != NULL; i++, q = strtok(NULL, toks)) 319283815Sbapt system_shells[i] = newstr(q); 320283815Sbapt if (i > 0) 321283815Sbapt while (i < _UC_MAXSHELLS) 322283815Sbapt system_shells[i++] = NULL; 323283815Sbapt break; 324283815Sbapt case _UC_DEFAULTSHELL: 325283815Sbapt config.shell_default = (q == NULL || !boolean_val(q, 1)) 326283815Sbapt ? (char *) bourne_shell : newstr(q); 327283815Sbapt break; 328283815Sbapt case _UC_DEFAULTGROUP: 329283815Sbapt q = unquote(q); 330283815Sbapt config.default_group = (q == NULL || !boolean_val(q, 1) || GETGRNAM(q) == NULL) 331283815Sbapt ? NULL : newstr(q); 332283815Sbapt break; 333283815Sbapt case _UC_EXTRAGROUPS: 334292849Sbapt while ((q = strtok(NULL, toks)) != NULL) { 335286196Sbapt if (config.groups == NULL) 336286196Sbapt config.groups = sl_init(); 337285412Sbapt sl_add(config.groups, newstr(q)); 338286196Sbapt } 339283815Sbapt break; 340283815Sbapt case _UC_DEFAULTCLASS: 341283815Sbapt config.default_class = (q == NULL || !boolean_val(q, 1)) 342283815Sbapt ? NULL : newstr(q); 343283815Sbapt break; 344283815Sbapt case _UC_MINUID: 345286151Sbapt if ((q = unquote(q)) != NULL) { 346286154Sbapt config.min_uid = strtounum(q, 0, 347286154Sbapt UID_MAX, &errstr); 348286151Sbapt if (errstr) 349286154Sbapt warnx("Invalid min_uid: '%s';" 350286154Sbapt " ignoring", q); 351286151Sbapt } 352283815Sbapt break; 353283815Sbapt case _UC_MAXUID: 354286151Sbapt if ((q = unquote(q)) != NULL) { 355286154Sbapt config.max_uid = strtounum(q, 0, 356286154Sbapt UID_MAX, &errstr); 357286151Sbapt if (errstr) 358286154Sbapt warnx("Invalid max_uid: '%s';" 359286154Sbapt " ignoring", q); 360286151Sbapt } 361283815Sbapt break; 362283815Sbapt case _UC_MINGID: 363286154Sbapt if ((q = unquote(q)) != NULL) { 364286154Sbapt config.min_gid = strtounum(q, 0, 365286154Sbapt GID_MAX, &errstr); 366286151Sbapt if (errstr) 367286154Sbapt warnx("Invalid min_gid: '%s';" 368286154Sbapt " ignoring", q); 369286155Sbapt } 370283815Sbapt break; 371283815Sbapt case _UC_MAXGID: 372286151Sbapt if ((q = unquote(q)) != NULL) { 373286154Sbapt config.max_gid = strtounum(q, 0, 374286154Sbapt GID_MAX, &errstr); 375286151Sbapt if (errstr) 376286154Sbapt warnx("Invalid max_gid: '%s';" 377286154Sbapt " ignoring", q); 378286151Sbapt } 379283815Sbapt break; 380283815Sbapt case _UC_EXPIRE: 381286152Sbapt if ((q = unquote(q)) != NULL) { 382286154Sbapt config.expire_days = strtonum(q, 0, 383286154Sbapt INT_MAX, &errstr); 384286152Sbapt if (errstr) 385286154Sbapt warnx("Invalid expire days:" 386286154Sbapt " '%s'; ignoring", q); 387286152Sbapt } 388283815Sbapt break; 389283815Sbapt case _UC_PASSWORD: 390286152Sbapt if ((q = unquote(q)) != NULL) { 391286154Sbapt config.password_days = strtonum(q, 0, 392286154Sbapt INT_MAX, &errstr); 393286152Sbapt if (errstr) 394286154Sbapt warnx("Invalid password days:" 395286154Sbapt " '%s'; ignoring", q); 396286152Sbapt } 397283815Sbapt break; 398283815Sbapt case _UC_FIELDS: 399283815Sbapt case _UC_NONE: 400283815Sbapt break; 40120253Sjoerg } 40220253Sjoerg } 40320253Sjoerg } 404283818Sbapt free(buf); 405283818Sbapt fclose(fp); 406283818Sbapt 407283815Sbapt return (&config); 40820253Sjoerg} 40920253Sjoerg 41020253Sjoerg 41120253Sjoergint 412286196Sbaptwrite_userconfig(struct userconf *cnf, const char *file) 41320253Sjoerg{ 41420253Sjoerg int fd; 415282697Sbapt int i, j; 416282681Sbapt struct sbuf *buf; 417282697Sbapt FILE *fp; 41820253Sjoerg 41920253Sjoerg if (file == NULL) 42020253Sjoerg file = _PATH_PW_CONF; 42120253Sjoerg 422282697Sbapt if ((fd = open(file, O_CREAT|O_RDWR|O_TRUNC|O_EXLOCK, 0644)) == -1) 423282697Sbapt return (0); 42420253Sjoerg 425282697Sbapt if ((fp = fdopen(fd, "w")) == NULL) { 426282697Sbapt close(fd); 427282697Sbapt return (0); 428282697Sbapt } 429282681Sbapt 430282697Sbapt buf = sbuf_new_auto(); 431282697Sbapt for (i = _UC_NONE; i < _UC_FIELDS; i++) { 432282697Sbapt int quote = 1; 43320253Sjoerg 434282697Sbapt sbuf_clear(buf); 435282697Sbapt switch (i) { 436282697Sbapt case _UC_DEFAULTPWD: 437286196Sbapt sbuf_cat(buf, boolean_str(cnf->default_password)); 438282697Sbapt break; 439282697Sbapt case _UC_REUSEUID: 440286196Sbapt sbuf_cat(buf, boolean_str(cnf->reuse_uids)); 441282697Sbapt break; 442282697Sbapt case _UC_REUSEGID: 443286196Sbapt sbuf_cat(buf, boolean_str(cnf->reuse_gids)); 444282697Sbapt break; 445282697Sbapt case _UC_NISPASSWD: 446286196Sbapt sbuf_cat(buf, cnf->nispasswd ? cnf->nispasswd : ""); 447282697Sbapt quote = 0; 448282697Sbapt break; 449282697Sbapt case _UC_DOTDIR: 450286196Sbapt sbuf_cat(buf, cnf->dotdir ? cnf->dotdir : 451282697Sbapt boolean_str(0)); 452282697Sbapt break; 453282697Sbapt case _UC_NEWMAIL: 454286196Sbapt sbuf_cat(buf, cnf->newmail ? cnf->newmail : 455282697Sbapt boolean_str(0)); 456282697Sbapt break; 457282697Sbapt case _UC_LOGFILE: 458286196Sbapt sbuf_cat(buf, cnf->logfile ? cnf->logfile : 459282697Sbapt boolean_str(0)); 460282697Sbapt break; 461282697Sbapt case _UC_HOMEROOT: 462286196Sbapt sbuf_cat(buf, cnf->home); 463282697Sbapt break; 464282697Sbapt case _UC_HOMEMODE: 465286196Sbapt sbuf_printf(buf, "%04o", cnf->homemode); 466282697Sbapt quote = 0; 467282697Sbapt break; 468282697Sbapt case _UC_SHELLPATH: 469286196Sbapt sbuf_cat(buf, cnf->shelldir); 470282697Sbapt break; 471282697Sbapt case _UC_SHELLS: 472282697Sbapt for (j = 0; j < _UC_MAXSHELLS && 473282697Sbapt system_shells[j] != NULL; j++) 474282697Sbapt sbuf_printf(buf, "%s\"%s\"", j ? 475282697Sbapt "," : "", system_shells[j]); 476282697Sbapt quote = 0; 477282697Sbapt break; 478282697Sbapt case _UC_DEFAULTSHELL: 479286196Sbapt sbuf_cat(buf, cnf->shell_default ? 480286196Sbapt cnf->shell_default : bourne_shell); 481282697Sbapt break; 482282697Sbapt case _UC_DEFAULTGROUP: 483286196Sbapt sbuf_cat(buf, cnf->default_group ? 484286196Sbapt cnf->default_group : ""); 485282697Sbapt break; 486282697Sbapt case _UC_EXTRAGROUPS: 487286196Sbapt for (j = 0; cnf->groups != NULL && 488286196Sbapt j < (int)cnf->groups->sl_cur; j++) 489282697Sbapt sbuf_printf(buf, "%s\"%s\"", j ? 490286196Sbapt "," : "", cnf->groups->sl_str[j]); 491282697Sbapt quote = 0; 492282697Sbapt break; 493282697Sbapt case _UC_DEFAULTCLASS: 494286196Sbapt sbuf_cat(buf, cnf->default_class ? 495286196Sbapt cnf->default_class : ""); 496282697Sbapt break; 497282697Sbapt case _UC_MINUID: 498286196Sbapt sbuf_printf(buf, "%ju", (uintmax_t)cnf->min_uid); 499282697Sbapt quote = 0; 500282697Sbapt break; 501282697Sbapt case _UC_MAXUID: 502286196Sbapt sbuf_printf(buf, "%ju", (uintmax_t)cnf->max_uid); 503282697Sbapt quote = 0; 504282697Sbapt break; 505282697Sbapt case _UC_MINGID: 506286196Sbapt sbuf_printf(buf, "%ju", (uintmax_t)cnf->min_gid); 507282697Sbapt quote = 0; 508282697Sbapt break; 509282697Sbapt case _UC_MAXGID: 510286196Sbapt sbuf_printf(buf, "%ju", (uintmax_t)cnf->max_gid); 511282697Sbapt quote = 0; 512282697Sbapt break; 513282697Sbapt case _UC_EXPIRE: 514286211Sbapt sbuf_printf(buf, "%jd", (intmax_t)cnf->expire_days); 515282697Sbapt quote = 0; 516282697Sbapt break; 517282697Sbapt case _UC_PASSWORD: 518286211Sbapt sbuf_printf(buf, "%jd", (intmax_t)cnf->password_days); 519282697Sbapt quote = 0; 520282697Sbapt break; 521282697Sbapt case _UC_NONE: 522282697Sbapt break; 523282697Sbapt } 524282697Sbapt sbuf_finish(buf); 52520253Sjoerg 526282697Sbapt if (comments[i]) 527282697Sbapt fputs(comments[i], fp); 52820253Sjoerg 529282697Sbapt if (*kwds[i]) { 530282697Sbapt if (quote) 531282697Sbapt fprintf(fp, "%s = \"%s\"\n", kwds[i], 532282697Sbapt sbuf_data(buf)); 533282697Sbapt else 534282697Sbapt fprintf(fp, "%s = %s\n", kwds[i], sbuf_data(buf)); 53520253Sjoerg#if debugging 536282697Sbapt printf("WROTE: %s = %s\n", kwds[i], sbuf_data(buf)); 53720253Sjoerg#endif 53820253Sjoerg } 53920253Sjoerg } 540282697Sbapt sbuf_delete(buf); 541282697Sbapt return (fclose(fp) != EOF); 54220253Sjoerg} 543