]>
git.cameronkatri.com Git - pw-darwin.git/blob - pw/pw_conf.c
9dff3fe03efaf7590af404548777cfc5fd298fde
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 * David L. Nugent. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 static const char rcsid
[] =
34 #include <sys/types.h>
72 static char bourne_shell
[] = "sh";
74 static char *system_shells
[_UC_MAXSHELLS
] =
81 static char const *booltrue
[] =
83 "yes", "true", "1", "on", NULL
85 static char const *boolfalse
[] =
87 "no", "false", "0", "off", NULL
90 static struct userconf config
=
92 0, /* Default password for new users? (nologin) */
95 NULL
, /* NIS version of the passwd file */
96 "/usr/share/skel", /* Where to obtain skeleton files */
97 NULL
, /* Mail to send to new accounts */
98 "/var/log/userlog", /* Where to log changes */
99 "/home", /* Where to create home directory */
100 _DEF_DIRMODE
, /* Home directory perms, modified by umask */
101 "/bin", /* Where shells are located */
102 system_shells
, /* List of shells (first is default) */
103 bourne_shell
, /* Default shell */
104 NULL
, /* Default group name */
105 NULL
, /* Default (additional) groups */
106 NULL
, /* Default login class */
107 1000, 32000, /* Allowed range of uids */
108 1000, 32000, /* Allowed range of gids */
109 0, /* Days until account expires */
110 0 /* Days until password expires */
113 static char const *comments
[_UC_FIELDS
] =
115 "#\n# pw.conf - user/group configuration defaults\n#\n",
116 "\n# Password for new users? no=nologin yes=loginid none=blank random=random\n",
117 "\n# Reuse gaps in uid sequence? (yes or no)\n",
118 "\n# Reuse gaps in gid sequence? (yes or no)\n",
119 "\n# Path to the NIS passwd file (blank or 'no' for none)\n",
120 "\n# Obtain default dotfiles from this directory\n",
121 "\n# Mail this file to new user (/etc/newuser.msg or no)\n",
122 "\n# Log add/change/remove information in this file\n",
123 "\n# Root directory in which $HOME directory is created\n",
124 "\n# Mode for the new $HOME directory, will be modified by umask\n",
125 "\n# Colon separated list of directories containing valid shells\n",
126 "\n# Comma separated list of available shells (without paths)\n",
127 "\n# Default shell (without path)\n",
128 "\n# Default group (leave blank for new group per user)\n",
129 "\n# Extra groups for new users\n",
130 "\n# Default login class for new users\n",
131 "\n# Range of valid default user ids\n",
133 "\n# Range of valid default group ids\n",
135 "\n# Days after which account expires (0=disabled)\n",
136 "\n# Days after which password expires (0=disabled)\n"
139 static char const *kwds
[] =
167 unquote(char const * str
)
169 if (str
&& (*str
== '"' || *str
== '\'')) {
170 char *p
= strchr(str
+ 1, *str
);
174 return (char *) (*++str
? str
: NULL
);
180 boolean_val(char const * str
, int dflt
)
182 if ((str
= unquote(str
)) != NULL
) {
185 for (i
= 0; booltrue
[i
]; i
++)
186 if (strcmp(str
, booltrue
[i
]) == 0)
188 for (i
= 0; boolfalse
[i
]; i
++)
189 if (strcmp(str
, boolfalse
[i
]) == 0)
196 passwd_val(char const * str
, int dflt
)
198 if ((str
= unquote(str
)) != NULL
) {
201 for (i
= 0; booltrue
[i
]; i
++)
202 if (strcmp(str
, booltrue
[i
]) == 0)
204 for (i
= 0; boolfalse
[i
]; i
++)
205 if (strcmp(str
, boolfalse
[i
]) == 0)
209 * Special cases for defaultpassword
211 if (strcmp(str
, "random") == 0)
213 if (strcmp(str
, "none") == 0)
216 errx(1, "Invalid value for default password");
229 return val
? booltrue
[0] : boolfalse
[0];
233 newstr(char const * p
)
237 if ((p
= unquote(p
)) == NULL
)
240 if ((q
= strdup(p
)) == NULL
)
247 read_userconfig(char const * file
)
258 if ((fp
= fopen(file
, "r")) == NULL
)
261 while ((linelen
= getline(&buf
, &linecap
, fp
)) > 0) {
262 if (*buf
&& (p
= strtok(buf
, " \t\r\n=")) != NULL
&& *p
!= '#') {
263 static char const toks
[] = " \t\r\n,=";
264 char *q
= strtok(NULL
, toks
);
268 while (i
< _UC_FIELDS
&& strcmp(p
, kwds
[i
]) != 0)
272 printf("Got unknown kwd `%s' val=`%s'\n", p
, q
? q
: "");
274 printf("Got kwd[%s]=%s\n", p
, q
);
278 config
.default_password
= passwd_val(q
, 1);
281 config
.reuse_uids
= boolean_val(q
, 0);
284 config
.reuse_gids
= boolean_val(q
, 0);
287 config
.nispasswd
= (q
== NULL
|| !boolean_val(q
, 1))
291 config
.dotdir
= (q
== NULL
|| !boolean_val(q
, 1))
295 config
.newmail
= (q
== NULL
|| !boolean_val(q
, 1))
299 config
.logfile
= (q
== NULL
|| !boolean_val(q
, 1))
303 config
.home
= (q
== NULL
|| !boolean_val(q
, 1))
304 ? "/home" : newstr(q
);
307 modeset
= setmode(q
);
308 config
.homemode
= (q
== NULL
|| !boolean_val(q
, 1))
309 ? _DEF_DIRMODE
: getmode(modeset
, _DEF_DIRMODE
);
313 config
.shelldir
= (q
== NULL
|| !boolean_val(q
, 1))
314 ? "/bin" : newstr(q
);
317 for (i
= 0; i
< _UC_MAXSHELLS
&& q
!= NULL
; i
++, q
= strtok(NULL
, toks
))
318 system_shells
[i
] = newstr(q
);
320 while (i
< _UC_MAXSHELLS
)
321 system_shells
[i
++] = NULL
;
323 case _UC_DEFAULTSHELL
:
324 config
.shell_default
= (q
== NULL
|| !boolean_val(q
, 1))
325 ? (char *) bourne_shell
: newstr(q
);
327 case _UC_DEFAULTGROUP
:
329 config
.default_group
= (q
== NULL
|| !boolean_val(q
, 1) || GETGRNAM(q
) == NULL
)
332 case _UC_EXTRAGROUPS
:
333 while ((q
= strtok(NULL
, toks
)) != NULL
) {
334 if (config
.groups
== NULL
)
335 config
.groups
= sl_init();
336 sl_add(config
.groups
, newstr(q
));
339 case _UC_DEFAULTCLASS
:
340 config
.default_class
= (q
== NULL
|| !boolean_val(q
, 1))
344 if ((q
= unquote(q
)) != NULL
) {
345 config
.min_uid
= strtounum(q
, 0,
348 warnx("Invalid min_uid: '%s';"
353 if ((q
= unquote(q
)) != NULL
) {
354 config
.max_uid
= strtounum(q
, 0,
357 warnx("Invalid max_uid: '%s';"
362 if ((q
= unquote(q
)) != NULL
) {
363 config
.min_gid
= strtounum(q
, 0,
366 warnx("Invalid min_gid: '%s';"
371 if ((q
= unquote(q
)) != NULL
) {
372 config
.max_gid
= strtounum(q
, 0,
375 warnx("Invalid max_gid: '%s';"
380 if ((q
= unquote(q
)) != NULL
) {
381 config
.expire_days
= strtonum(q
, 0,
384 warnx("Invalid expire days:"
385 " '%s'; ignoring", q
);
389 if ((q
= unquote(q
)) != NULL
) {
390 config
.password_days
= strtonum(q
, 0,
393 warnx("Invalid password days:"
394 " '%s'; ignoring", q
);
411 write_userconfig(struct userconf
*cnf
, const char *file
)
417 char cfgfile
[MAXPATHLEN
];
420 snprintf(cfgfile
, sizeof(cfgfile
), "%s/" _PW_CONF
,
425 if ((fd
= open(file
, O_CREAT
|O_RDWR
|O_TRUNC
|O_EXLOCK
, 0644)) == -1)
428 if ((fp
= fdopen(fd
, "w")) == NULL
) {
433 buf
= sbuf_new_auto();
434 for (i
= _UC_NONE
; i
< _UC_FIELDS
; i
++) {
440 sbuf_cat(buf
, boolean_str(cnf
->default_password
));
443 sbuf_cat(buf
, boolean_str(cnf
->reuse_uids
));
446 sbuf_cat(buf
, boolean_str(cnf
->reuse_gids
));
449 sbuf_cat(buf
, cnf
->nispasswd
? cnf
->nispasswd
: "");
453 sbuf_cat(buf
, cnf
->dotdir
? cnf
->dotdir
:
457 sbuf_cat(buf
, cnf
->newmail
? cnf
->newmail
:
461 sbuf_cat(buf
, cnf
->logfile
? cnf
->logfile
:
465 sbuf_cat(buf
, cnf
->home
);
468 sbuf_printf(buf
, "%04o", cnf
->homemode
);
472 sbuf_cat(buf
, cnf
->shelldir
);
475 for (j
= 0; j
< _UC_MAXSHELLS
&&
476 system_shells
[j
] != NULL
; j
++)
477 sbuf_printf(buf
, "%s\"%s\"", j
?
478 "," : "", system_shells
[j
]);
481 case _UC_DEFAULTSHELL
:
482 sbuf_cat(buf
, cnf
->shell_default
?
483 cnf
->shell_default
: bourne_shell
);
485 case _UC_DEFAULTGROUP
:
486 sbuf_cat(buf
, cnf
->default_group
?
487 cnf
->default_group
: "");
489 case _UC_EXTRAGROUPS
:
490 for (j
= 0; cnf
->groups
!= NULL
&&
491 j
< (int)cnf
->groups
->sl_cur
; j
++)
492 sbuf_printf(buf
, "%s\"%s\"", j
?
493 "," : "", cnf
->groups
->sl_str
[j
]);
496 case _UC_DEFAULTCLASS
:
497 sbuf_cat(buf
, cnf
->default_class
?
498 cnf
->default_class
: "");
501 sbuf_printf(buf
, "%ju", (uintmax_t)cnf
->min_uid
);
505 sbuf_printf(buf
, "%ju", (uintmax_t)cnf
->max_uid
);
509 sbuf_printf(buf
, "%ju", (uintmax_t)cnf
->min_gid
);
513 sbuf_printf(buf
, "%ju", (uintmax_t)cnf
->max_gid
);
517 sbuf_printf(buf
, "%jd", (intmax_t)cnf
->expire_days
);
521 sbuf_printf(buf
, "%jd", (intmax_t)cnf
->password_days
);
530 fputs(comments
[i
], fp
);
534 fprintf(fp
, "%s = \"%s\"\n", kwds
[i
],
537 fprintf(fp
, "%s = %s\n", kwds
[i
], sbuf_data(buf
));
539 printf("WROTE: %s = %s\n", kwds
[i
], sbuf_data(buf
));
544 return (fclose(fp
) != EOF
);