~ubuntu-branches/ubuntu/raring/shadow/raring-proposed

« back to all changes in this revision

Viewing changes to src/pwck.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2009-05-05 09:45:21 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20090505094521-wpk2wn3q7957tlah
Tags: 1:4.1.3.1-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Ubuntu specific:
    + debian/login.defs: use SHA512 by default for password crypt routine.
  - debian/patches/stdout-encrypted-password.patch: chpasswd can report
    password hashes on stdout (debian bug 505640).
  - debian/login.pam: Enable SELinux support (debian bug 527106).
  - debian/securetty.linux: support Freescale MX-series (debian bug 527095).
* Add debian/patches/300_lastlog_failure: fixed upstream (debian bug 524873).
* Drop debian/patches/593_omit_lastchange_field_if_clock_is_misset: fixed
  upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright 1992 - 1994, Julianne Frances Haugh
 
2
 * Copyright (c) 1992 - 1994, Julianne Frances Haugh
 
3
 * Copyright (c) 1996 - 2000, Marek Michałkiewicz
 
4
 * Copyright (c) 2001       , Michał Moskal
 
5
 * Copyright (c) 2001 - 2006, Tomasz Kłoczko
 
6
 * Copyright (c) 2007 - 2009, Nicolas François
3
7
 * All rights reserved.
4
8
 *
5
9
 * Redistribution and use in source and binary forms, with or without
10
14
 * 2. Redistributions in binary form must reproduce the above copyright
11
15
 *    notice, this list of conditions and the following disclaimer in the
12
16
 *    documentation and/or other materials provided with the distribution.
13
 
 * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
14
 
 *    may be used to endorse or promote products derived from this software
15
 
 *    without specific prior written permission.
 
17
 * 3. The name of the copyright holders or contributors may not be used to
 
18
 *    endorse or promote products derived from this software without
 
19
 *    specific prior written permission.
16
20
 *
17
 
 * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
18
 
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 
 * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
21
 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 
 * SUCH DAMAGE.
 
21
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
22
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
23
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 
24
 * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
 
25
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
26
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
27
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
28
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
29
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
30
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
31
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
32
 */
29
33
 
30
34
#include <config.h>
31
35
 
32
 
#ident "$Id: pwck.c 1751 2008-02-03 16:28:03Z nekral-guest $"
 
36
#ident "$Id: pwck.c 2587 2009-04-05 21:23:27Z nekral-guest $"
33
37
 
34
38
#include <fcntl.h>
35
39
#include <grp.h>
54
58
#define E_CANTOPEN      3
55
59
#define E_CANTLOCK      4
56
60
#define E_CANTUPDATE    5
 
61
#define E_CANTSORT      6
57
62
 
58
63
/*
59
64
 * Global variables
60
65
 */
 
66
char *Prog;
61
67
 
62
 
static char *Prog;
63
68
static const char *pwd_file = PASSWD_FILE;
64
 
static int use_system_pw_file = 1;
 
69
static bool use_system_pw_file = true;
65
70
static const char *spw_file = SHADOW_FILE;
66
 
static int use_system_spw_file = 1;
67
 
 
68
 
static int is_shadow = 0;
 
71
static bool use_system_spw_file = true;
 
72
 
 
73
static bool is_shadow = false;
 
74
 
 
75
static bool pw_locked  = false;
 
76
static bool spw_locked = false;
69
77
 
70
78
/* Options */
71
 
static int read_only = 0;
72
 
static int sort_mode = 0;
73
 
static int quiet = 0;           /* don't report warnings, only errors */
 
79
static bool read_only = false;
 
80
static bool sort_mode = false;
 
81
static bool quiet = false;              /* don't report warnings, only errors */
74
82
 
75
83
/* local function prototypes */
 
84
static void fail_exit (int code);
76
85
static void usage (void);
77
86
static void process_flags (int argc, char **argv);
78
87
static void open_files (void);
79
 
static void close_files (int changed);
80
 
static void check_pw_file (int *errors, int *changed);
81
 
static void check_spw_file (int *errors, int *changed);
82
 
 
 
88
static void close_files (bool changed);
 
89
static void check_pw_file (int *errors, bool *changed);
 
90
static void check_spw_file (int *errors, bool *changed);
 
91
 
 
92
/*
 
93
 * fail_exit - do some cleanup and exit with the given error code
 
94
 */
 
95
static void fail_exit (int code)
 
96
{
 
97
        if (spw_locked) {
 
98
                if (spw_unlock () == 0) {
 
99
                        fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
 
100
                        SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
 
101
                        /* continue */
 
102
                }
 
103
        }
 
104
 
 
105
        if (pw_locked) {
 
106
                if (pw_unlock () == 0) {
 
107
                        fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
 
108
                        SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
 
109
                        /* continue */
 
110
                }
 
111
        }
 
112
 
 
113
        closelog ();
 
114
 
 
115
        exit (code);
 
116
}
83
117
/*
84
118
 * usage - print syntax message and exit
85
119
 */
106
140
                switch (arg) {
107
141
                case 'e':       /* added for Debian shadow-961025-2 compatibility */
108
142
                case 'q':
109
 
                        quiet = 1;
 
143
                        quiet = true;
110
144
                        break;
111
145
                case 'r':
112
 
                        read_only = 1;
 
146
                        read_only = true;
113
147
                        break;
114
148
                case 's':
115
 
                        sort_mode = 1;
 
149
                        sort_mode = true;
116
150
                        break;
117
151
                default:
118
152
                        usage ();
137
171
         */
138
172
        if (optind != argc) {
139
173
                pwd_file = argv[optind];
140
 
                pw_name (pwd_file);
141
 
                use_system_pw_file = 0;
 
174
                pw_setdbname (pwd_file);
 
175
                use_system_pw_file = false;
142
176
        }
143
177
        if ((optind + 2) == argc) {
144
178
                spw_file = argv[optind + 1];
145
 
                spw_name (spw_file);
146
 
                is_shadow = 1;
147
 
                use_system_spw_file = 0;
 
179
                spw_setdbname (spw_file);
 
180
                is_shadow = true;
 
181
                use_system_spw_file = false;
148
182
        } else if (optind == argc) {
149
183
                is_shadow = spw_file_present ();
150
184
        }
163
197
         */
164
198
        if (!read_only) {
165
199
                if (pw_lock () == 0) {
166
 
                        fprintf (stderr, _("%s: cannot lock file %s\n"),
 
200
                        fprintf (stderr,
 
201
                                 _("%s: cannot lock %s; try again later.\n"),
167
202
                                 Prog, pwd_file);
168
 
                        if (use_system_pw_file) {
169
 
                                SYSLOG ((LOG_WARN, "cannot lock %s", pwd_file));
170
 
                        }
171
 
                        closelog ();
172
 
                        exit (E_CANTLOCK);
 
203
                        fail_exit (E_CANTLOCK);
173
204
                }
174
 
                if (is_shadow && (spw_lock () == 0)) {
175
 
                        fprintf (stderr, _("%s: cannot lock file %s\n"),
176
 
                                 Prog, spw_file);
177
 
                        if (use_system_spw_file) {
178
 
                                SYSLOG ((LOG_WARN, "cannot lock %s", spw_file));
 
205
                pw_locked = true;
 
206
                if (is_shadow) {
 
207
                        if (spw_lock () == 0) {
 
208
                                fprintf (stderr,
 
209
                                         _("%s: cannot lock %s; try again later.\n"),
 
210
                                         Prog, spw_file);
 
211
                                fail_exit (E_CANTLOCK);
179
212
                        }
180
 
                        closelog ();
181
 
                        exit (E_CANTLOCK);
 
213
                        spw_locked = true;
182
214
                }
183
215
        }
184
216
 
187
219
         * otherwise.
188
220
         */
189
221
        if (pw_open (read_only ? O_RDONLY : O_RDWR) == 0) {
190
 
                fprintf (stderr, _("%s: cannot open file %s\n"),
 
222
                fprintf (stderr, _("%s: cannot open %s\n"),
191
223
                         Prog, pwd_file);
192
224
                if (use_system_pw_file) {
193
225
                        SYSLOG ((LOG_WARN, "cannot open %s", pwd_file));
194
226
                }
195
 
                closelog ();
196
 
                exit (E_CANTOPEN);
 
227
                fail_exit (E_CANTOPEN);
197
228
        }
198
229
        if (is_shadow && (spw_open (read_only ? O_RDONLY : O_RDWR) == 0)) {
199
 
                fprintf (stderr, _("%s: cannot open file %s\n"),
 
230
                fprintf (stderr, _("%s: cannot open %s\n"),
200
231
                         Prog, spw_file);
201
232
                if (use_system_spw_file) {
202
233
                        SYSLOG ((LOG_WARN, "cannot open %s", spw_file));
203
234
                }
204
 
                closelog ();
205
 
                exit (E_CANTOPEN);
 
235
                fail_exit (E_CANTOPEN);
206
236
        }
207
237
}
208
238
 
213
243
 *      changes are committed in the databases. The databases are
214
244
 *      unlocked anyway.
215
245
 */
216
 
static void close_files (int changed)
 
246
static void close_files (bool changed)
217
247
{
218
248
        /*
219
249
         * All done. If there were no change we can just abandon any
221
251
         */
222
252
        if (changed) {
223
253
                if (pw_close () == 0) {
224
 
                        fprintf (stderr, _("%s: cannot update file %s\n"),
 
254
                        fprintf (stderr, _("%s: failure while writing changes to %s\n"),
225
255
                                 Prog, pwd_file);
226
 
                        SYSLOG ((LOG_WARN, "cannot update %s", pwd_file));
227
 
                        closelog ();
228
 
                        exit (E_CANTUPDATE);
 
256
                        SYSLOG ((LOG_ERR, "failure while writing changes to %s", pwd_file));
 
257
                        fail_exit (E_CANTUPDATE);
229
258
                }
230
259
                if (is_shadow && (spw_close () == 0)) {
231
 
                        fprintf (stderr, _("%s: cannot update file %s\n"),
 
260
                        fprintf (stderr, _("%s: failure while writing changes to %s\n"),
232
261
                                 Prog, spw_file);
233
 
                        SYSLOG ((LOG_WARN, "cannot update %s", spw_file));
234
 
                        closelog ();
235
 
                        exit (E_CANTUPDATE);
 
262
                        SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_file));
 
263
                        fail_exit (E_CANTUPDATE);
236
264
                }
237
265
        }
238
266
 
239
267
        /*
240
268
         * Don't be anti-social - unlock the files when you're done.
241
269
         */
242
 
        if (is_shadow) {
243
 
                spw_unlock ();
244
 
        }
245
 
        (void) pw_unlock ();
 
270
        if (spw_locked) {
 
271
                if (spw_unlock () == 0) {
 
272
                        fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
 
273
                        SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
 
274
                        /* continue */
 
275
                }
 
276
        }
 
277
        spw_locked = false;
 
278
        if (pw_locked) {
 
279
                if (pw_unlock () == 0) {
 
280
                        fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
 
281
                        SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
 
282
                        /* continue */
 
283
                }
 
284
        }
 
285
        pw_locked = false;
246
286
}
247
287
 
248
288
/*
249
289
 * check_pw_file - check the content of the passwd file
250
290
 */
251
 
static void check_pw_file (int *errors, int *changed)
 
291
static void check_pw_file (int *errors, bool *changed)
252
292
{
253
293
        struct commonio_entry *pfe, *tpfe;
254
294
        struct passwd *pwd;
262
302
                 * If this is a NIS line, skip it. You can't "know" what NIS
263
303
                 * is going to do without directly asking NIS ...
264
304
                 */
265
 
                if ((pfe->line[0] == '+') || (pfe->line[0] == '-')) {
 
305
                if (('+' == pfe->line[0]) || ('-' == pfe->line[0])) {
266
306
                        continue;
267
307
                }
268
308
 
294
334
                         * loop to try out the next list element.
295
335
                         */
296
336
                      delete_pw:
297
 
                        SYSLOG ((LOG_INFO, "delete passwd line `%s'",
 
337
                        SYSLOG ((LOG_INFO, "delete passwd line '%s'",
298
338
                                 pfe->line));
299
 
                        *changed = 1;
 
339
                        *changed = true;
300
340
 
301
341
                        __pw_del_entry (pfe);
302
342
                        continue;
350
390
                /*
351
391
                 * Check for invalid usernames.  --marekm
352
392
                 */
353
 
                if (!check_user_name (pwd->pw_name)) {
 
393
                if (!is_valid_user_name (pwd->pw_name)) {
354
394
                        printf (_("invalid user name '%s'\n"), pwd->pw_name);
355
395
                        *errors += 1;
356
396
                }
357
397
 
358
398
                /*
 
399
                 * Check for invalid user ID.
 
400
                 */
 
401
                if (pwd->pw_uid == (uid_t)-1) {
 
402
                        printf (_("invalid user ID '%lu'\n"), (long unsigned int)pwd->pw_uid);
 
403
                        *errors += 1;
 
404
                }
 
405
 
 
406
                /*
359
407
                 * Make sure the primary group exists
360
408
                 */
361
409
                /* local, no need for xgetgrgid */
365
413
                         * No primary group, just give a warning
366
414
                         */
367
415
 
368
 
                        printf (_("user %s: no group %u\n"),
369
 
                                pwd->pw_name, pwd->pw_gid);
 
416
                        printf (_("user '%s': no group %lu\n"),
 
417
                                pwd->pw_name, (unsigned long) pwd->pw_gid);
370
418
                        *errors += 1;
371
419
                }
372
420
 
377
425
                        /*
378
426
                         * Home directory doesn't exist, give a warning
379
427
                         */
380
 
                        printf (_("user %s: directory %s does not exist\n"),
 
428
                        printf (_("user '%s': directory '%s' does not exist\n"),
381
429
                                pwd->pw_name, pwd->pw_dir);
382
430
                        *errors += 1;
383
431
                }
392
440
                        /*
393
441
                         * Login shell doesn't exist, give a warning
394
442
                         */
395
 
                        printf (_("user %s: program %s does not exist\n"),
 
443
                        printf (_("user '%s': program '%s' does not exist\n"),
396
444
                                pwd->pw_name, pwd->pw_shell);
397
445
                        *errors += 1;
398
446
                }
403
451
 
404
452
                if (is_shadow) {
405
453
                        spw = (struct spwd *) spw_locate (pwd->pw_name);
406
 
                        if (spw == NULL) {
 
454
                        if (NULL == spw) {
407
455
                                printf (_("no matching password file entry in %s\n"),
408
456
                                        spw_file);
409
457
                                printf (_("add user '%s' in %s? "),
413
461
                                        struct spwd sp;
414
462
                                        struct passwd pw;
415
463
 
416
 
                                        sp.sp_namp = pwd->pw_name;
417
 
                                        sp.sp_pwdp = pwd->pw_passwd;
418
 
                                        sp.sp_min =
 
464
                                        sp.sp_namp   = pwd->pw_name;
 
465
                                        sp.sp_pwdp   = pwd->pw_passwd;
 
466
                                        sp.sp_min    =
419
467
                                            getdef_num ("PASS_MIN_DAYS", -1);
420
 
                                        sp.sp_max =
 
468
                                        sp.sp_max    =
421
469
                                            getdef_num ("PASS_MAX_DAYS", -1);
422
 
                                        sp.sp_warn =
 
470
                                        sp.sp_warn   =
423
471
                                            getdef_num ("PASS_WARN_AGE", -1);
424
 
                                        sp.sp_inact = -1;
 
472
                                        sp.sp_inact  = -1;
425
473
                                        sp.sp_expire = -1;
426
 
                                        sp.sp_flag = -1;
427
 
                                        sp.sp_lstchg =
428
 
                                            time ((time_t *) 0) / (24L * 3600L);
429
 
                                        *changed = 1;
 
474
                                        sp.sp_flag   = SHADOW_SP_FLAG_UNSET;
 
475
                                        sp.sp_lstchg = (long) time ((time_t *) 0) / SCALE;
 
476
                                        if (0 == sp.sp_lstchg) {
 
477
                                                /* Better disable aging than
 
478
                                                 * requiring a password change
 
479
                                                 */
 
480
                                                sp.sp_lstchg = -1;
 
481
                                        }
 
482
                                        *changed = true;
430
483
 
431
484
                                        if (spw_update (&sp) == 0) {
432
485
                                                fprintf (stderr,
433
 
                                                         _("%s: can't update shadow entry for %s\n"),
434
 
                                                         Prog, sp.sp_namp);
 
486
                                                         _("%s: failed to prepare the new %s entry '%s'\n"),
 
487
                                                         Prog, spw_dbname (), sp.sp_namp);
435
488
                                                exit (E_CANTUPDATE);
436
489
                                        }
437
490
                                        /* remove password from /etc/passwd */
439
492
                                        pw.pw_passwd = SHADOW_PASSWD_STRING;    /* XXX warning: const */
440
493
                                        if (pw_update (&pw) == 0) {
441
494
                                                fprintf (stderr,
442
 
                                                         _("%s: can't update passwd entry for %s\n"),
443
 
                                                         Prog, pw.pw_name);
 
495
                                                         _("%s: failed to prepare the new %s entry '%s'\n"),
 
496
                                                         Prog, pw_dbname (), pw.pw_name);
444
497
                                                exit (E_CANTUPDATE);
445
498
                                        }
446
499
                                }
452
505
/*
453
506
 * check_spw_file - check the content of the shadowed password file (shadow)
454
507
 */
455
 
static void check_spw_file (int *errors, int *changed)
 
508
static void check_spw_file (int *errors, bool *changed)
456
509
{
457
510
        struct commonio_entry *spe, *tspe;
458
511
        struct spwd *spw;
465
518
                 * Do not treat lines which were missing in shadow
466
519
                 * and were added earlier.
467
520
                 */
468
 
                if (spe->line == NULL) {
 
521
                if (NULL == spe->line) {
469
522
                        continue;
470
523
                }
471
524
 
473
526
                 * If this is a NIS line, skip it. You can't "know" what NIS
474
527
                 * is going to do without directly asking NIS ...
475
528
                 */
476
 
                if ((spe->line[0] == '+') || (spe->line[0] == '-')) {
 
529
                if (('+' == spe->line[0]) || ('-' == spe->line[0])) {
477
530
                        continue;
478
531
                }
479
532
 
505
558
                         * to try out the next list element.
506
559
                         */
507
560
                      delete_spw:
508
 
                        SYSLOG ((LOG_INFO, "delete shadow line `%s'",
 
561
                        SYSLOG ((LOG_INFO, "delete shadow line '%s'",
509
562
                                 spe->line));
510
 
                        *changed = 1;
 
563
                        *changed = true;
511
564
 
512
565
                        __spw_del_entry (spe);
513
566
                        continue;
583
636
                /*
584
637
                 * Warn if last password change in the future.  --marekm
585
638
                 */
586
 
                if (!quiet
587
 
                    && (spw->sp_lstchg > time ((time_t *) 0) / SCALE)) {
 
639
                if (   !quiet
 
640
                    && (spw->sp_lstchg > (long) time ((time_t *) 0) / SCALE)) {
588
641
                        printf (_("user %s: last password change in the future\n"),
589
642
                                spw->sp_namp);
590
643
                        *errors += 1;
598
651
int main (int argc, char **argv)
599
652
{
600
653
        int errors = 0;
601
 
        int changed = 0;
 
654
        bool changed = false;
602
655
 
603
656
        /*
604
657
         * Get my name so that I can use it to report errors.
605
658
         */
606
659
        Prog = Basename (argv[0]);
607
660
 
608
 
        setlocale (LC_ALL, "");
609
 
        bindtextdomain (PACKAGE, LOCALEDIR);
610
 
        textdomain (PACKAGE);
 
661
        (void) setlocale (LC_ALL, "");
 
662
        (void) bindtextdomain (PACKAGE, LOCALEDIR);
 
663
        (void) textdomain (PACKAGE);
611
664
 
612
665
        OPENLOG ("pwck");
613
666
 
617
670
        open_files ();
618
671
 
619
672
        if (sort_mode) {
620
 
                pw_sort ();
 
673
                if (pw_sort () != 0) {
 
674
                        fprintf (stderr,
 
675
                                 _("%s: cannot sort entries in %s\n"),
 
676
                                 Prog, pw_dbname ());
 
677
                        fail_exit (E_CANTSORT);
 
678
                }
621
679
                if (is_shadow) {
622
 
                        spw_sort ();
 
680
                        if (spw_sort () != 0) {
 
681
                                fprintf (stderr,
 
682
                                         _("%s: cannot sort entries in %s\n"),
 
683
                                         Prog, spw_dbname ());
 
684
                                fail_exit (E_CANTSORT);
 
685
                        }
623
686
                }
624
 
                changed = 1;
 
687
                changed = true;
625
688
        } else {
626
689
                check_pw_file (&errors, &changed);
627
690
 
637
700
        /*
638
701
         * Tell the user what we did and exit.
639
702
         */
640
 
        if (errors != 0) {
 
703
        if (0 != errors) {
641
704
                printf (changed ?
642
705
                        _("%s: the files have been updated\n") :
643
706
                        _("%s: no changes\n"), Prog);
644
707
        }
645
708
 
646
709
        closelog ();
647
 
        exit (errors ? E_BADENTRY : E_OKAY);
 
710
        exit ((0 != errors) ? E_BADENTRY : E_OKAY);
648
711
}
649
712