From 355ad6a9e089717be726f956e6fa54fb07425a94 Mon Sep 17 00:00:00 2001 From: Alejandro Colomar Date: Wed, 22 Dec 2021 15:32:17 +0100 Subject: [PATCH] Have a single definition of date_to_str() PARAMETERS: According to the C2x charter, I reordered the parameters 'size' and 'buf' from previously existing date_to_str() definitions. C2x charter: > 15. Application Programming Interfaces (APIs) should be > self-documenting when possible. In particular, the order of > parameters in function declarations should be arranged such that > the size of an array appears before the array. The purpose is to > allow Variable-Length Array (VLA) notation to be used. This not > only makes the code's purpose clearer to human readers, but also > makes static analysis easier. Any new APIs added to the Standard > should take this into consideration. I used 'long' for the date parameter, as some uses of the function need to pass a negative value meaning "never". FUNCTION BODY: I didn't check '#ifdef HAVE_STRFTIME', which old definitions did, since strftime(3) is guaranteed by the C89 standard, and all of the conversion specifiers that we use are also specified by that standard, so we don't need any extensions at all. Signed-off-by: Alejandro Colomar --- lib/prototypes.h | 3 +++ libmisc/Makefile.am | 1 + libmisc/date_to_str.c | 46 +++++++++++++++++++++++++++++++++++++++++++ po/POTFILES.in | 1 + src/chage.c | 18 ++--------------- src/passwd.c | 20 +++---------------- src/usermod.c | 30 ++-------------------------- 7 files changed, 58 insertions(+), 61 deletions(-) create mode 100644 libmisc/date_to_str.c diff --git a/lib/prototypes.h b/lib/prototypes.h index b697e0ec..ff68114c 100644 --- a/lib/prototypes.h +++ b/lib/prototypes.h @@ -134,6 +134,9 @@ extern int copy_tree (const char *src_root, const char *dst_root, uid_t old_uid, uid_t new_uid, gid_t old_gid, gid_t new_gid); +/* date_to_str.c */ +extern void date_to_str (size_t size, char buf[size], long date); + /* encrypt.c */ extern /*@exposed@*//*@null@*/char *pw_encrypt (const char *, const char *); diff --git a/libmisc/Makefile.am b/libmisc/Makefile.am index 9f237e0d..3d319cd8 100644 --- a/libmisc/Makefile.am +++ b/libmisc/Makefile.am @@ -19,6 +19,7 @@ libmisc_la_SOURCES = \ cleanup_user.c \ console.c \ copydir.c \ + date_to_str.c \ entry.c \ env.c \ failure.c \ diff --git a/libmisc/date_to_str.c b/libmisc/date_to_str.c new file mode 100644 index 00000000..07e99f1a --- /dev/null +++ b/libmisc/date_to_str.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021, Alejandro Colomar + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the copyright holders or contributors may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#ident "$Id$" + +#include "prototypes.h" + +void date_to_str (size_t size, char buf[size], long date) +{ + time_t t; + + t = date; + if (date < 0) + (void) strncpy (buf, "never", size); + else + (void) strftime (buf, size, "%Y-%m-%d", gmtime (&t)); + buf[size - 1] = '\0'; +} diff --git a/po/POTFILES.in b/po/POTFILES.in index df761283..61b79dbd 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -41,6 +41,7 @@ libmisc/cleanup_group.c libmisc/cleanup_user.c libmisc/console.c libmisc/copydir.c +libmisc/date_to_str.c libmisc/entry.c libmisc/env.c libmisc/failure.c diff --git a/src/chage.c b/src/chage.c index c7490801..1c69d498 100644 --- a/src/chage.c +++ b/src/chage.c @@ -90,7 +90,6 @@ static long expdate; /* local function prototypes */ static /*@noreturn@*/void usage (int status); -static void date_to_str (char *buf, size_t maxsize, time_t date); static int new_fields (void); static void print_date (time_t date); static void list_fields (void); @@ -161,19 +160,6 @@ static /*@noreturn@*/void usage (int status) exit (status); } -static void date_to_str (char *buf, size_t maxsize, time_t date) -{ - struct tm *tp; - - tp = gmtime (&date); -#ifdef HAVE_STRFTIME - (void) strftime (buf, maxsize, "%Y-%m-%d", tp); -#else - (void) snprintf (buf, maxsize, "%04d-%02d-%02d", - tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday); -#endif /* HAVE_STRFTIME */ -} - /* * new_fields - change the user's password aging information interactively. * @@ -207,7 +193,7 @@ static int new_fields (void) if (-1 == lstchgdate || lstchgdate > LONG_MAX / SCALE) { strcpy (buf, "-1"); } else { - date_to_str (buf, sizeof buf, (time_t) (lstchgdate * SCALE)); + date_to_str (sizeof(buf), buf, lstchgdate * SCALE); } change_field (buf, sizeof buf, _("Last Password Change (YYYY-MM-DD)")); @@ -238,7 +224,7 @@ static int new_fields (void) if (-1 == expdate || LONG_MAX / SCALE < expdate) { strcpy (buf, "-1"); } else { - date_to_str (buf, sizeof buf, (time_t) (expdate * SCALE)); + date_to_str (sizeof(buf), buf, expdate * SCALE); } change_field (buf, sizeof buf, diff --git a/src/passwd.c b/src/passwd.c index 8ec55125..76fde70e 100644 --- a/src/passwd.c +++ b/src/passwd.c @@ -135,7 +135,6 @@ static int new_password (const struct passwd *); static void check_password (const struct passwd *, const struct spwd *); #endif /* !USE_PAM */ -static /*@observer@*/const char *date_to_str (time_t); static /*@observer@*/const char *pw_status (const char *); static void print_status (const struct passwd *); static /*@noreturn@*/void fail_exit (int); @@ -447,21 +446,6 @@ static void check_password (const struct passwd *pw, const struct spwd *sp) } #endif /* !USE_PAM */ -static /*@observer@*/const char *date_to_str (time_t t) -{ - static char buf[80]; - struct tm *tm; - - tm = gmtime (&t); -#ifdef HAVE_STRFTIME - (void) strftime (buf, sizeof buf, "%m/%d/%Y", tm); -#else /* !HAVE_STRFTIME */ - (void) snprintf (buf, sizeof buf, "%02d/%02d/%04d", - tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900); -#endif /* !HAVE_STRFTIME */ - return buf; -} - static /*@observer@*/const char *pw_status (const char *pass) { if (*pass == '*' || *pass == '!') { @@ -478,14 +462,16 @@ static /*@observer@*/const char *pw_status (const char *pass) */ static void print_status (const struct passwd *pw) { + char date[80]; struct spwd *sp; sp = getspnam (pw->pw_name); /* local, no need for xgetspnam */ if (NULL != sp) { + date_to_str (sizeof(date), date, sp->sp_lstchg * SCALE), (void) printf ("%s %s %s %lld %lld %lld %lld\n", pw->pw_name, pw_status (sp->sp_pwdp), - date_to_str (sp->sp_lstchg * SCALE), + date, ((long long)sp->sp_min * SCALE) / DAY, ((long long)sp->sp_max * SCALE) / DAY, ((long long)sp->sp_warn * SCALE) / DAY, diff --git a/src/usermod.c b/src/usermod.c index 0a075565..a13c1310 100644 --- a/src/usermod.c +++ b/src/usermod.c @@ -185,8 +185,6 @@ static bool sub_gid_locked = false; /* local function prototypes */ -static void date_to_str (/*@unique@*//*@out@*/char *buf, size_t maxsize, - long int date); static int get_groups (char *); static /*@noreturn@*/void usage (int status); static void new_pwent (struct passwd *); @@ -213,28 +211,6 @@ static void move_mailbox (void); extern int allow_bad_names; -static void date_to_str (/*@unique@*//*@out@*/char *buf, size_t maxsize, - long int date) -{ - struct tm *tp; - - if (date < 0) { - strncpy (buf, "never", maxsize); - } else { - time_t t = (time_t) date; - tp = gmtime (&t); -#ifdef HAVE_STRFTIME - strftime (buf, maxsize, "%Y-%m-%d", tp); -#else - (void) snprintf (buf, maxsize, "%04d-%02d-%02d", - tp->tm_year + 1900, - tp->tm_mon + 1, - tp->tm_mday); -#endif /* HAVE_STRFTIME */ - } - buf[maxsize - 1] = '\0'; -} - /* * get_groups - convert a list of group names to an array of group IDs * @@ -637,10 +613,8 @@ static void new_spent (struct spwd *spent) if (eflg) { /* log dates rather than numbers of days. */ char new_exp[16], old_exp[16]; - date_to_str (new_exp, sizeof(new_exp), - user_newexpire * DAY); - date_to_str (old_exp, sizeof(old_exp), - user_expire * DAY); + date_to_str (sizeof(new_exp), new_exp, user_newexpire * DAY); + date_to_str (sizeof(old_exp), old_exp, user_expire * DAY); #ifdef WITH_AUDIT audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "changing expiration date",