pw_conf.c revision 283818
1183593Sjkoshy/*- 2183593Sjkoshy * Copyright (C) 1996 3183593Sjkoshy * David L. Nugent. All rights reserved. 4183593Sjkoshy * 5183593Sjkoshy * Redistribution and use in source and binary forms, with or without 6183593Sjkoshy * modification, are permitted provided that the following conditions 7183593Sjkoshy * are met: 8183593Sjkoshy * 1. Redistributions of source code must retain the above copyright 9183593Sjkoshy * notice, this list of conditions and the following disclaimer. 10183593Sjkoshy * 2. Redistributions in binary form must reproduce the above copyright 11183593Sjkoshy * notice, this list of conditions and the following disclaimer in the 12231871Sbrueffer * documentation and/or other materials provided with the distribution. 13231871Sbrueffer * 14231871Sbrueffer * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND 15231871Sbrueffer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16231871Sbrueffer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17231871Sbrueffer * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE 18231871Sbrueffer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19231871Sbrueffer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20231871Sbrueffer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21231871Sbrueffer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22231871Sbrueffer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23183593Sjkoshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24183593Sjkoshy * SUCH DAMAGE. 25183593Sjkoshy */ 26184892Sjkoshy 27206622Suqs#ifndef lint 28183593Sjkoshystatic const char rcsid[] = 29183593Sjkoshy "$FreeBSD: head/usr.sbin/pw/pw_conf.c 283818 2015-05-31 12:04:06Z bapt $"; 30183593Sjkoshy#endif /* not lint */ 31183593Sjkoshy 32183593Sjkoshy#include <sys/types.h> 33183593Sjkoshy#include <sys/sbuf.h> 34183593Sjkoshy#include <string.h> 35183593Sjkoshy#include <ctype.h> 36183593Sjkoshy#include <fcntl.h> 37183593Sjkoshy#include <err.h> 38183593Sjkoshy 39183593Sjkoshy#include "pw.h" 40183593Sjkoshy 41183593Sjkoshy#define debugging 0 42183593Sjkoshy 43183593Sjkoshyenum { 44183593Sjkoshy _UC_NONE, 45183593Sjkoshy _UC_DEFAULTPWD, 46183593Sjkoshy _UC_REUSEUID, 47183593Sjkoshy _UC_REUSEGID, 48183593Sjkoshy _UC_NISPASSWD, 49183593Sjkoshy _UC_DOTDIR, 50183593Sjkoshy _UC_NEWMAIL, 51183593Sjkoshy _UC_LOGFILE, 52208595Suqs _UC_HOMEROOT, 53208595Suqs _UC_HOMEMODE, 54208595Suqs _UC_SHELLPATH, 55183593Sjkoshy _UC_SHELLS, 56208595Suqs _UC_DEFAULTSHELL, 57183593Sjkoshy _UC_DEFAULTGROUP, 58183593Sjkoshy _UC_EXTRAGROUPS, 59183593Sjkoshy _UC_DEFAULTCLASS, 60183593Sjkoshy _UC_MINUID, 61183593Sjkoshy _UC_MAXUID, 62183593Sjkoshy _UC_MINGID, 63183593Sjkoshy _UC_MAXGID, 64183593Sjkoshy _UC_EXPIRE, 65183593Sjkoshy _UC_PASSWORD, 66183593Sjkoshy _UC_FIELDS 67183593Sjkoshy}; 68183593Sjkoshy 69183593Sjkoshystatic char bourne_shell[] = "sh"; 70183593Sjkoshy 71183593Sjkoshystatic char *system_shells[_UC_MAXSHELLS] = 72183593Sjkoshy{ 73183593Sjkoshy bourne_shell, 74183593Sjkoshy "csh", 75183593Sjkoshy "tcsh" 76183593Sjkoshy}; 77183593Sjkoshy 78183593Sjkoshystatic char const *booltrue[] = 79183593Sjkoshy{ 80183593Sjkoshy "yes", "true", "1", "on", NULL 81183593Sjkoshy}; 82183593Sjkoshystatic char const *boolfalse[] = 83183593Sjkoshy{ 84183593Sjkoshy "no", "false", "0", "off", NULL 85183593Sjkoshy}; 86183593Sjkoshy 87183593Sjkoshystatic struct userconf config = 88196449Sjkoshy{ 89183593Sjkoshy 0, /* Default password for new users? (nologin) */ 90183593Sjkoshy 0, /* Reuse uids? */ 91183593Sjkoshy 0, /* Reuse gids? */ 92183593Sjkoshy NULL, /* NIS version of the passwd file */ 93183593Sjkoshy "/usr/share/skel", /* Where to obtain skeleton files */ 94196449Sjkoshy NULL, /* Mail to send to new accounts */ 95183593Sjkoshy "/var/log/userlog", /* Where to log changes */ 96183593Sjkoshy "/home", /* Where to create home directory */ 97183593Sjkoshy _DEF_DIRMODE, /* Home directory perms, modified by umask */ 98183593Sjkoshy "/bin", /* Where shells are located */ 99183593Sjkoshy system_shells, /* List of shells (first is default) */ 100183593Sjkoshy bourne_shell, /* Default shell */ 101183593Sjkoshy NULL, /* Default group name */ 102183593Sjkoshy NULL, /* Default (additional) groups */ 103183593Sjkoshy NULL, /* Default login class */ 104183593Sjkoshy 1000, 32000, /* Allowed range of uids */ 105183593Sjkoshy 1000, 32000, /* Allowed range of gids */ 106183593Sjkoshy 0, /* Days until account expires */ 107183593Sjkoshy 0, /* Days until password expires */ 108183593Sjkoshy 0 /* size of default_group array */ 109183593Sjkoshy}; 110183593Sjkoshy 111183593Sjkoshystatic char const *comments[_UC_FIELDS] = 112183593Sjkoshy{ 113183593Sjkoshy "#\n# pw.conf - user/group configuration defaults\n#\n", 114183593Sjkoshy "\n# Password for new users? no=nologin yes=loginid none=blank random=random\n", 115183593Sjkoshy "\n# Reuse gaps in uid sequence? (yes or no)\n", 116183593Sjkoshy "\n# Reuse gaps in gid sequence? (yes or no)\n", 117183593Sjkoshy "\n# Path to the NIS passwd file (blank or 'no' for none)\n", 118183593Sjkoshy "\n# Obtain default dotfiles from this directory\n", 119183593Sjkoshy "\n# Mail this file to new user (/etc/newuser.msg or no)\n", 120183593Sjkoshy "\n# Log add/change/remove information in this file\n", 121183593Sjkoshy "\n# Root directory in which $HOME directory is created\n", 122183593Sjkoshy "\n# Mode for the new $HOME directory, will be modified by umask\n", 123183593Sjkoshy "\n# Colon separated list of directories containing valid shells\n", 124183593Sjkoshy "\n# Comma separated list of available shells (without paths)\n", 125183593Sjkoshy "\n# Default shell (without path)\n", 126183593Sjkoshy "\n# Default group (leave blank for new group per user)\n", 127183593Sjkoshy "\n# Extra groups for new users\n", 128183593Sjkoshy "\n# Default login class for new users\n", 129183593Sjkoshy "\n# Range of valid default user ids\n", 130183593Sjkoshy NULL, 131183593Sjkoshy "\n# Range of valid default group ids\n", 132183593Sjkoshy NULL, 133183593Sjkoshy "\n# Days after which account expires (0=disabled)\n", 134183593Sjkoshy "\n# Days after which password expires (0=disabled)\n" 135183593Sjkoshy}; 136183593Sjkoshy 137183593Sjkoshystatic char const *kwds[] = 138183593Sjkoshy{ 139183593Sjkoshy "", 140183593Sjkoshy "defaultpasswd", 141183593Sjkoshy "reuseuids", 142183593Sjkoshy "reusegids", 143183593Sjkoshy "nispasswd", 144183593Sjkoshy "skeleton", 145183593Sjkoshy "newmail", 146183593Sjkoshy "logfile", 147183593Sjkoshy "home", 148183593Sjkoshy "homemode", 149183593Sjkoshy "shellpath", 150183593Sjkoshy "shells", 151183593Sjkoshy "defaultshell", 152183593Sjkoshy "defaultgroup", 153183593Sjkoshy "extragroups", 154183593Sjkoshy "defaultclass", 155183593Sjkoshy "minuid", 156183593Sjkoshy "maxuid", 157183593Sjkoshy "mingid", 158183593Sjkoshy "maxgid", 159183593Sjkoshy "expire_days", 160183593Sjkoshy "password_days", 161183593Sjkoshy NULL 162196449Sjkoshy}; 163183593Sjkoshy 164183593Sjkoshystatic char * 165183593Sjkoshyunquote(char const * str) 166183593Sjkoshy{ 167183593Sjkoshy if (str && (*str == '"' || *str == '\'')) { 168183593Sjkoshy char *p = strchr(str + 1, *str); 169183593Sjkoshy 170183593Sjkoshy if (p != NULL) 171183593Sjkoshy *p = '\0'; 172183593Sjkoshy return (char *) (*++str ? str : NULL); 173183593Sjkoshy } 174183593Sjkoshy return (char *) str; 175183593Sjkoshy} 176183593Sjkoshy 177183593Sjkoshyint 178183593Sjkoshyboolean_val(char const * str, int dflt) 179183593Sjkoshy{ 180183593Sjkoshy if ((str = unquote(str)) != NULL) { 181183593Sjkoshy int i; 182183593Sjkoshy 183233648Seadler for (i = 0; booltrue[i]; i++) 184183593Sjkoshy if (strcmp(str, booltrue[i]) == 0) 185183593Sjkoshy return 1; 186183593Sjkoshy for (i = 0; boolfalse[i]; i++) 187184917Sjkoshy if (strcmp(str, boolfalse[i]) == 0) 188183593Sjkoshy return 0; 189183593Sjkoshy 190184917Sjkoshy /* 191183593Sjkoshy * Special cases for defaultpassword 192183593Sjkoshy */ 193183593Sjkoshy if (strcmp(str, "random") == 0) 194184917Sjkoshy return -1; 195183593Sjkoshy if (strcmp(str, "none") == 0) 196233648Seadler return -2; 197183593Sjkoshy } 198184917Sjkoshy return dflt; 199183593Sjkoshy} 200183593Sjkoshy 201184917Sjkoshychar const * 202183593Sjkoshyboolean_str(int val) 203183593Sjkoshy{ 204183593Sjkoshy if (val == -1) 205183593Sjkoshy return "random"; 206184917Sjkoshy else if (val == -2) 207183593Sjkoshy return "none"; 208183593Sjkoshy else 209183593Sjkoshy return val ? booltrue[0] : boolfalse[0]; 210183593Sjkoshy} 211184917Sjkoshy 212183593Sjkoshychar * 213183593Sjkoshynewstr(char const * p) 214184917Sjkoshy{ 215183593Sjkoshy char *q; 216183593Sjkoshy 217184917Sjkoshy if ((p = unquote(p)) == NULL) 218183593Sjkoshy return (NULL); 219183593Sjkoshy 220183593Sjkoshy if ((q = strdup(p)) == NULL) 221183593Sjkoshy err(1, "strdup()"); 222184917Sjkoshy 223183593Sjkoshy return (q); 224183593Sjkoshy} 225184917Sjkoshy 226183593Sjkoshystruct userconf * 227183593Sjkoshyread_userconfig(char const * file) 228184917Sjkoshy{ 229183593Sjkoshy FILE *fp; 230183593Sjkoshy char *buf, *p; 231184917Sjkoshy size_t linecap; 232183593Sjkoshy ssize_t linelen; 233183593Sjkoshy 234184932Sjkoshy buf = NULL; 235184892Sjkoshy linecap = 0; 236183593Sjkoshy 237184892Sjkoshy config.numgroups = 200; 238183593Sjkoshy config.groups = calloc(config.numgroups, sizeof(char *)); 239184932Sjkoshy if (config.groups == NULL) 240184892Sjkoshy err(1, "calloc()"); 241183593Sjkoshy if (file == NULL) 242184892Sjkoshy file = _PATH_PW_CONF; 243183593Sjkoshy 244184917Sjkoshy if ((fp = fopen(file, "r")) == NULL) 245183593Sjkoshy return (&config); 246183593Sjkoshy 247184917Sjkoshy while ((linelen = getline(&buf, &linecap, fp)) > 0) { 248183593Sjkoshy if (*buf && (p = strtok(buf, " \t\r\n=")) != NULL && *p != '#') { 249183593Sjkoshy static char const toks[] = " \t\r\n,="; 250183593Sjkoshy char *q = strtok(NULL, toks); 251184917Sjkoshy int i = 0; 252183593Sjkoshy mode_t *modeset; 253183593Sjkoshy 254183593Sjkoshy while (i < _UC_FIELDS && strcmp(p, kwds[i]) != 0) 255184917Sjkoshy ++i; 256183593Sjkoshy#if debugging 257183593Sjkoshy if (i == _UC_FIELDS) 258184917Sjkoshy printf("Got unknown kwd `%s' val=`%s'\n", p, q ? q : ""); 259183593Sjkoshy else 260183593Sjkoshy printf("Got kwd[%s]=%s\n", p, q); 261184917Sjkoshy#endif 262183593Sjkoshy switch (i) { 263183593Sjkoshy case _UC_DEFAULTPWD: 264184917Sjkoshy config.default_password = boolean_val(q, 1); 265183593Sjkoshy break; 266183593Sjkoshy case _UC_REUSEUID: 267184917Sjkoshy config.reuse_uids = boolean_val(q, 0); 268183593Sjkoshy break; 269183593Sjkoshy case _UC_REUSEGID: 270184917Sjkoshy config.reuse_gids = boolean_val(q, 0); 271183593Sjkoshy break; 272183593Sjkoshy case _UC_NISPASSWD: 273183593Sjkoshy config.nispasswd = (q == NULL || !boolean_val(q, 1)) 274183593Sjkoshy ? NULL : newstr(q); 275183593Sjkoshy break; 276183593Sjkoshy case _UC_DOTDIR: 277183593Sjkoshy config.dotdir = (q == NULL || !boolean_val(q, 1)) 278183593Sjkoshy ? NULL : newstr(q); 279183593Sjkoshy break; 280183593Sjkoshy case _UC_NEWMAIL: 281183593Sjkoshy config.newmail = (q == NULL || !boolean_val(q, 1)) 282183593Sjkoshy ? NULL : newstr(q); 283183593Sjkoshy break; 284183593Sjkoshy case _UC_LOGFILE: 285183593Sjkoshy config.logfile = (q == NULL || !boolean_val(q, 1)) 286183593Sjkoshy ? NULL : newstr(q); 287184917Sjkoshy break; 288183593Sjkoshy case _UC_HOMEROOT: 289183593Sjkoshy config.home = (q == NULL || !boolean_val(q, 1)) 290183593Sjkoshy ? "/home" : newstr(q); 291183593Sjkoshy break; 292183593Sjkoshy case _UC_HOMEMODE: 293183593Sjkoshy modeset = setmode(q); 294183593Sjkoshy config.homemode = (q == NULL || !boolean_val(q, 1)) 295183593Sjkoshy ? _DEF_DIRMODE : getmode(modeset, _DEF_DIRMODE); 296183593Sjkoshy free(modeset); 297183593Sjkoshy break; 298183593Sjkoshy case _UC_SHELLPATH: 299183593Sjkoshy config.shelldir = (q == NULL || !boolean_val(q, 1)) 300183593Sjkoshy ? "/bin" : newstr(q); 301183593Sjkoshy break; 302183593Sjkoshy case _UC_SHELLS: 303183593Sjkoshy for (i = 0; i < _UC_MAXSHELLS && q != NULL; i++, q = strtok(NULL, toks)) 304183593Sjkoshy system_shells[i] = newstr(q); 305183593Sjkoshy if (i > 0) 306183593Sjkoshy while (i < _UC_MAXSHELLS) 307183593Sjkoshy system_shells[i++] = NULL; 308183593Sjkoshy break; 309183593Sjkoshy case _UC_DEFAULTSHELL: 310183593Sjkoshy config.shell_default = (q == NULL || !boolean_val(q, 1)) 311183593Sjkoshy ? (char *) bourne_shell : newstr(q); 312183593Sjkoshy break; 313183593Sjkoshy case _UC_DEFAULTGROUP: 314183593Sjkoshy q = unquote(q); 315183593Sjkoshy config.default_group = (q == NULL || !boolean_val(q, 1) || GETGRNAM(q) == NULL) 316183593Sjkoshy ? NULL : newstr(q); 317183593Sjkoshy break; 318183593Sjkoshy case _UC_EXTRAGROUPS: 319183593Sjkoshy for (i = 0; q != NULL; q = strtok(NULL, toks)) { 320183593Sjkoshy if (extendarray(&config.groups, &config.numgroups, i + 2) != -1) 321183593Sjkoshy config.groups[i++] = newstr(q); 322183593Sjkoshy } 323183593Sjkoshy if (i > 0) 324183593Sjkoshy while (i < config.numgroups) 325183593Sjkoshy config.groups[i++] = NULL; 326183593Sjkoshy break; 327183593Sjkoshy case _UC_DEFAULTCLASS: 328183593Sjkoshy config.default_class = (q == NULL || !boolean_val(q, 1)) 329183593Sjkoshy ? NULL : newstr(q); 330183593Sjkoshy break; 331183593Sjkoshy case _UC_MINUID: 332183593Sjkoshy if ((q = unquote(q)) != NULL && isdigit(*q)) 333183593Sjkoshy config.min_uid = (uid_t) atol(q); 334183593Sjkoshy break; 335183593Sjkoshy case _UC_MAXUID: 336183593Sjkoshy if ((q = unquote(q)) != NULL && isdigit(*q)) 337183593Sjkoshy config.max_uid = (uid_t) atol(q); 338183593Sjkoshy break; 339183593Sjkoshy case _UC_MINGID: 340183593Sjkoshy if ((q = unquote(q)) != NULL && isdigit(*q)) 341183593Sjkoshy config.min_gid = (gid_t) atol(q); 342183593Sjkoshy break; 343183593Sjkoshy case _UC_MAXGID: 344183593Sjkoshy if ((q = unquote(q)) != NULL && isdigit(*q)) 345183593Sjkoshy config.max_gid = (gid_t) atol(q); 346183593Sjkoshy break; 347183593Sjkoshy case _UC_EXPIRE: 348183593Sjkoshy if ((q = unquote(q)) != NULL && isdigit(*q)) 349183593Sjkoshy config.expire_days = atoi(q); 350183593Sjkoshy break; 351196449Sjkoshy case _UC_PASSWORD: 352196449Sjkoshy if ((q = unquote(q)) != NULL && isdigit(*q)) 353183593Sjkoshy config.password_days = atoi(q); 354184917Sjkoshy break; 355183593Sjkoshy case _UC_FIELDS: 356185326Sjkoshy case _UC_NONE: 357183593Sjkoshy break; 358184917Sjkoshy } 359183593Sjkoshy } 360183593Sjkoshy } 361184917Sjkoshy free(buf); 362183593Sjkoshy fclose(fp); 363183593Sjkoshy 364183593Sjkoshy return (&config); 365183593Sjkoshy} 366183593Sjkoshy 367183593Sjkoshy 368183593Sjkoshyint 369183593Sjkoshywrite_userconfig(char const * file) 370183593Sjkoshy{ 371183593Sjkoshy int fd; 372183593Sjkoshy int i, j; 373183593Sjkoshy struct sbuf *buf; 374183593Sjkoshy FILE *fp; 375183593Sjkoshy 376183593Sjkoshy if (file == NULL) 377183593Sjkoshy file = _PATH_PW_CONF; 378183593Sjkoshy 379184917Sjkoshy if ((fd = open(file, O_CREAT|O_RDWR|O_TRUNC|O_EXLOCK, 0644)) == -1) 380183593Sjkoshy return (0); 381183593Sjkoshy 382184917Sjkoshy if ((fp = fdopen(fd, "w")) == NULL) { 383183593Sjkoshy close(fd); 384183593Sjkoshy return (0); 385184917Sjkoshy } 386183593Sjkoshy 387183593Sjkoshy buf = sbuf_new_auto(); 388184917Sjkoshy for (i = _UC_NONE; i < _UC_FIELDS; i++) { 389183593Sjkoshy int quote = 1; 390183593Sjkoshy 391184917Sjkoshy sbuf_clear(buf); 392183593Sjkoshy switch (i) { 393183593Sjkoshy case _UC_DEFAULTPWD: 394184917Sjkoshy sbuf_cat(buf, boolean_str(config.default_password)); 395183593Sjkoshy break; 396196449Sjkoshy case _UC_REUSEUID: 397183593Sjkoshy sbuf_cat(buf, boolean_str(config.reuse_uids)); 398183593Sjkoshy break; 399183593Sjkoshy case _UC_REUSEGID: 400183593Sjkoshy sbuf_cat(buf, boolean_str(config.reuse_gids)); 401183593Sjkoshy break; 402196449Sjkoshy case _UC_NISPASSWD: 403183593Sjkoshy sbuf_cat(buf, config.nispasswd ? config.nispasswd : 404183593Sjkoshy ""); 405184917Sjkoshy quote = 0; 406183593Sjkoshy break; 407183593Sjkoshy case _UC_DOTDIR: 408183593Sjkoshy sbuf_cat(buf, config.dotdir ? config.dotdir : 409183593Sjkoshy boolean_str(0)); 410184917Sjkoshy break; 411183593Sjkoshy case _UC_NEWMAIL: 412183593Sjkoshy sbuf_cat(buf, config.newmail ? config.newmail : 413184917Sjkoshy boolean_str(0)); 414183593Sjkoshy break; 415183593Sjkoshy case _UC_LOGFILE: 416183593Sjkoshy sbuf_cat(buf, config.logfile ? config.logfile : 417183593Sjkoshy boolean_str(0)); 418183593Sjkoshy break; 419183593Sjkoshy case _UC_HOMEROOT: 420183593Sjkoshy sbuf_cat(buf, config.home); 421183593Sjkoshy break; 422183593Sjkoshy case _UC_HOMEMODE: 423183593Sjkoshy sbuf_printf(buf, "%04o", config.homemode); 424183593Sjkoshy quote = 0; 425183593Sjkoshy break; 426183593Sjkoshy case _UC_SHELLPATH: 427183593Sjkoshy sbuf_cat(buf, config.shelldir); 428183593Sjkoshy break; 429183593Sjkoshy case _UC_SHELLS: 430184917Sjkoshy for (j = 0; j < _UC_MAXSHELLS && 431183593Sjkoshy system_shells[j] != NULL; j++) 432183593Sjkoshy sbuf_printf(buf, "%s\"%s\"", j ? 433183593Sjkoshy "," : "", system_shells[j]); 434183593Sjkoshy quote = 0; 435184917Sjkoshy break; 436183593Sjkoshy case _UC_DEFAULTSHELL: 437183593Sjkoshy sbuf_cat(buf, config.shell_default ? 438183593Sjkoshy config.shell_default : bourne_shell); 439184917Sjkoshy break; 440183593Sjkoshy case _UC_DEFAULTGROUP: 441183593Sjkoshy sbuf_cat(buf, config.default_group ? 442183593Sjkoshy config.default_group : ""); 443183593Sjkoshy break; 444183593Sjkoshy case _UC_EXTRAGROUPS: 445183593Sjkoshy for (j = 0; j < config.numgroups && 446183593Sjkoshy config.groups[j] != NULL; j++) 447183593Sjkoshy sbuf_printf(buf, "%s\"%s\"", j ? 448183593Sjkoshy "," : "", config.groups[j]); 449183593Sjkoshy quote = 0; 450183593Sjkoshy break; 451183593Sjkoshy case _UC_DEFAULTCLASS: 452183593Sjkoshy sbuf_cat(buf, config.default_class ? 453183593Sjkoshy config.default_class : ""); 454184917Sjkoshy break; 455183593Sjkoshy case _UC_MINUID: 456183593Sjkoshy sbuf_printf(buf, "%lu", (unsigned long) config.min_uid); 457184917Sjkoshy quote = 0; 458183593Sjkoshy break; 459183593Sjkoshy case _UC_MAXUID: 460183593Sjkoshy sbuf_printf(buf, "%lu", (unsigned long) config.max_uid); 461184917Sjkoshy quote = 0; 462226436Seadler break; 463196449Sjkoshy case _UC_MINGID: 464183593Sjkoshy sbuf_printf(buf, "%lu", (unsigned long) config.min_gid); 465184917Sjkoshy quote = 0; 466183593Sjkoshy break; 467183593Sjkoshy case _UC_MAXGID: 468183593Sjkoshy sbuf_printf(buf, "%lu", (unsigned long) config.max_gid); 469184917Sjkoshy quote = 0; 470183593Sjkoshy break; 471183593Sjkoshy case _UC_EXPIRE: 472184917Sjkoshy sbuf_printf(buf, "%d", config.expire_days); 473183593Sjkoshy quote = 0; 474183593Sjkoshy break; 475184917Sjkoshy case _UC_PASSWORD: 476183593Sjkoshy sbuf_printf(buf, "%d", config.password_days); 477183593Sjkoshy quote = 0; 478184917Sjkoshy break; 479184892Sjkoshy case _UC_NONE: 480183593Sjkoshy break; 481184892Sjkoshy } 482183593Sjkoshy sbuf_finish(buf); 483184917Sjkoshy 484183593Sjkoshy if (comments[i]) 485183593Sjkoshy fputs(comments[i], fp); 486183593Sjkoshy 487183593Sjkoshy if (*kwds[i]) { 488183593Sjkoshy if (quote) 489183593Sjkoshy fprintf(fp, "%s = \"%s\"\n", kwds[i], 490183593Sjkoshy sbuf_data(buf)); 491183593Sjkoshy else 492183593Sjkoshy fprintf(fp, "%s = %s\n", kwds[i], sbuf_data(buf)); 493183593Sjkoshy#if debugging 494183593Sjkoshy printf("WROTE: %s = %s\n", kwds[i], sbuf_data(buf)); 495183593Sjkoshy#endif 496183593Sjkoshy } 497183593Sjkoshy } 498183593Sjkoshy sbuf_delete(buf); 499183593Sjkoshy return (fclose(fp) != EOF); 500183593Sjkoshy} 501183593Sjkoshy