Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package wtmpdb for openSUSE:Factory checked 
in at 2023-06-23 21:52:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/wtmpdb (Old)
 and      /work/SRC/openSUSE:Factory/.wtmpdb.new.15902 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "wtmpdb"

Fri Jun 23 21:52:10 2023 rev:5 rq:1094677 version:0.7.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/wtmpdb/wtmpdb.changes    2023-06-14 
16:28:39.950219812 +0200
+++ /work/SRC/openSUSE:Factory/.wtmpdb.new.15902/wtmpdb.changes 2023-06-23 
21:52:17.590515959 +0200
@@ -1,0 +2,7 @@
+Wed Jun 21 06:52:21 UTC 2023 - Thorsten Kukuk <ku...@suse.com>
+
+- Update to version 0.7.0
+  - wtmpdb rotate: use sqlite3_bind_* internal
+  - wtmpdb last: Implement -x, -d, -i and -w options
+
+-------------------------------------------------------------------

Old:
----
  wtmpdb-0.6.0.tar.xz

New:
----
  wtmpdb-0.7.0.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ wtmpdb.spec ++++++
--- /var/tmp/diff_new_pack.nkaqUE/_old  2023-06-23 21:52:18.346520066 +0200
+++ /var/tmp/diff_new_pack.nkaqUE/_new  2023-06-23 21:52:18.350520088 +0200
@@ -18,7 +18,7 @@
 
 %define lname   libwtmpdb0
 Name:           wtmpdb
-Version:        0.6.0
+Version:        0.7.0
 Release:        0
 Summary:        Reports last logged in users and system reboots
 License:        BSD-2-Clause
@@ -78,7 +78,8 @@
 if [ "$1" -eq 0 ]; then
     pam-config -d --wtmpdb
 fi
-%service_del_postun_without_restart wtmpdb-update-boot.service 
wtmpdb-rotate.timer
+%service_del_postun_without_restart wtmpdb-update-boot.service
+%service_del_postun wtmpdb-rotate.timer
 
 %post   -n %{lname} -p /sbin/ldconfig
 %postun -n %{lname} -p /sbin/ldconfig

++++++ wtmpdb-0.6.0.tar.xz -> wtmpdb-0.7.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wtmpdb-0.6.0/NEWS new/wtmpdb-0.7.0/NEWS
--- old/wtmpdb-0.6.0/NEWS       2023-06-12 16:15:30.000000000 +0200
+++ new/wtmpdb-0.7.0/NEWS       2023-06-22 15:27:58.000000000 +0200
@@ -1,3 +1,7 @@
+Version 0.7.0
+* wtmpdb rotate: use sqlite3_bind_* internal
+* wtmpdb last: Implement -x, -d, -i and -w options
+
 Version 0.6.0
 * wtmpdb rotate: move old log entries into wtmpdb_<yyyymmdd>.db
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wtmpdb-0.6.0/include/wtmpdb.h 
new/wtmpdb-0.7.0/include/wtmpdb.h
--- old/wtmpdb-0.6.0/include/wtmpdb.h   2023-06-12 16:15:30.000000000 +0200
+++ new/wtmpdb-0.7.0/include/wtmpdb.h   2023-06-22 15:27:58.000000000 +0200
@@ -54,9 +54,8 @@
                            int (*cb_func) (void *unused, int argc,
                                            char **argv, char **azColName),
                            char **error);
-extern int wtmpdb_logrotate  (const char *db_path,
-                            const int days,
-                           char **error);
+extern int wtmpdb_rotate (const char *db_path, const int days, char **error, 
+                         char **wtmpdb_name, uint64_t *entries);
 
 /* helper function */
 extern int64_t wtmpdb_get_id (const char *db_path, const char *tty,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wtmpdb-0.6.0/lib/libwtmpdb.map 
new/wtmpdb-0.7.0/lib/libwtmpdb.map
--- old/wtmpdb-0.6.0/lib/libwtmpdb.map  2023-06-12 16:15:30.000000000 +0200
+++ new/wtmpdb-0.7.0/lib/libwtmpdb.map  2023-06-22 15:27:58.000000000 +0200
@@ -4,8 +4,11 @@
        wtmpdb_login;
        wtmpdb_logout;
        wtmpdb_read_all;
-       wtmpdb_logrotate;
        wtmpdb_timespec2usec;
        wtmpdb_get_id;
   local: *;
 };
+LIBWTMPDB_0.7 {
+  global:
+        wtmpdb_rotate;
+} LIBWTMPDB_0.1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wtmpdb-0.6.0/lib/sqlite.c 
new/wtmpdb-0.7.0/lib/sqlite.c
--- old/wtmpdb-0.6.0/lib/sqlite.c       2023-06-12 16:15:30.000000000 +0200
+++ new/wtmpdb-0.7.0/lib/sqlite.c       2023-06-22 15:27:58.000000000 +0200
@@ -29,6 +29,7 @@
 #include <time.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <libgen.h>
 #include <string.h>
 #include <limits.h>
@@ -441,23 +442,21 @@
   return 0;
 }
 
-static int logrotate_callback(void *data, int argc, char **argv, char 
**azColName) {
-  (void)argc;
-  (void)azColName;
-  sqlite3 *db_dest = (sqlite3*)data;
-  char *error = NULL;
+static int
+export_row (sqlite3 *db_dest, sqlite3_stmt *sqlStatement, char **error)
+{
   char *endptr;
 
-  const int type = atoi (argv[1]);
-  const char *user = argv[2];
-  const char *tty = argv[5];
-  const char *host = argv[6];
-  const char *service = argv[7];
-  uint64_t login_t = strtoul(argv[3], &endptr, 10);
+  const int type = sqlite3_column_int( sqlStatement, 1 );
+  const char *user = (const char*)sqlite3_column_text( sqlStatement, 2 );
+  const char *tty = (const char*)sqlite3_column_text( sqlStatement, 5 );
+  const char *host = (const char*)sqlite3_column_text( sqlStatement, 6 );
+  const char *service = (const char*)sqlite3_column_text( sqlStatement, 7 );
+  uint64_t login_t = strtoul((const char*)sqlite3_column_text( sqlStatement, 3 
), &endptr, 10);
   if ((errno == ERANGE && login_t == UINT64_MAX)
-      || (endptr == argv[1]) || (*endptr != '\0'))
+      || (endptr == (const char *)sqlite3_column_text( sqlStatement, 3 )) || 
(*endptr != '\0'))
     fprintf (stderr, "Invalid numeric time entry for 'login': '%s'\n",
-            argv[3]);
+            sqlite3_column_text( sqlStatement, 5 ));
 
   int id = add_entry (db_dest,
                      type,
@@ -466,57 +465,56 @@
                      tty,
                      host,
                      service,
-                     &error);
+                     error);
   if (id >=0)
     {
-      if ( argv[4] )
+      const char *logout = (const char*)sqlite3_column_text( sqlStatement, 4 );
+      if (logout)
        {
-          int64_t logout_t = strtoul(argv[4], &endptr, 10);
+          int64_t logout_t = strtoul(logout, &endptr, 10);
          if ((errno == ERANGE && logout_t == INT64_MAX)
-             || (endptr == argv[1]) || (*endptr != '\0'))
+             || (endptr == logout) || (*endptr != '\0'))
          {
-           fprintf (stderr, "Invalid numeric time entry for 'logout': '%s'\n", 
argv[4]);
+           fprintf (stderr, "Invalid numeric time entry for 'logout': '%s'\n", 
sqlite3_column_text( sqlStatement, 3 ));
            return -1;
          }
-          if (update_logout (db_dest, id, logout_t, &error) == -1)
+          if (update_logout (db_dest, id, logout_t, error) == -1)
          {
-            fprintf (stderr, "Cannot update DB value: '%s'\n", error);
+            fprintf (stderr, "Cannot update DB value: '%s'\n", *error);
            return -1;
          }
        }
     }
   else
     {
-       fprintf (stderr, "Cannot insert DB value: '%s'\n", error);
+       fprintf (stderr, "Cannot insert DB value: '%s'\n", *error);
        return -1;
     }
 
-   return 0;
+  return 0;
 }
 
 /* Reads all entries from database and calls the callback function for
    each entry.
    Returns 0 on success, -1 on failure. */
 int
-wtmpdb_logrotate  (const char *db_path,
-                  const int days,
-                  char **error)
+wtmpdb_rotate (const char *db_path, const int days, char **error,
+              char **wtmpdb_name, uint64_t *entries)
 {
   sqlite3 *db_src;
   sqlite3 *db_dest;
-  char *err_msg = 0;
+  uint64_t counter = 0;
   struct timespec ts_now;
   clock_gettime (CLOCK_REALTIME, &ts_now);
-  time_t rawtime = time(0); // System time: number of seconds since 00:00, Jan 
1 1970 UTC
-  time(&rawtime);
-  struct tm *tm = localtime (&rawtime);
-  uint64_t login_t = (ts_now.tv_sec - days * 86400) * USEC_PER_SEC;
+  time_t offset = ts_now.tv_sec - days * 86400;
+  struct tm *tm = localtime (&offset);
+  uint64_t login_t = offset * USEC_PER_SEC;
   char date[10];
   strftime (date, 10, "%Y%m%d", tm);
-
   char *dest_path = NULL;
   char *dest_file = strdup(db_path);
   strip_extension(dest_file);
+
   if (asprintf (&dest_path, "%s/%s_%s.db", dirname(dest_file), 
basename(dest_file), date) < 0)
     {
       *error = strdup ("Out of memory");
@@ -537,11 +535,14 @@
       return -1;
     }
 
-  char *sql = NULL;
-  if (asprintf (&sql, "SELECT * FROM wtmp where Login <= %lld",
-               (long long unsigned)login_t) < 0) /* conversation for 
i586/x86_64 build needed */
+  char *sql_select = "SELECT * FROM wtmp where Login <= ?";
+  sqlite3_stmt *res;
+  if (sqlite3_prepare_v2 (db_src, sql_select, -1, &res, 0) != SQLITE_OK)
     {
-      *error = strdup ("Out of memory");
+      if (error)
+        if (asprintf (error, "Failed to execute statement: %s",
+                      sqlite3_errmsg (db_src)) < 0)
+          *error = strdup ("Out of memory");
       sqlite3_close (db_src);
       sqlite3_close (db_dest);
       free(dest_path);
@@ -549,26 +550,32 @@
       return -1;
     }
 
-  if (sqlite3_exec (db_src, sql, logrotate_callback, (void*)db_dest, &err_msg) 
!= SQLITE_OK)
+  if (sqlite3_bind_int64 (res, 1, login_t) != SQLITE_OK)
     {
       if (error)
-        if (asprintf (error, "SQL error: %s", err_msg) < 0)
-          *error = strdup ("Out of memory");
+        if (asprintf (error, "Failed to create replace statement for login 
time: %s",
+                      sqlite3_errmsg (db_src)) < 0)
+          *error = strdup("Out of memory");
 
-      sqlite3_free (err_msg);
+      sqlite3_finalize(res);
       sqlite3_close (db_src);
       sqlite3_close (db_dest);
-      free(sql);
       free(dest_path);
       free(dest_file);
       return -1;
     }
 
-  free(sql);
-  if (asprintf (&sql, "DELETE FROM wtmp where Login <= %lld",
-               (long long unsigned)login_t) < 0) /* conversation for 
i586/x86_64 build needed */
+  int rc;
+  while ((rc = sqlite3_step(res)) == SQLITE_ROW) {
+    export_row (db_dest, res, error);
+    ++counter;
+  }
+  if (rc != SQLITE_DONE)
     {
-      *error = strdup ("Out of memory");
+      if (asprintf (error, "SQL error: %s", sqlite3_errmsg(db_src)) < 0)
+       *error = strdup ("Out of memory");
+
+      sqlite3_finalize(res);
       sqlite3_close (db_src);
       sqlite3_close (db_dest);
       free(dest_path);
@@ -576,24 +583,68 @@
       return -1;
     }
 
-  if (sqlite3_exec (db_src, sql, NULL, NULL, &err_msg) != SQLITE_OK)
+  sqlite3_finalize(res);
+
+  char *sql_delete = "DELETE FROM wtmp where Login <= ?";
+  if (sqlite3_prepare_v2 (db_src, sql_delete, -1, &res, 0) != SQLITE_OK)
     {
       if (error)
-        if (asprintf (error, "SQL error: %s", err_msg) < 0)
+        if (asprintf (error, "Failed to execute statement: %s",
+                      sqlite3_errmsg (db_src)) < 0)
           *error = strdup ("Out of memory");
+      sqlite3_close (db_src);
+      sqlite3_close (db_dest);
+      free(dest_path);
+      free(dest_file);
+      return -1;
+    }
 
-      sqlite3_free (err_msg);
+  if (sqlite3_bind_int64 (res, 1, login_t) != SQLITE_OK)
+    {
+      if (error)
+        if (asprintf (error, "Failed to create replace statement for login 
time: %s",
+                      sqlite3_errmsg (db_src)) < 0)
+          *error = strdup("Out of memory");
+
+      sqlite3_finalize(res);
+      sqlite3_close (db_src);
+      sqlite3_close (db_dest);
+      free(dest_path);
+      free(dest_file);
+      return -1;
+    }
+
+  int step = sqlite3_step (res);
+
+  if (step != SQLITE_DONE)
+    {
+      if (error)
+        if (asprintf (error, "Adding an entry did not return SQLITE_DONE: %d",
+                      step) < 0)
+          *error = strdup("Out of memory");
+
+      sqlite3_finalize(res);
       sqlite3_close (db_src);
       sqlite3_close (db_dest);
-      free(sql);
       free(dest_path);
       free(dest_file);
       return -1;
     }
 
-  free(sql);
+  sqlite3_finalize(res);
   sqlite3_close (db_src);
   sqlite3_close (db_dest);
+
+  if (counter > 0)
+    {
+      if (wtmpdb_name)
+       *wtmpdb_name = strdup (dest_path);
+      if (entries)
+       *entries = counter;
+    }
+  else
+    unlink (dest_path);
+
   free(dest_path);
   free(dest_file);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wtmpdb-0.6.0/man/wtmpdb.8.xml 
new/wtmpdb-0.7.0/man/wtmpdb.8.xml
--- old/wtmpdb-0.6.0/man/wtmpdb.8.xml   2023-06-12 16:15:30.000000000 +0200
+++ new/wtmpdb-0.7.0/man/wtmpdb.8.xml   2023-06-22 15:27:58.000000000 +0200
@@ -58,7 +58,7 @@
          <variablelist>
            <varlistentry>
              <term>
-               <option>-a, --lasthost</option>
+               <option>-a, --hostlast</option>
              </term>
              <listitem>
                <para>
@@ -68,6 +68,16 @@
            </varlistentry>
            <varlistentry>
              <term>
+               <option>-d, --dns</option>
+             </term>
+             <listitem>
+               <para>
+                 Translate IP addresses into a hostname.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>
                <option>-f, --file</option> <replaceable>FILE</replaceable>
              </term>
              <listitem>
@@ -88,6 +98,16 @@
            </varlistentry>
            <varlistentry>
              <term>
+               <option>-i, --ip</option>
+             </term>
+             <listitem>
+               <para>
+                 Translate hostnames to IP addresses.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>
                <option>-n, --limit</option> <replaceable>N</replaceable>
              </term>
              <listitem>
@@ -147,6 +167,26 @@
                </para>
              </listitem>
            </varlistentry>
+           <varlistentry>
+             <term>
+               <option>-w, --fullnames</option>
+             </term>
+             <listitem>
+               <para>
+                 Display full IP addresses and user and domain names.
+               </para>
+             </listitem>
+           </varlistentry>
+           <varlistentry>
+             <term>
+               <option>-x, --system</option>
+             </term>
+             <listitem>
+               <para>
+                 Display system shutdown entries.
+               </para>
+             </listitem>
+           </varlistentry>
          </variablelist>
          <para>
            <replaceable>TIME</replaceable> must be in the format 
<option>"YYYY-MM-DD HH:MM:SS"</option>.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wtmpdb-0.6.0/meson.build new/wtmpdb-0.7.0/meson.build
--- old/wtmpdb-0.6.0/meson.build        2023-06-12 16:15:30.000000000 +0200
+++ new/wtmpdb-0.7.0/meson.build        2023-06-22 15:27:58.000000000 +0200
@@ -11,7 +11,7 @@
                  'b_pie=true',
                  'warning_level=3',],
   license : ['BSD-2-Clause',],
-  version : '0.6.0',
+  version : '0.7.0',
 )
 
 conf = configuration_data()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wtmpdb-0.6.0/src/wtmpdb.c 
new/wtmpdb-0.7.0/src/wtmpdb.c
--- old/wtmpdb-0.6.0/src/wtmpdb.c       2023-06-12 16:15:30.000000000 +0200
+++ new/wtmpdb-0.7.0/src/wtmpdb.c       2023-06-22 15:27:58.000000000 +0200
@@ -35,6 +35,8 @@
 #include <string.h>
 #include <limits.h>
 #include <getopt.h>
+#include <netdb.h>
+#include <arpa/inet.h>
 #include <sys/utsname.h>
 
 #if HAVE_AUDIT
@@ -58,6 +60,10 @@
 static int hostlast = 0;
 static int nohostname = 0;
 static int noservice = 1;
+static int dflag = 0;
+static int iflag = 0;
+static int wflag = 0;
+static int xflag = 0;
 static const int name_len = 8; /* LAST_LOGIN_LEN */
 static int login_fmt = TIMEFMT_SHORT;
 static int login_len = 16; /* 16 = short, 24 = full */
@@ -70,6 +76,44 @@
 static time_t since = 0; /* Who was logged in after this time? */
 static time_t until = 0; /* Who was logged in until this time? */
 
+
+/* isipaddr - find out if string provided is an IP address or not
+   0 - no IP address
+   1 - is IP address
+*/
+static int
+isipaddr (const char *string, int *addr_type,
+          struct sockaddr_storage *addr)
+{
+  struct sockaddr_storage local_addr;
+  int is_ip;
+
+  if (addr == NULL)
+    addr = &local_addr;
+
+  memset(addr, 0, sizeof (struct sockaddr_storage));
+
+  /* first ipv4 */
+  if (inet_pton (AF_INET, string, &((struct sockaddr_in *)addr)->sin_addr) > 0)
+    {
+      if (addr_type != NULL)
+        *addr_type = AF_INET;
+      addr->ss_family = AF_INET;
+      is_ip = 1;
+    }
+  else if (inet_pton (AF_INET6, string, &((struct sockaddr_in6 
*)addr)->sin6_addr) > 0)
+    { /* then ipv6 */
+      if (addr_type != NULL)
+        *addr_type = AF_INET6;
+      addr->ss_family = AF_INET6;
+      is_ip = 1;
+    }
+  else
+    is_ip = 0;
+
+  return is_ip;
+}
+
 static int
 parse_time (const char *str, time_t *time)
 {
@@ -111,15 +155,86 @@
     }
 }
 
+static void
+calc_time_length(char *dst, size_t dstlen, int64_t start, int64_t stop)
+{
+  int64_t secs = (stop - start)/USEC_PER_SEC;
+  int mins  = (secs / 60) % 60;
+  int hours = (secs / 3600) % 24;
+  int days  = secs / 86400;
+
+  if (days)
+    snprintf (dst, dstlen, "(%d+%02d:%02d)", days, hours, mins);
+  else if (hours)
+    snprintf (dst, dstlen, " (%02d:%02d)", hours, mins);
+  else
+    snprintf (dst, dstlen, " (00:%02d)", mins);
+}
+
+static void
+print_line (const char *user, const char *tty, const char *host,
+           const char *print_service,
+           const char *logintime, const char *logouttime,
+           const char *length)
+{
+  char *line;
+
+  if (nohostname)
+    {
+      if (asprintf (&line, "%-8.*s %-12.12s%s %-*.*s - %-*.*s %s\n",
+                   wflag?(int)strlen(user):name_len, user, tty, print_service,
+                   login_len, login_len, logintime,
+                   logout_len, logout_len, logouttime,
+                   length) < 0)
+       {
+         fprintf (stderr, "Out f memory");
+         exit (EXIT_FAILURE);
+       }
+    }
+  else
+    {
+      if (hostlast)
+       {
+         if (asprintf (&line, "%-8.*s %-12.12s%s %-*.*s - %-*.*s %-12.12s 
%s\n",
+                       wflag?(int)strlen(user):name_len, user, tty, 
print_service,
+                       login_len, login_len, logintime,
+                       logout_len, logout_len, logouttime,
+                       length, host) < 0)
+           {
+             fprintf (stderr, "Out f memory");
+             exit (EXIT_FAILURE);
+           }
+       }
+      else
+       {
+         if (asprintf (&line, "%-8.*s %-12.12s %-16.*s%s %-*.*s - %-*.*s %s\n",
+                       wflag?(int)strlen(user):name_len, user, tty,
+                       wflag?(int)strlen(host):host_len, host, print_service,
+                       login_len, login_len, logintime,
+                       logout_len, logout_len, logouttime,
+                       length) < 0)
+           {
+             fprintf (stderr, "Out f memory");
+             exit (EXIT_FAILURE);
+           }
+       }
+    }
+
+  printf ("%s", line);
+  free (line);
+}
+
 static int
 print_entry (void *unused __attribute__((__unused__)),
             int argc, char **argv, char **azColName)
 {
+  char host_buf[NI_MAXHOST];
   char logintime[32]; /* LAST_TIMESTAMP_LEN */
   char logouttime[32]; /* LAST_TIMESTAMP_LEN */
   char length[32]; /* LAST_TIMESTAMP_LEN */
-  char *line;
   char *endptr;
+  int64_t logout_t = -1;
+  static int64_t newer_boot = -1;
 
   /* Yes, it's waste of time to let sqlite iterate through all entries
      even if we don't need more anymore, but telling sqlite we don't
@@ -145,7 +260,7 @@
 
   uint64_t login_t = strtoul(argv[3], &endptr, 10);
   if ((errno == ERANGE && login_t == UINT64_MAX)
-      || (endptr == argv[1]) || (*endptr != '\0'))
+      || (endptr == argv[3]) || (*endptr != '\0'))
     fprintf (stderr, "Invalid numeric time entry for 'login': '%s'\n",
             argv[3]);
 
@@ -166,9 +281,9 @@
 
   if (argv[4])
     {
-      int64_t logout_t = strtoul(argv[4], &endptr, 10);
+      logout_t = strtoul(argv[4], &endptr, 10);
       if ((errno == ERANGE && logout_t == INT64_MAX)
-         || (endptr == argv[1]) || (*endptr != '\0'))
+         || (endptr == argv[4]) || (*endptr != '\0'))
        fprintf (stderr, "Invalid numeric time entry for 'logout': '%s'\n",
                 argv[4]);
 
@@ -179,17 +294,7 @@
       format_time (logout_fmt, logouttime, sizeof (logouttime),
                   logout_t/USEC_PER_SEC);
 
-      int64_t secs = (logout_t - login_t)/USEC_PER_SEC;
-      int mins  = (secs / 60) % 60;
-      int hours = (secs / 3600) % 24;
-      int days  = secs / 86400;
-
-      if (days)
-       snprintf (length, sizeof(length), "(%d+%02d:%02d)", days, hours, mins);
-      else if (hours)
-       snprintf (length, sizeof(length), " (%02d:%02d)", hours, mins);
-      else
-       snprintf (length, sizeof(length), " (00:%02d)", mins);
+      calc_time_length (length, sizeof(length), login_t, logout_t);
     }
   else /* login but no logout */
     {
@@ -252,50 +357,67 @@
        }
     }
 
-  if (nohostname)
+  if (dflag && strlen (host) > 0)
     {
-      if (asprintf (&line, "%-8.*s %-12.12s%s %-*.*s - %-*.*s %s\n",
-                   name_len, user, tty, print_service,
-                   login_len, login_len, logintime,
-                   logout_len, logout_len, logouttime,
-                   length) < 0)
+      struct sockaddr_storage addr;
+      int addr_type = 0;
+
+      if (isipaddr (host, &addr_type, &addr))
        {
-         fprintf (stderr, "Out f memory");
-         exit (EXIT_FAILURE);
+         if (getnameinfo ((struct sockaddr*)&addr, sizeof (addr), host_buf, 
sizeof (host_buf),
+                          NULL, 0, NI_NAMEREQD) == 0)
+           host = host_buf;
        }
     }
-  else
+
+  if (iflag && strlen (host) > 0)
     {
-      if (hostlast)
+      struct addrinfo  hints;
+      struct addrinfo  *result;
+
+      memset(&hints, 0, sizeof(hints));
+      hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
+      hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
+      hints.ai_flags = 0;
+      hints.ai_protocol = 0;          /* Any protocol */
+      if (getaddrinfo(host, NULL, &hints, &result) == 0)
        {
-         if (asprintf (&line, "%-8.*s %-12.12s%s %-*.*s - %-*.*s %-12.12s 
%s\n",
-                       name_len, user, tty, print_service,
-                       login_len, login_len, logintime,
-                       logout_len, logout_len, logouttime,
-                       length, host) < 0)
+         if (result->ai_family == AF_INET)
            {
-             fprintf (stderr, "Out f memory");
-             exit (EXIT_FAILURE);
+             if (inet_ntop(result->ai_family,
+                           &((struct sockaddr_in *)result->ai_addr)->sin_addr,
+                           host_buf, sizeof (host_buf)) != NULL)
+               host = host_buf;
            }
-       }
-      else
-       {
-         if (asprintf (&line, "%-8.*s %-12.12s %-16.*s%s %-*.*s - %-*.*s %s\n",
-                       name_len, user, tty,
-                       host_len, host, print_service,
-                       login_len, login_len, logintime,
-                       logout_len, logout_len, logouttime,
-                       length) < 0)
+         else if (result->ai_family == AF_INET6)
            {
-             fprintf (stderr, "Out f memory");
-             exit (EXIT_FAILURE);
+             if (inet_ntop(result->ai_family,
+                           &((struct sockaddr_in6 
*)result->ai_addr)->sin6_addr,
+                           host_buf, sizeof (host_buf)) != NULL)
+               host = host_buf;
            }
+
+         freeaddrinfo(result);
        }
     }
-  free (print_service);
 
-  printf ("%s", line);
-  free (line);
+  print_line (user, tty, host, print_service, logintime, logouttime, length);
+
+  if (xflag && (type == BOOT_TIME) && newer_boot != -1 && logout_t != -1)
+    {
+      format_time (login_fmt, logintime, sizeof (logintime),
+                  logout_t/USEC_PER_SEC);
+      format_time (logout_fmt, logouttime, sizeof (logouttime),
+                  newer_boot/USEC_PER_SEC);
+      calc_time_length (length, sizeof(length), logout_t, newer_boot);
+
+      print_line ("shutdown", "system down", host, print_service,
+                 logintime, logouttime, length);
+    }
+  if (xflag && (type == BOOT_TIME))
+    newer_boot = login_t;
+
+  free (print_service);
 
   currentry++;
 
@@ -310,15 +432,19 @@
   fprintf (output, "Usage: wtmpdb [command] [options]\n");
   fputs ("Commands: last, boot, rotate, shutdown\n\n", output);
   fputs ("Options for last:\n", output);
-  fputs ("  -a, --lasthost      Display hostnames as last entry\n", output);
+  fputs ("  -a, --hostlast      Display hostnames as last entry\n", output);
+  fputs ("  -d, --dns           Translate IP addresses into a hostname\n", 
output);
   fputs ("  -f, --file FILE     Use FILE as wtmpdb database\n", output);
   fputs ("  -F, --fulltimes     Display full times and dates\n", output);
+  fputs ("  -i, --ip            Translate hostnames to IP addresses\n", 
output);
   fputs ("  -n, --limit N       Display only first N entries\n", output);
   fputs ("  -p, --present TIME  Display who was present at TIME\n", output);
   fputs ("  -R, --nohostname    Don't display hostname\n", output);
   fputs ("  -S, --service       Display PAM service used to login\n", output);
   fputs ("  -s, --since TIME    Display who was logged in after TIME\n", 
output);
   fputs ("  -t, --until TIME    Display who was logged in until TIME\n", 
output);
+  fputs ("  -w, --fullnames     Display full IP addresses and user and domain 
names\n", output);
+  fputs ("  -x, --system        Display system shutdown entries\n", output);
   fputs ("TIME must be in the format \"YYYY-MM-DD HH:MM:SS\"\n", output);
   fputs ("\n", output);
 
@@ -343,7 +469,7 @@
 }
 
 static int
-main_logrotate (int argc, char **argv)
+main_rotate (int argc, char **argv)
 {
   struct option const longopts[] = {
     {"file", required_argument, NULL, 'f'},
@@ -352,6 +478,8 @@
   };
   char *error = NULL;
   int days = LOGROTATE_DAYS;
+  char *wtmpdb_backup = NULL;
+  uint64_t entries = 0;
 
   int c;
 
@@ -377,7 +505,8 @@
       usage (EXIT_FAILURE);
     }
 
-  if (wtmpdb_logrotate (wtmpdb_path, days, &error) != 0)
+  if (wtmpdb_rotate (wtmpdb_path, days, &error,
+                    &wtmpdb_backup, &entries) != 0)
     {
       if (error)
         {
@@ -390,10 +519,13 @@
       exit (EXIT_FAILURE);
     }
 
-  char wtmptime[32];
-  format_time (TIMEFMT_CTIME, wtmptime, sizeof (wtmptime),
-              wtmp_start/USEC_PER_SEC);
-  printf ("\n%s begins %s\n", wtmpdb_path, wtmptime);
+  if (entries == 0 || wtmpdb_backup == NULL)
+    printf ("No old entries found\n");
+  else
+    printf ("%lli entries moved to %s\n", 
+           (long long unsigned int)entries, wtmpdb_backup);
+
+  free (wtmpdb_backup);
 
   return EXIT_SUCCESS;
 }
@@ -403,26 +535,33 @@
 {
   struct option const longopts[] = {
     {"hostlast", no_argument, NULL, 'a'},
+    {"dns", no_argument, NULL, 'd'},
     {"file", required_argument, NULL, 'f'},
+    {"fullnames", no_argument, NULL, 'w'},
     {"fulltimes", no_argument, NULL, 'F'},
+    {"ip", no_argument, NULL, 'i'},
     {"limit", required_argument, NULL, 'n'},
     {"present", required_argument, NULL, 'p'},
     {"nohostname", no_argument, NULL, 'R'},
-    {"since", required_argument, NULL, 's'},
     {"service", no_argument, NULL, 'S'},
+    {"since", required_argument, NULL, 's'},
+    {"system", no_argument, NULL, 'x'},
     {"until", required_argument, NULL, 'u'},
     {NULL, 0, NULL, '\0'}
   };
   char *error = NULL;
   int c;
 
-  while ((c = getopt_long (argc, argv, "af:Fn:p:RSs:t:", longopts, NULL)) != 
-1)
+  while ((c = getopt_long (argc, argv, "adf:Fin:p:RSs:t:wx", longopts, NULL)) 
!= -1)
     {
       switch (c)
         {
        case 'a':
          hostlast = 1;
          break;
+       case 'd':
+         dflag = 1;
+         break;
         case 'f':
           wtmpdb_path = optarg;
           break;
@@ -432,6 +571,9 @@
          logout_fmt = TIMEFMT_CTIME;
          logout_len = 24;
          break;
+       case 'i':
+         iflag = 1;
+         break;
        case 'n':
          maxentries = atoi (optarg);
          break;
@@ -462,6 +604,12 @@
              exit (EXIT_FAILURE);
            }
          break;
+       case 'w':
+         wflag = 1;
+         break;
+       case 'x':
+         xflag = 1;
+         break;
         default:
           usage (EXIT_FAILURE);
           break;
@@ -480,6 +628,24 @@
       usage (EXIT_FAILURE);
     }
 
+  if (nohostname && dflag)
+    {
+      fprintf (stderr, "The options -d and -R cannot be used together.\n");
+      usage (EXIT_FAILURE);
+    }
+
+  if (nohostname && iflag)
+    {
+      fprintf (stderr, "The options -i and -R cannot be used together.\n");
+      usage (EXIT_FAILURE);
+    }
+
+  if (dflag && iflag)
+    {
+      fprintf (stderr, "The options -d and -i cannot be used together.\n");
+      usage (EXIT_FAILURE);
+    }
+
   if (wtmpdb_read_all (wtmpdb_path, print_entry, &error) != 0)
     {
       if (error)
@@ -680,7 +846,7 @@
   else if (strcmp (argv[1], "shutdown") == 0)
     return main_shutdown (--argc, ++argv);
   else if (strcmp (argv[1], "rotate") == 0)
-    return main_logrotate (--argc, ++argv);
+    return main_rotate (--argc, ++argv);
 
   while ((c = getopt_long (argc, argv, "hv", longopts, NULL)) != -1)
     {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wtmpdb-0.6.0/tests/tst-login-logout.c 
new/wtmpdb-0.7.0/tests/tst-login-logout.c
--- old/wtmpdb-0.6.0/tests/tst-login-logout.c   2023-06-12 16:15:30.000000000 
+0200
+++ new/wtmpdb-0.7.0/tests/tst-login-logout.c   2023-06-22 15:27:58.000000000 
+0200
@@ -37,6 +37,8 @@
 
 #include "wtmpdb.h"
 
+#define DAYS 2
+
 static int
 test_args (const char *db_path, const char *user, const char *tty,
           const char *rhost, const char *service)
@@ -96,7 +98,7 @@
 }
 
 static int
-test_logrotate (const char *db_path)
+test_rotate (const char *db_path)
 {
   char *error = NULL;
 
@@ -118,7 +120,7 @@
       return 1;
     }
 
-  if (wtmpdb_logrotate (db_path, 1, &error) != 0)
+  if (wtmpdb_rotate (db_path, DAYS, &error, NULL, NULL) != 0)
     {
       if (error)
         {
@@ -126,7 +128,7 @@
           free (error);
         }
       else
-       fprintf (stderr, "wtmpdb_logrotate failed\n");
+       fprintf (stderr, "wtmpdb_rotate failed\n");
       return 1;
     }
 
@@ -170,13 +172,14 @@
   if (test_args (db_path, "user5", NULL, "localhost", NULL) != 0)
     return 1;
 
-  if (test_logrotate (db_path) != 0)
+  if (test_rotate (db_path) != 0)
     return 1;
 
   /* cleanup */
-  time_t rawtime = time(0); /* System time: number of seconds since 00:00, Jan 
1 1970 UTC */
-  time(&rawtime);
-  struct tm *tm = localtime (&rawtime);
+  struct timespec ts_now;
+  clock_gettime (CLOCK_REALTIME, &ts_now);
+  time_t offset = ts_now.tv_sec - DAYS * 86400;
+  struct tm *tm = localtime (&offset);
   char date[10];
   strftime (date, 10, "%Y%m%d", tm);
   char *backup_path = NULL;

Reply via email to