pw_conf.c revision 81982
1264269Ssbruno/*- 2264269Ssbruno * Copyright (C) 1996 3264269Ssbruno * David L. Nugent. All rights reserved. 4264269Ssbruno * 5264269Ssbruno * Redistribution and use in source and binary forms, with or without 6264269Ssbruno * modification, are permitted provided that the following conditions 7264269Ssbruno * are met: 8264269Ssbruno * 1. Redistributions of source code must retain the above copyright 9264269Ssbruno * notice, this list of conditions and the following disclaimer. 10264269Ssbruno * 2. Redistributions in binary form must reproduce the above copyright 11264269Ssbruno * notice, this list of conditions and the following disclaimer in the 12264269Ssbruno * documentation and/or other materials provided with the distribution. 13264269Ssbruno * 14264269Ssbruno * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND 15264269Ssbruno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16264269Ssbruno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17264269Ssbruno * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE 18264269Ssbruno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19264269Ssbruno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20264269Ssbruno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21264269Ssbruno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22264269Ssbruno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23264269Ssbruno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24264269Ssbruno * SUCH DAMAGE. 25264269Ssbruno */ 26264269Ssbruno 27264269Ssbruno#ifndef lint 28264269Ssbrunostatic const char rcsid[] = 29264269Ssbruno "$FreeBSD: head/usr.sbin/pw/pw_conf.c 81982 2001-08-20 15:09:34Z brian $"; 30264269Ssbruno#endif /* not lint */ 31264269Ssbruno 32264269Ssbruno#include <string.h> 33264269Ssbruno#include <ctype.h> 34264269Ssbruno#include <fcntl.h> 35264269Ssbruno 36264269Ssbruno#include "pw.h" 37264269Ssbruno 38264269Ssbruno#define debugging 0 39264269Ssbruno 40264269Ssbrunoenum { 41264269Ssbruno _UC_NONE, 42264269Ssbruno _UC_DEFAULTPWD, 43264269Ssbruno _UC_REUSEUID, 44264269Ssbruno _UC_REUSEGID, 45264269Ssbruno _UC_NISPASSWD, 46264269Ssbruno _UC_DOTDIR, 47264269Ssbruno _UC_NEWMAIL, 48264269Ssbruno _UC_LOGFILE, 49264269Ssbruno _UC_HOMEROOT, 50264269Ssbruno _UC_SHELLPATH, 51264269Ssbruno _UC_SHELLS, 52264269Ssbruno _UC_DEFAULTSHELL, 53264269Ssbruno _UC_DEFAULTGROUP, 54264269Ssbruno _UC_EXTRAGROUPS, 55264269Ssbruno _UC_DEFAULTCLASS, 56264269Ssbruno _UC_MINUID, 57264269Ssbruno _UC_MAXUID, 58264269Ssbruno _UC_MINGID, 59264269Ssbruno _UC_MAXGID, 60264269Ssbruno _UC_EXPIRE, 61264269Ssbruno _UC_PASSWORD, 62264269Ssbruno _UC_FIELDS 63264269Ssbruno}; 64264269Ssbruno 65264269Ssbrunostatic char bourne_shell[] = "sh"; 66264269Ssbruno 67264269Ssbrunostatic char *system_shells[_UC_MAXSHELLS] = 68264269Ssbruno{ 69264269Ssbruno bourne_shell, 70264269Ssbruno "csh", 71264269Ssbruno "tcsh" 72264269Ssbruno}; 73264269Ssbruno 74264269Ssbrunostatic char const *booltrue[] = 75264269Ssbruno{ 76264269Ssbruno "yes", "true", "1", "on", NULL 77264269Ssbruno}; 78264269Ssbrunostatic char const *boolfalse[] = 79264269Ssbruno{ 80264269Ssbruno "no", "false", "0", "off", NULL 81264269Ssbruno}; 82264269Ssbruno 83264269Ssbrunostatic struct userconf config = 84264269Ssbruno{ 85264269Ssbruno 0, /* Default password for new users? (nologin) */ 86264269Ssbruno 0, /* Reuse uids? */ 87264269Ssbruno 0, /* Reuse gids? */ 88264269Ssbruno NULL, /* NIS version of the passwd file */ 89264269Ssbruno "/usr/share/skel", /* Where to obtain skeleton files */ 90264269Ssbruno NULL, /* Mail to send to new accounts */ 91264269Ssbruno "/var/log/userlog", /* Where to log changes */ 92264269Ssbruno "/home", /* Where to create home directory */ 93264269Ssbruno "/bin", /* Where shells are located */ 94264269Ssbruno system_shells, /* List of shells (first is default) */ 95264269Ssbruno bourne_shell, /* Default shell */ 96264269Ssbruno NULL, /* Default group name */ 97264269Ssbruno NULL, /* Default (additional) groups */ 98264269Ssbruno NULL, /* Default login class */ 99264269Ssbruno 1000, 32000, /* Allowed range of uids */ 100264269Ssbruno 1000, 32000, /* Allowed range of gids */ 101264269Ssbruno 0, /* Days until account expires */ 102264269Ssbruno 0, /* Days until password expires */ 103264269Ssbruno 0 /* size of default_group array */ 104264269Ssbruno}; 105264269Ssbruno 106264269Ssbrunostatic char const *comments[_UC_FIELDS] = 107264269Ssbruno{ 108264269Ssbruno "#\n# pw.conf - user/group configuration defaults\n#\n", 109264269Ssbruno "\n# Password for new users? no=nologin yes=loginid none=blank random=random\n", 110264269Ssbruno "\n# Reuse gaps in uid sequence? (yes or no)\n", 111264269Ssbruno "\n# Reuse gaps in gid sequence? (yes or no)\n", 112264269Ssbruno "\n# Path to the NIS passwd file (blank or 'no' for none)\n", 113264269Ssbruno "\n# Obtain default dotfiles from this directory\n", 114264269Ssbruno "\n# Mail this file to new user (/etc/newuser.msg or no)\n", 115264269Ssbruno "\n# Log add/change/remove information in this file\n", 116264269Ssbruno "\n# Root directory in which $HOME directory is created\n", 117264269Ssbruno "\n# Colon separated list of directories containing valid shells\n", 118264269Ssbruno "\n# Comma separated list of available shells (without paths)\n", 119264269Ssbruno "\n# Default shell (without path)\n", 120264269Ssbruno "\n# Default group (leave blank for new group per user)\n", 121264269Ssbruno "\n# Extra groups for new users\n", 122264269Ssbruno "\n# Default login class for new users\n", 123264269Ssbruno "\n# Range of valid default user ids\n", 124264269Ssbruno NULL, 125264269Ssbruno "\n# Range of valid default group ids\n", 126264269Ssbruno NULL, 127264269Ssbruno "\n# Days after which account expires (0=disabled)\n", 128264269Ssbruno "\n# Days after which password expires (0=disabled)\n" 129264269Ssbruno}; 130264269Ssbruno 131264269Ssbrunostatic char const *kwds[] = 132264269Ssbruno{ 133264269Ssbruno "", 134264269Ssbruno "defaultpasswd", 135264269Ssbruno "reuseuids", 136264269Ssbruno "reusegids", 137264269Ssbruno "nispasswd", 138264269Ssbruno "skeleton", 139264269Ssbruno "newmail", 140264269Ssbruno "logfile", 141264269Ssbruno "home", 142264269Ssbruno "shellpath", 143264269Ssbruno "shells", 144264269Ssbruno "defaultshell", 145264269Ssbruno "defaultgroup", 146264269Ssbruno "extragroups", 147264269Ssbruno "defaultclass", 148264269Ssbruno "minuid", 149264269Ssbruno "maxuid", 150264269Ssbruno "mingid", 151264269Ssbruno "maxgid", 152264269Ssbruno "expire_days", 153264269Ssbruno "password_days", 154264269Ssbruno NULL 155264269Ssbruno}; 156264269Ssbruno 157264269Ssbrunostatic char * 158264269Ssbrunounquote(char const * str) 159264269Ssbruno{ 160264269Ssbruno if (str && (*str == '"' || *str == '\'')) { 161264269Ssbruno char *p = strchr(str + 1, *str); 162264269Ssbruno 163264269Ssbruno if (p != NULL) 164264269Ssbruno *p = '\0'; 165264269Ssbruno return (char *) (*++str ? str : NULL); 166264269Ssbruno } 167264269Ssbruno return (char *) str; 168264269Ssbruno} 169264269Ssbruno 170264269Ssbrunoint 171264269Ssbrunoboolean_val(char const * str, int dflt) 172264269Ssbruno{ 173264269Ssbruno if ((str = unquote(str)) != NULL) { 174264269Ssbruno int i; 175264269Ssbruno 176264269Ssbruno for (i = 0; booltrue[i]; i++) 177264269Ssbruno if (strcmp(str, booltrue[i]) == 0) 178264269Ssbruno return 1; 179264269Ssbruno for (i = 0; boolfalse[i]; i++) 180264269Ssbruno if (strcmp(str, boolfalse[i]) == 0) 181264269Ssbruno return 0; 182264269Ssbruno 183264269Ssbruno /* 184264269Ssbruno * Special cases for defaultpassword 185264269Ssbruno */ 186264269Ssbruno if (strcmp(str, "random") == 0) 187264269Ssbruno return -1; 188264269Ssbruno if (strcmp(str, "none") == 0) 189264269Ssbruno return -2; 190264269Ssbruno } 191264269Ssbruno return dflt; 192264269Ssbruno} 193264269Ssbruno 194264269Ssbrunochar const * 195264269Ssbrunoboolean_str(int val) 196264269Ssbruno{ 197264269Ssbruno if (val == -1) 198264269Ssbruno return "random"; 199264269Ssbruno else if (val == -2) 200264269Ssbruno return "none"; 201264269Ssbruno else 202264269Ssbruno return val ? booltrue[0] : boolfalse[0]; 203264269Ssbruno} 204264269Ssbruno 205264269Ssbrunochar * 206264269Ssbrunonewstr(char const * p) 207264269Ssbruno{ 208264269Ssbruno char *q = NULL; 209264269Ssbruno 210264269Ssbruno if ((p = unquote(p)) != NULL) { 211264269Ssbruno int l = strlen(p) + 1; 212264269Ssbruno 213264269Ssbruno if ((q = malloc(l)) != NULL) 214264269Ssbruno memcpy(q, p, l); 215264269Ssbruno } 216264269Ssbruno return q; 217264269Ssbruno} 218264269Ssbruno 219264269Ssbruno#define LNBUFSZ 1024 220264269Ssbruno 221264269Ssbruno 222264269Ssbrunostruct userconf * 223264269Ssbrunoread_userconfig(char const * file) 224264269Ssbruno{ 225264269Ssbruno FILE *fp; 226264269Ssbruno 227264269Ssbruno extendarray(&config.groups, &config.numgroups, 200); 228264269Ssbruno memset(config.groups, 0, config.numgroups * sizeof(char *)); 229264269Ssbruno if (file == NULL) 230264269Ssbruno file = _PATH_PW_CONF; 231264269Ssbruno if ((fp = fopen(file, "r")) != NULL) { 232264269Ssbruno int buflen = LNBUFSZ; 233264269Ssbruno char *buf = malloc(buflen); 234264269Ssbruno 235264269Ssbruno nextline: 236264269Ssbruno while (fgets(buf, buflen, fp) != NULL) { 237264269Ssbruno char *p; 238264269Ssbruno 239264269Ssbruno while ((p = strchr(buf, '\n')) == NULL) { 240264269Ssbruno int l; 241264269Ssbruno if (extendline(&buf, &buflen, buflen + LNBUFSZ) == -1) { 242264269Ssbruno int ch; 243264269Ssbruno while ((ch = fgetc(fp)) != '\n' && ch != EOF); 244264269Ssbruno goto nextline; /* Ignore it */ 245264269Ssbruno } 246264269Ssbruno l = strlen(buf); 247264269Ssbruno if (fgets(buf + l, buflen - l, fp) == NULL) 248264269Ssbruno break; /* Unterminated last line */ 249264269Ssbruno } 250264269Ssbruno 251264269Ssbruno if (p != NULL) 252264269Ssbruno *p = '\0'; 253264269Ssbruno 254264269Ssbruno if (*buf && (p = strtok(buf, " \t\r\n=")) != NULL && *p != '#') { 255264269Ssbruno static char const toks[] = " \t\r\n,="; 256264269Ssbruno char *q = strtok(NULL, toks); 257264269Ssbruno int i = 0; 258264269Ssbruno 259264269Ssbruno while (i < _UC_FIELDS && strcmp(p, kwds[i]) != 0) 260264269Ssbruno ++i; 261264269Ssbruno#if debugging 262264269Ssbruno if (i == _UC_FIELDS) 263264269Ssbruno printf("Got unknown kwd `%s' val=`%s'\n", p, q ? q : ""); 264264269Ssbruno else 265264269Ssbruno printf("Got kwd[%s]=%s\n", p, q); 266264269Ssbruno#endif 267264269Ssbruno switch (i) { 268264269Ssbruno case _UC_DEFAULTPWD: 269264269Ssbruno config.default_password = boolean_val(q, 1); 270264269Ssbruno break; 271264269Ssbruno case _UC_REUSEUID: 272264269Ssbruno config.reuse_uids = boolean_val(q, 0); 273264269Ssbruno break; 274264269Ssbruno case _UC_REUSEGID: 275264269Ssbruno config.reuse_gids = boolean_val(q, 0); 276264269Ssbruno break; 277264269Ssbruno case _UC_NISPASSWD: 278264269Ssbruno config.nispasswd = (q == NULL || !boolean_val(q, 1)) 279264269Ssbruno ? NULL : newstr(q); 280264269Ssbruno break; 281264269Ssbruno case _UC_DOTDIR: 282264269Ssbruno config.dotdir = (q == NULL || !boolean_val(q, 1)) 283264269Ssbruno ? NULL : newstr(q); 284264269Ssbruno break; 285264269Ssbruno case _UC_NEWMAIL: 286264269Ssbruno config.newmail = (q == NULL || !boolean_val(q, 1)) 287264269Ssbruno ? NULL : newstr(q); 288264269Ssbruno break; 289264269Ssbruno case _UC_LOGFILE: 290264269Ssbruno config.logfile = (q == NULL || !boolean_val(q, 1)) 291264269Ssbruno ? NULL : newstr(q); 292264269Ssbruno break; 293264269Ssbruno case _UC_HOMEROOT: 294264269Ssbruno config.home = (q == NULL || !boolean_val(q, 1)) 295264269Ssbruno ? "/home" : newstr(q); 296264269Ssbruno break; 297264269Ssbruno case _UC_SHELLPATH: 298264269Ssbruno config.shelldir = (q == NULL || !boolean_val(q, 1)) 299264269Ssbruno ? "/bin" : newstr(q); 300264269Ssbruno break; 301264269Ssbruno case _UC_SHELLS: 302264269Ssbruno for (i = 0; i < _UC_MAXSHELLS && q != NULL; i++, q = strtok(NULL, toks)) 303264269Ssbruno system_shells[i] = newstr(q); 304264269Ssbruno if (i > 0) 305264269Ssbruno while (i < _UC_MAXSHELLS) 306264269Ssbruno system_shells[i++] = NULL; 307264269Ssbruno break; 308264269Ssbruno case _UC_DEFAULTSHELL: 309264269Ssbruno config.shell_default = (q == NULL || !boolean_val(q, 1)) 310264269Ssbruno ? (char *) bourne_shell : newstr(q); 311264269Ssbruno break; 312264269Ssbruno case _UC_DEFAULTGROUP: 313264269Ssbruno q = unquote(q); 314264269Ssbruno config.default_group = (q == NULL || !boolean_val(q, 1) || GETGRNAM(q) == NULL) 315264269Ssbruno ? NULL : newstr(q); 316264269Ssbruno break; 317264269Ssbruno case _UC_EXTRAGROUPS: 318264269Ssbruno for (i = 0; q != NULL; q = strtok(NULL, toks)) { 319264269Ssbruno if (extendarray(&config.groups, &config.numgroups, i + 2) != -1) 320264269Ssbruno config.groups[i++] = newstr(q); 321264269Ssbruno } 322264269Ssbruno if (i > 0) 323264269Ssbruno while (i < config.numgroups) 324264269Ssbruno config.groups[i++] = NULL; 325264269Ssbruno break; 326264269Ssbruno case _UC_DEFAULTCLASS: 327264269Ssbruno config.default_class = (q == NULL || !boolean_val(q, 1)) 328264269Ssbruno ? NULL : newstr(q); 329264269Ssbruno break; 330264269Ssbruno case _UC_MINUID: 331264269Ssbruno if ((q = unquote(q)) != NULL && isdigit(*q)) 332264269Ssbruno config.min_uid = (uid_t) atol(q); 333264269Ssbruno break; 334264269Ssbruno case _UC_MAXUID: 335264269Ssbruno if ((q = unquote(q)) != NULL && isdigit(*q)) 336264269Ssbruno config.max_uid = (uid_t) atol(q); 337264269Ssbruno break; 338264269Ssbruno case _UC_MINGID: 339264269Ssbruno if ((q = unquote(q)) != NULL && isdigit(*q)) 340264269Ssbruno config.min_gid = (gid_t) atol(q); 341264269Ssbruno break; 342264269Ssbruno case _UC_MAXGID: 343264269Ssbruno if ((q = unquote(q)) != NULL && isdigit(*q)) 344264269Ssbruno config.max_gid = (gid_t) atol(q); 345264269Ssbruno break; 346264269Ssbruno case _UC_EXPIRE: 347264269Ssbruno if ((q = unquote(q)) != NULL && isdigit(*q)) 348264269Ssbruno config.expire_days = atoi(q); 349264269Ssbruno break; 350264269Ssbruno case _UC_PASSWORD: 351264269Ssbruno if ((q = unquote(q)) != NULL && isdigit(*q)) 352264269Ssbruno config.password_days = atoi(q); 353264269Ssbruno break; 354264269Ssbruno case _UC_FIELDS: 355264269Ssbruno case _UC_NONE: 356264269Ssbruno break; 357264269Ssbruno } 358264269Ssbruno } 359264269Ssbruno } 360264269Ssbruno free(buf); 361264269Ssbruno fclose(fp); 362264269Ssbruno } 363264269Ssbruno return &config; 364264269Ssbruno} 365264269Ssbruno 366287463Ssbruno 367264269Ssbrunoint 368264269Ssbrunowrite_userconfig(char const * file) 369264269Ssbruno{ 370264269Ssbruno int fd; 371264269Ssbruno 372264269Ssbruno if (file == NULL) 373264269Ssbruno file = _PATH_PW_CONF; 374278961Ssbruno 375264269Ssbruno if ((fd = open(file, O_CREAT | O_RDWR | O_TRUNC | O_EXLOCK, 0644)) != -1) { 376278961Ssbruno FILE *fp; 377278961Ssbruno 378264269Ssbruno if ((fp = fdopen(fd, "w")) == NULL) 379264269Ssbruno close(fd); 380264269Ssbruno else { 381264269Ssbruno int i, j, k; 382264269Ssbruno int len = LNBUFSZ; 383264269Ssbruno char *buf = malloc(len); 384264269Ssbruno 385264269Ssbruno for (i = _UC_NONE; i < _UC_FIELDS; i++) { 386264269Ssbruno int quote = 1; 387264269Ssbruno char const *val = buf; 388264269Ssbruno 389264269Ssbruno *buf = '\0'; 390264269Ssbruno switch (i) { 391264269Ssbruno case _UC_DEFAULTPWD: 392264269Ssbruno val = boolean_str(config.default_password); 393264269Ssbruno break; 394264269Ssbruno case _UC_REUSEUID: 395264269Ssbruno val = boolean_str(config.reuse_uids); 396264269Ssbruno break; 397264269Ssbruno case _UC_REUSEGID: 398264269Ssbruno val = boolean_str(config.reuse_gids); 399264269Ssbruno break; 400264269Ssbruno case _UC_NISPASSWD: 401264269Ssbruno val = config.nispasswd ? config.nispasswd : ""; 402264269Ssbruno quote = 0; 403264269Ssbruno break; 404264269Ssbruno case _UC_DOTDIR: 405264269Ssbruno val = config.dotdir ? config.dotdir : boolean_str(0); 406264269Ssbruno break; 407264269Ssbruno case _UC_NEWMAIL: 408264269Ssbruno val = config.newmail ? config.newmail : boolean_str(0); 409264269Ssbruno break; 410264269Ssbruno case _UC_LOGFILE: 411264269Ssbruno val = config.logfile ? config.logfile : boolean_str(0); 412264269Ssbruno break; 413264269Ssbruno case _UC_HOMEROOT: 414264269Ssbruno val = config.home; 415264269Ssbruno break; 416264269Ssbruno case _UC_SHELLPATH: 417264269Ssbruno val = config.shelldir; 418264269Ssbruno break; 419264269Ssbruno case _UC_SHELLS: 420264269Ssbruno for (j = k = 0; j < _UC_MAXSHELLS && system_shells[j] != NULL; j++) { 421264269Ssbruno char lbuf[64]; 422264269Ssbruno int l = snprintf(lbuf, sizeof lbuf, "%s\"%s\"", k ? "," : "", system_shells[j]); 423264269Ssbruno if (l < 0) 424264269Ssbruno l = 0; 425264269Ssbruno if (l + k + 1 < len || extendline(&buf, &len, len + LNBUFSZ) != -1) { 426264269Ssbruno strcpy(buf + k, lbuf); 427264269Ssbruno k += l; 428264269Ssbruno } 429264269Ssbruno } 430264269Ssbruno quote = 0; 431264269Ssbruno break; 432264269Ssbruno case _UC_DEFAULTSHELL: 433264269Ssbruno val = config.shell_default ? config.shell_default : bourne_shell; 434264269Ssbruno break; 435264269Ssbruno case _UC_DEFAULTGROUP: 436264269Ssbruno val = config.default_group ? config.default_group : ""; 437264269Ssbruno break; 438264269Ssbruno case _UC_EXTRAGROUPS: 439264269Ssbruno extendarray(&config.groups, &config.numgroups, 200); 440264269Ssbruno for (j = k = 0; j < config.numgroups && config.groups[j] != NULL; j++) { 441264269Ssbruno char lbuf[64]; 442264269Ssbruno int l = snprintf(lbuf, sizeof lbuf, "%s\"%s\"", k ? "," : "", config.groups[j]); 443264269Ssbruno if (l < 0) 444264269Ssbruno l = 0; 445264269Ssbruno if (l + k + 1 < len || extendline(&buf, &len, len + 1024) != -1) { 446264269Ssbruno strcpy(buf + k, lbuf); 447264269Ssbruno k += l; 448264269Ssbruno } 449264269Ssbruno } 450264269Ssbruno quote = 0; 451264269Ssbruno break; 452264269Ssbruno case _UC_DEFAULTCLASS: 453264269Ssbruno val = config.default_class ? config.default_class : ""; 454264269Ssbruno break; 455264269Ssbruno case _UC_MINUID: 456264269Ssbruno sprintf(buf, "%lu", (unsigned long) config.min_uid); 457264269Ssbruno quote = 0; 458264269Ssbruno break; 459264269Ssbruno case _UC_MAXUID: 460264269Ssbruno sprintf(buf, "%lu", (unsigned long) config.max_uid); 461264269Ssbruno quote = 0; 462264269Ssbruno break; 463264269Ssbruno case _UC_MINGID: 464264269Ssbruno sprintf(buf, "%lu", (unsigned long) config.min_gid); 465264269Ssbruno quote = 0; 466264269Ssbruno break; 467264269Ssbruno case _UC_MAXGID: 468264269Ssbruno sprintf(buf, "%lu", (unsigned long) config.max_gid); 469264269Ssbruno quote = 0; 470264269Ssbruno break; 471264269Ssbruno case _UC_EXPIRE: 472264269Ssbruno sprintf(buf, "%d", config.expire_days); 473264269Ssbruno quote = 0; 474264269Ssbruno break; 475264269Ssbruno case _UC_PASSWORD: 476264269Ssbruno sprintf(buf, "%d", config.password_days); 477264269Ssbruno quote = 0; 478264269Ssbruno break; 479264269Ssbruno case _UC_NONE: 480264269Ssbruno break; 481264269Ssbruno } 482264269Ssbruno 483264269Ssbruno if (comments[i]) 484264269Ssbruno fputs(comments[i], fp); 485264269Ssbruno 486264269Ssbruno if (*kwds[i]) { 487264269Ssbruno if (quote) 488264269Ssbruno fprintf(fp, "%s = \"%s\"\n", kwds[i], val); 489264269Ssbruno else 490264269Ssbruno fprintf(fp, "%s = %s\n", kwds[i], val); 491264269Ssbruno#if debugging 492264269Ssbruno printf("WROTE: %s = %s\n", kwds[i], val); 493264269Ssbruno#endif 494264269Ssbruno } 495264269Ssbruno } 496264269Ssbruno free(buf); 497264269Ssbruno return fclose(fp) != EOF; 498264269Ssbruno } 499264269Ssbruno } 500264269Ssbruno return 0; 501264269Ssbruno} 502264269Ssbruno