2 * Copyright (c) 1989 - 1994, Julianne Frances Haugh
3 * Copyright (c) 1996 - 2000, Marek Michałkiewicz
4 * Copyright (c) 2001 - 2005, Tomasz Kłoczko
5 * Copyright (c) 2008 - 2011, Nicolas François
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the copyright holders or contributors may not be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 #include <sys/types.h>
45 #include "prototypes.h"
49 #include "exitcodes.h"
56 static bool spw_locked = false;
57 static bool pw_locked = false;
59 /* local function prototypes */
60 static void fail_exit (int status);
61 static void usage (int status);
62 static void process_flags (int argc, char **argv);
64 static void fail_exit (int status)
67 if (spw_unlock () == 0) {
68 fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
69 SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
74 if (pw_unlock () == 0) {
75 fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
76 SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
83 static void usage (int status)
85 FILE *usageout = (E_SUCCESS != status) ? stderr : stdout;
86 (void) fprintf (usageout,
87 _("Usage: %s [options]\n"
91 (void) fputs (_(" -h, --help display this help message and exit\n"), usageout);
92 (void) fputs (_(" -R, --root CHROOT_DIR directory to chroot into\n"), usageout);
93 (void) fputs ("\n", usageout);
98 * process_flags - parse the command line options
100 * It will not return if an error is encountered.
102 static void process_flags (int argc, char **argv)
105 * Parse the command line options.
108 static struct option long_options[] = {
109 {"help", no_argument, NULL, 'h'},
110 {"root", required_argument, NULL, 'R'},
111 {NULL, 0, NULL, '\0'}
114 while ((c = getopt_long (argc, argv, "hR:",
115 long_options, NULL)) != -1) {
119 /*@notreached@*/break;
120 case 'R': /* no-op, handled in process_root_flag () */
127 if (optind != argc) {
132 int main (int argc, char **argv)
134 const struct passwd *pw;
136 const struct spwd *spwd;
138 Prog = Basename (argv[0]);
140 (void) setlocale (LC_ALL, "");
141 (void) bindtextdomain (PACKAGE, LOCALEDIR);
142 (void) textdomain (PACKAGE);
144 process_root_flag ("-R", argc, argv);
146 OPENLOG ("pwunconv");
148 process_flags (argc, argv);
151 if (getdef_bool("USE_TCB")) {
152 fprintf (stderr, _("%s: can't work with tcb enabled\n"), Prog);
155 #endif /* WITH_TCB */
157 if (!spw_file_present ()) {
158 /* shadow not installed, do nothing */
162 if (pw_lock () == 0) {
164 _("%s: cannot lock %s; try again later.\n"),
169 if (pw_open (O_RDWR) == 0) {
171 _("%s: cannot open %s\n"),
176 if (spw_lock () == 0) {
178 _("%s: cannot lock %s; try again later.\n"),
179 Prog, spw_dbname ());
183 if (spw_open (O_RDONLY) == 0) {
185 _("%s: cannot open %s\n"),
186 Prog, spw_dbname ());
191 while ((pw = pw_next ()) != NULL) {
192 spwd = spw_locate (pw->pw_name);
200 * Update password if non-shadow is "x".
202 if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0) {
203 pwent.pw_passwd = spwd->sp_pwdp;
207 * Password aging works differently in the two different
208 * systems. With shadow password files you apparently must
209 * have some aging information. The maxweeks or minweeks
210 * may not map exactly. In pwconv we set max == 10000,
211 * which is about 30 years. Here we have to undo that
212 * kludge. So, if maxdays == 10000, no aging information is
213 * put into the new file. Otherwise, the days are converted
214 * to weeks and so on.
216 if (pw_update (&pwent) == 0) {
218 _("%s: failed to prepare the new %s entry '%s'\n"),
219 Prog, pw_dbname (), pwent.pw_name);
224 if (spw_close () == 0) {
226 _("%s: failure while writing changes to %s\n"),
227 Prog, spw_dbname ());
228 SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ()));
232 if (pw_close () == 0) {
234 _("%s: failure while writing changes to %s\n"),
236 SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ()));
240 if (unlink (SHADOW) != 0) {
242 _("%s: cannot delete %s\n"), Prog, SHADOW);
243 SYSLOG ((LOG_ERR, "cannot delete %s", SHADOW));
247 if (spw_unlock () == 0) {
248 fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
249 SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
252 if (pw_unlock () == 0) {
253 fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
254 SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
258 nscd_flush_cache ("passwd");