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/10/usr.sbin/pw/pw_conf.c 326849 2017-12-14 13:10:22Z eugen $"; 3030259Scharnier#endif /* not lint */ 3130259Scharnier 32285092Sbapt#include <sys/types.h> 33285092Sbapt#include <sys/sbuf.h> 34287084Sbapt 35287084Sbapt#include <err.h> 36287084Sbapt#include <fcntl.h> 3720253Sjoerg#include <string.h> 38287084Sbapt#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 */ 108287084Sbapt 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; 189305750Sasomers } 190305750Sasomers return dflt; 191305750Sasomers} 19220253Sjoerg 193305750Sasomersint 194305750Sasomerspasswd_val(char const * str, int dflt) 195305750Sasomers{ 196305750Sasomers if ((str = unquote(str)) != NULL) { 197305750Sasomers int i; 198305750Sasomers 199305750Sasomers for (i = 0; booltrue[i]; i++) 200305750Sasomers if (strcmp(str, booltrue[i]) == 0) 201326849Seugen return P_YES; 202305750Sasomers for (i = 0; boolfalse[i]; i++) 203305750Sasomers if (strcmp(str, boolfalse[i]) == 0) 204326849Seugen return P_NO; 205305750Sasomers 20620253Sjoerg /* 20720253Sjoerg * Special cases for defaultpassword 20820253Sjoerg */ 20920253Sjoerg if (strcmp(str, "random") == 0) 210326849Seugen return P_RANDOM; 21120253Sjoerg if (strcmp(str, "none") == 0) 212326849Seugen return P_NONE; 213305750Sasomers 214305750Sasomers 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{ 233285092Sbapt char *q; 23420253Sjoerg 235285092Sbapt if ((p = unquote(p)) == NULL) 236285092Sbapt return (NULL); 23720253Sjoerg 238285092Sbapt if ((q = strdup(p)) == NULL) 239285092Sbapt err(1, "strdup()"); 240285092Sbapt 241285092Sbapt return (q); 24220253Sjoerg} 24320253Sjoerg 24420253Sjoergstruct userconf * 24520253Sjoergread_userconfig(char const * file) 24620253Sjoerg{ 247268346Sbapt FILE *fp; 248268346Sbapt char *buf, *p; 249287084Sbapt const char *errstr; 250268346Sbapt size_t linecap; 251268346Sbapt ssize_t linelen; 25220253Sjoerg 253268346Sbapt buf = NULL; 254268346Sbapt linecap = 0; 255268346Sbapt 25620253Sjoerg if (file == NULL) 25720253Sjoerg file = _PATH_PW_CONF; 258268346Sbapt 259285092Sbapt if ((fp = fopen(file, "r")) == NULL) 260285092Sbapt return (&config); 26120747Sdavidn 262285092Sbapt while ((linelen = getline(&buf, &linecap, fp)) > 0) { 263285092Sbapt if (*buf && (p = strtok(buf, " \t\r\n=")) != NULL && *p != '#') { 264285092Sbapt static char const toks[] = " \t\r\n,="; 265285092Sbapt char *q = strtok(NULL, toks); 266285092Sbapt int i = 0; 267285092Sbapt mode_t *modeset; 268285092Sbapt 269285092Sbapt while (i < _UC_FIELDS && strcmp(p, kwds[i]) != 0) 270285092Sbapt ++i; 27120253Sjoerg#if debugging 272285092Sbapt if (i == _UC_FIELDS) 273285092Sbapt printf("Got unknown kwd `%s' val=`%s'\n", p, q ? q : ""); 274285092Sbapt else 275285092Sbapt printf("Got kwd[%s]=%s\n", p, q); 27620253Sjoerg#endif 277285092Sbapt switch (i) { 278285092Sbapt case _UC_DEFAULTPWD: 279305750Sasomers config.default_password = passwd_val(q, 1); 280285092Sbapt break; 281285092Sbapt case _UC_REUSEUID: 282285092Sbapt config.reuse_uids = boolean_val(q, 0); 283285092Sbapt break; 284285092Sbapt case _UC_REUSEGID: 285285092Sbapt config.reuse_gids = boolean_val(q, 0); 286285092Sbapt break; 287285092Sbapt case _UC_NISPASSWD: 288285092Sbapt config.nispasswd = (q == NULL || !boolean_val(q, 1)) 289285092Sbapt ? NULL : newstr(q); 290285092Sbapt break; 291285092Sbapt case _UC_DOTDIR: 292285092Sbapt config.dotdir = (q == NULL || !boolean_val(q, 1)) 293285092Sbapt ? NULL : newstr(q); 294285092Sbapt break; 29520747Sdavidn case _UC_NEWMAIL: 296285092Sbapt config.newmail = (q == NULL || !boolean_val(q, 1)) 297285092Sbapt ? NULL : newstr(q); 298285092Sbapt break; 299285092Sbapt case _UC_LOGFILE: 300285092Sbapt config.logfile = (q == NULL || !boolean_val(q, 1)) 301285092Sbapt ? NULL : newstr(q); 302285092Sbapt break; 303285092Sbapt case _UC_HOMEROOT: 304285092Sbapt config.home = (q == NULL || !boolean_val(q, 1)) 305285092Sbapt ? "/home" : newstr(q); 306285092Sbapt break; 307285092Sbapt case _UC_HOMEMODE: 308285092Sbapt modeset = setmode(q); 309285092Sbapt config.homemode = (q == NULL || !boolean_val(q, 1)) 310285092Sbapt ? _DEF_DIRMODE : getmode(modeset, _DEF_DIRMODE); 311285092Sbapt free(modeset); 312285092Sbapt break; 313285092Sbapt case _UC_SHELLPATH: 314285092Sbapt config.shelldir = (q == NULL || !boolean_val(q, 1)) 315285092Sbapt ? "/bin" : newstr(q); 316285092Sbapt break; 317285092Sbapt case _UC_SHELLS: 318285092Sbapt for (i = 0; i < _UC_MAXSHELLS && q != NULL; i++, q = strtok(NULL, toks)) 319285092Sbapt system_shells[i] = newstr(q); 320285092Sbapt if (i > 0) 321285092Sbapt while (i < _UC_MAXSHELLS) 322285092Sbapt system_shells[i++] = NULL; 323285092Sbapt break; 324285092Sbapt case _UC_DEFAULTSHELL: 325285092Sbapt config.shell_default = (q == NULL || !boolean_val(q, 1)) 326285092Sbapt ? (char *) bourne_shell : newstr(q); 327285092Sbapt break; 328285092Sbapt case _UC_DEFAULTGROUP: 329285092Sbapt q = unquote(q); 330285092Sbapt config.default_group = (q == NULL || !boolean_val(q, 1) || GETGRNAM(q) == NULL) 331285092Sbapt ? NULL : newstr(q); 332285092Sbapt break; 333285092Sbapt case _UC_EXTRAGROUPS: 334292965Sbapt while ((q = strtok(NULL, toks)) != NULL) { 335287084Sbapt if (config.groups == NULL) 336287084Sbapt config.groups = sl_init(); 337287084Sbapt sl_add(config.groups, newstr(q)); 33820253Sjoerg } 339285092Sbapt break; 340285092Sbapt case _UC_DEFAULTCLASS: 341285092Sbapt config.default_class = (q == NULL || !boolean_val(q, 1)) 342285092Sbapt ? NULL : newstr(q); 343285092Sbapt break; 344285092Sbapt case _UC_MINUID: 345287084Sbapt if ((q = unquote(q)) != NULL) { 346287084Sbapt config.min_uid = strtounum(q, 0, 347287084Sbapt UID_MAX, &errstr); 348287084Sbapt if (errstr) 349287084Sbapt warnx("Invalid min_uid: '%s';" 350287084Sbapt " ignoring", q); 351287084Sbapt } 352285092Sbapt break; 353285092Sbapt case _UC_MAXUID: 354287084Sbapt if ((q = unquote(q)) != NULL) { 355287084Sbapt config.max_uid = strtounum(q, 0, 356287084Sbapt UID_MAX, &errstr); 357287084Sbapt if (errstr) 358287084Sbapt warnx("Invalid max_uid: '%s';" 359287084Sbapt " ignoring", q); 360287084Sbapt } 361285092Sbapt break; 362285092Sbapt case _UC_MINGID: 363287084Sbapt if ((q = unquote(q)) != NULL) { 364287084Sbapt config.min_gid = strtounum(q, 0, 365287084Sbapt GID_MAX, &errstr); 366287084Sbapt if (errstr) 367287084Sbapt warnx("Invalid min_gid: '%s';" 368287084Sbapt " ignoring", q); 369287084Sbapt } 370285092Sbapt break; 371285092Sbapt case _UC_MAXGID: 372287084Sbapt if ((q = unquote(q)) != NULL) { 373287084Sbapt config.max_gid = strtounum(q, 0, 374287084Sbapt GID_MAX, &errstr); 375287084Sbapt if (errstr) 376287084Sbapt warnx("Invalid max_gid: '%s';" 377287084Sbapt " ignoring", q); 378287084Sbapt } 379285092Sbapt break; 380285092Sbapt case _UC_EXPIRE: 381287084Sbapt if ((q = unquote(q)) != NULL) { 382287084Sbapt config.expire_days = strtonum(q, 0, 383287084Sbapt INT_MAX, &errstr); 384287084Sbapt if (errstr) 385287084Sbapt warnx("Invalid expire days:" 386287084Sbapt " '%s'; ignoring", q); 387287084Sbapt } 388285092Sbapt break; 389285092Sbapt case _UC_PASSWORD: 390287084Sbapt if ((q = unquote(q)) != NULL) { 391287084Sbapt config.password_days = strtonum(q, 0, 392287084Sbapt INT_MAX, &errstr); 393287084Sbapt if (errstr) 394287084Sbapt warnx("Invalid password days:" 395287084Sbapt " '%s'; ignoring", q); 396287084Sbapt } 397285092Sbapt break; 398285092Sbapt case _UC_FIELDS: 399285092Sbapt case _UC_NONE: 400285092Sbapt break; 40120253Sjoerg } 40220253Sjoerg } 40320253Sjoerg } 404285092Sbapt free(buf); 405285092Sbapt fclose(fp); 406285092Sbapt 407285092Sbapt return (&config); 40820253Sjoerg} 40920253Sjoerg 41020253Sjoerg 41120253Sjoergint 412287084Sbaptwrite_userconfig(struct userconf *cnf, const char *file) 41320253Sjoerg{ 41420253Sjoerg int fd; 415285092Sbapt int i, j; 416285092Sbapt struct sbuf *buf; 417285092Sbapt FILE *fp; 41820253Sjoerg 41920253Sjoerg if (file == NULL) 42020253Sjoerg file = _PATH_PW_CONF; 42120253Sjoerg 422285092Sbapt if ((fd = open(file, O_CREAT|O_RDWR|O_TRUNC|O_EXLOCK, 0644)) == -1) 423285092Sbapt return (0); 42420253Sjoerg 425285092Sbapt if ((fp = fdopen(fd, "w")) == NULL) { 426285092Sbapt close(fd); 427285092Sbapt return (0); 428285092Sbapt } 429285092Sbapt 430285092Sbapt buf = sbuf_new_auto(); 431285092Sbapt for (i = _UC_NONE; i < _UC_FIELDS; i++) { 432285092Sbapt int quote = 1; 43320253Sjoerg 434285092Sbapt sbuf_clear(buf); 435285092Sbapt switch (i) { 436285092Sbapt case _UC_DEFAULTPWD: 437287084Sbapt sbuf_cat(buf, boolean_str(cnf->default_password)); 438285092Sbapt break; 439285092Sbapt case _UC_REUSEUID: 440287084Sbapt sbuf_cat(buf, boolean_str(cnf->reuse_uids)); 441285092Sbapt break; 442285092Sbapt case _UC_REUSEGID: 443287084Sbapt sbuf_cat(buf, boolean_str(cnf->reuse_gids)); 444285092Sbapt break; 445285092Sbapt case _UC_NISPASSWD: 446287084Sbapt sbuf_cat(buf, cnf->nispasswd ? cnf->nispasswd : ""); 447285092Sbapt quote = 0; 448285092Sbapt break; 449285092Sbapt case _UC_DOTDIR: 450287084Sbapt sbuf_cat(buf, cnf->dotdir ? cnf->dotdir : 451285092Sbapt boolean_str(0)); 452285092Sbapt break; 453285092Sbapt case _UC_NEWMAIL: 454287084Sbapt sbuf_cat(buf, cnf->newmail ? cnf->newmail : 455285092Sbapt boolean_str(0)); 456285092Sbapt break; 457285092Sbapt case _UC_LOGFILE: 458287084Sbapt sbuf_cat(buf, cnf->logfile ? cnf->logfile : 459285092Sbapt boolean_str(0)); 460285092Sbapt break; 461285092Sbapt case _UC_HOMEROOT: 462287084Sbapt sbuf_cat(buf, cnf->home); 463285092Sbapt break; 464285092Sbapt case _UC_HOMEMODE: 465287084Sbapt sbuf_printf(buf, "%04o", cnf->homemode); 466285092Sbapt quote = 0; 467285092Sbapt break; 468285092Sbapt case _UC_SHELLPATH: 469287084Sbapt sbuf_cat(buf, cnf->shelldir); 470285092Sbapt break; 471285092Sbapt case _UC_SHELLS: 472285092Sbapt for (j = 0; j < _UC_MAXSHELLS && 473285092Sbapt system_shells[j] != NULL; j++) 474285092Sbapt sbuf_printf(buf, "%s\"%s\"", j ? 475285092Sbapt "," : "", system_shells[j]); 476285092Sbapt quote = 0; 477285092Sbapt break; 478285092Sbapt case _UC_DEFAULTSHELL: 479287084Sbapt sbuf_cat(buf, cnf->shell_default ? 480287084Sbapt cnf->shell_default : bourne_shell); 481285092Sbapt break; 482285092Sbapt case _UC_DEFAULTGROUP: 483287084Sbapt sbuf_cat(buf, cnf->default_group ? 484287084Sbapt cnf->default_group : ""); 485285092Sbapt break; 486285092Sbapt case _UC_EXTRAGROUPS: 487287084Sbapt for (j = 0; cnf->groups != NULL && 488287084Sbapt j < (int)cnf->groups->sl_cur; j++) 489285092Sbapt sbuf_printf(buf, "%s\"%s\"", j ? 490287084Sbapt "," : "", cnf->groups->sl_str[j]); 491285092Sbapt quote = 0; 492285092Sbapt break; 493285092Sbapt case _UC_DEFAULTCLASS: 494287084Sbapt sbuf_cat(buf, cnf->default_class ? 495287084Sbapt cnf->default_class : ""); 496285092Sbapt break; 497285092Sbapt case _UC_MINUID: 498287084Sbapt sbuf_printf(buf, "%ju", (uintmax_t)cnf->min_uid); 499285092Sbapt quote = 0; 500285092Sbapt break; 501285092Sbapt case _UC_MAXUID: 502287084Sbapt sbuf_printf(buf, "%ju", (uintmax_t)cnf->max_uid); 503285092Sbapt quote = 0; 504285092Sbapt break; 505285092Sbapt case _UC_MINGID: 506287084Sbapt sbuf_printf(buf, "%ju", (uintmax_t)cnf->min_gid); 507285092Sbapt quote = 0; 508285092Sbapt break; 509285092Sbapt case _UC_MAXGID: 510287084Sbapt sbuf_printf(buf, "%ju", (uintmax_t)cnf->max_gid); 511285092Sbapt quote = 0; 512285092Sbapt break; 513285092Sbapt case _UC_EXPIRE: 514287084Sbapt sbuf_printf(buf, "%jd", (intmax_t)cnf->expire_days); 515285092Sbapt quote = 0; 516285092Sbapt break; 517285092Sbapt case _UC_PASSWORD: 518287084Sbapt sbuf_printf(buf, "%jd", (intmax_t)cnf->password_days); 519285092Sbapt quote = 0; 520285092Sbapt break; 521285092Sbapt case _UC_NONE: 522285092Sbapt break; 523285092Sbapt } 524285092Sbapt sbuf_finish(buf); 52520253Sjoerg 526285092Sbapt if (comments[i]) 527285092Sbapt fputs(comments[i], fp); 52820253Sjoerg 529285092Sbapt if (*kwds[i]) { 530285092Sbapt if (quote) 531285092Sbapt fprintf(fp, "%s = \"%s\"\n", kwds[i], 532285092Sbapt sbuf_data(buf)); 533285092Sbapt else 534285092Sbapt fprintf(fp, "%s = %s\n", kwds[i], sbuf_data(buf)); 53520253Sjoerg#if debugging 536285092Sbapt printf("WROTE: %s = %s\n", kwds[i], sbuf_data(buf)); 53720253Sjoerg#endif 53820253Sjoerg } 53920253Sjoerg } 540285092Sbapt sbuf_delete(buf); 541285092Sbapt return (fclose(fp) != EOF); 54220253Sjoerg} 543