about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--NEWS8
-rw-r--r--package/deps.mak3
-rw-r--r--package/info2
-rw-r--r--package/modes1
-rw-r--r--package/targets.mak3
-rw-r--r--src/include/utmps/utmps.h2
-rw-r--r--src/include/utmps/utmpx.h10
-rw-r--r--src/utmps/deps-exe/utmps-write6
-rw-r--r--src/utmps/utmps-write.c149
-rw-r--r--src/utmps/utmps_getid.c5
-rw-r--r--src/utmps/utmps_getline.c5
11 files changed, 184 insertions, 10 deletions
diff --git a/NEWS b/NEWS
index 2c165e2..0298f9e 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,13 @@
 Changelog for utmps.
 
+In 0.1.1.0
+----------
+
+ - Bugfixes.
+ - New binary: utmps-write. It's a generic utmp client, writing
+user-defined records to the utmp and/or wtmp databases.
+
+
 In 0.1.0.3
 ----------
 
diff --git a/package/deps.mak b/package/deps.mak
index 4093dd8..fa85734 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -14,6 +14,7 @@ src/utmps/pututxline.o src/utmps/pututxline.lo: src/utmps/pututxline.c src/utmps
 src/utmps/setutxent.o src/utmps/setutxent.lo: src/utmps/setutxent.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h
 src/utmps/updwtmpx.o src/utmps/updwtmpx.lo: src/utmps/updwtmpx.c src/include/utmps/config.h src/include/utmps/utmps.h
 src/utmps/utmps-utmpd.o src/utmps/utmps-utmpd.lo: src/utmps/utmps-utmpd.c src/utmps/utmps-internal.h src/include/utmps/utmpx.h
+src/utmps/utmps-write.o src/utmps/utmps-write.lo: src/utmps/utmps-write.c src/include/utmps/config.h src/include/utmps/utmps.h src/include/utmps/utmpx.h
 src/utmps/utmps-wtmpd.o src/utmps/utmps-wtmpd.lo: src/utmps/utmps-wtmpd.c src/utmps/utmps-internal.h src/include/utmps/utmpx.h
 src/utmps/utmps_end.o src/utmps/utmps_end.lo: src/utmps/utmps_end.c src/include/utmps/utmps.h
 src/utmps/utmps_getent.o src/utmps/utmps_getent.lo: src/utmps/utmps_getent.c src/utmps/utmps-internal.h src/include/utmps/utmps.h src/include/utmps/utmpx.h
@@ -38,5 +39,7 @@ libutmps.so.xyzzy: EXTRA_LIBS := -lskarnet
 libutmps.so.xyzzy: src/utmps/endutxent.lo src/utmps/getutxent.lo src/utmps/getutxid.lo src/utmps/getutxline.lo src/utmps/logwtmp.lo src/utmps/pututxline.lo src/utmps/setutxent.lo src/utmps/updwtmpx.lo src/utmps/utmpxname.lo src/utmps/utmps_end.lo src/utmps/utmps_getent.lo src/utmps/utmps_getid.lo src/utmps/utmps_getline.lo src/utmps/utmps_here.lo src/utmps/utmps_here_maybe_init.lo src/utmps/utmps_putline.lo src/utmps/utmps_rewind.lo src/utmps/utmps_start.lo src/utmps/utmps_updwtmpx.lo src/utmps/utmps_utmpx_pack.lo src/utmps/utmps_utmpx_unpack.lo
 utmps-utmpd: EXTRA_LIBS := -lskarnet ${MAYBEPTHREAD_LIB}
 utmps-utmpd: src/utmps/utmps-utmpd.o libutmps.a.xyzzy ${LIBNSSS}
+utmps-write: EXTRA_LIBS := -lskarnet ${SOCKET_LIB} ${MAYBEPTHREAD_LIB}
+utmps-write: src/utmps/utmps-write.o libutmps.a.xyzzy ${LIBNSSS} #{SYSCLOCK_LIB}
 utmps-wtmpd: EXTRA_LIBS := -lskarnet ${MAYBEPTHREAD_LIB}
 utmps-wtmpd: src/utmps/utmps-wtmpd.o libutmps.a.xyzzy ${LIBNSSS}
diff --git a/package/info b/package/info
index 8c31b77..fc959f2 100644
--- a/package/info
+++ b/package/info
@@ -1,4 +1,4 @@
 package=utmps
-version=0.1.0.3
+version=0.1.1.0
 category=admin
 package_macro_name=UTMPS
diff --git a/package/modes b/package/modes
index 39e777c..e0d2b24 100644
--- a/package/modes
+++ b/package/modes
@@ -1,2 +1,3 @@
 utmps-utmpd	0755
 utmps-wtmpd	0755
+utmps-write	0755
diff --git a/package/targets.mak b/package/targets.mak
index 3ff5217..1d68e83 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -1,6 +1,7 @@
 BIN_TARGETS := \
 utmps-utmpd \
-utmps-wtmpd
+utmps-wtmpd \
+utmps-write
 
 LIBEXEC_TARGETS :=
 
diff --git a/src/include/utmps/utmps.h b/src/include/utmps/utmps.h
index 9894276..cc60e9d 100644
--- a/src/include/utmps/utmps.h
+++ b/src/include/utmps/utmps.h
@@ -27,7 +27,7 @@ extern int utmps_getid (utmps *, unsigned short, char const *, struct utmpx *, t
 extern int utmps_getline (utmps *, char const *, struct utmpx *, tain const *, tain *) ;
 #define utmps_getline_g(a, line, b, deadline) utmps_getline(a, line, b, (deadline), &STAMP)
 extern int utmps_putline (utmps *, struct utmpx const *, tain const *, tain *) ;
-#define utmps_putline_g(a, entry, deadline) utmps_putline(a, entry, (deadine), &STAMP)
+#define utmps_putline_g(a, entry, deadline) utmps_putline(a, entry, (deadline), &STAMP)
 
 extern int utmps_updwtmpx (char const *, struct utmpx const *, tain const *, tain *) ;
 #define utmps_updwtmpx_g(file, b, deadline) utmps_updwtmpx(file, b, (deadline), &STAMP)
diff --git a/src/include/utmps/utmpx.h b/src/include/utmps/utmpx.h
index 0af2fac..8fa6dd2 100644
--- a/src/include/utmps/utmpx.h
+++ b/src/include/utmps/utmpx.h
@@ -26,18 +26,18 @@ struct utmpx
 {
   short ut_type ;
   pid_t ut_pid ;
-  char ut_line[UTMPS_UT_LINESIZE] ;
-  char ut_id[UTMPS_UT_IDSIZE] ;
-  char ut_user[UTMPS_UT_NAMESIZE] ;
+  char ut_line[UTMPS_UT_LINESIZE] __attribute__((nonstring)) ;
+  char ut_id[UTMPS_UT_IDSIZE] __attribute__((nonstring)) ;
+  char ut_user[UTMPS_UT_NAMESIZE] __attribute__((nonstring)) ;
 
-  char ut_host[UTMPS_UT_HOSTSIZE] ;
+  char ut_host[UTMPS_UT_HOSTSIZE] __attribute__((nonstring)) ;
   struct exit_status ut_exit ;
   pid_t ut_session ;
 
   struct timeval ut_tv ;
 
   uint32_t ut_addr_v6[4] ;
-  char _dummy[20] ;
+  char _dummy[20] __attribute__((nonstring)) ;
 } ;
 
 #define EMPTY 0
diff --git a/src/utmps/deps-exe/utmps-write b/src/utmps/deps-exe/utmps-write
new file mode 100644
index 0000000..bdb0ac9
--- /dev/null
+++ b/src/utmps/deps-exe/utmps-write
@@ -0,0 +1,6 @@
+libutmps.a.xyzzy
+${LIBNSSS}
+-lskarnet
+${SOCKET_LIB}
+#{SYSCLOCK_LIB}
+${MAYBEPTHREAD_LIB}
diff --git a/src/utmps/utmps-write.c b/src/utmps/utmps-write.c
new file mode 100644
index 0000000..061a0be
--- /dev/null
+++ b/src/utmps/utmps-write.c
@@ -0,0 +1,149 @@
+/* ISC license. */
+
+#include <unistd.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <pwd.h>
+
+#include <skalibs/sgetopt.h>
+#include <skalibs/strerr2.h>
+#include <skalibs/types.h>
+#include <skalibs/tai.h>
+#include <skalibs/fmtscan.h>
+
+#include <utmps/config.h>
+#include <utmps/utmps.h>
+#include <utmps/utmpx.h>
+
+#define USAGE "utmps-write [ -u ] [ -w ] [ -U utmpd-socket ] [ -W wtmpd-socket ] [ -t timeout ] [ -T timestamp ] [ -h host ] [ -i ip ] [ -l user ] [ -p pid ] id type line"
+#define dieusage() strerr_dieusage(100, USAGE)
+
+typedef struct uttype_s uttype, *uttype_ref ;
+struct uttype_s
+{
+  char const *s ;
+  short type ;
+} ;
+
+static uttype const uttypes[] =
+{
+  { "ACCOUNTING", 9 },
+  { "BOOT_TIME", 2 },
+  { "DEAD_PROCESS", 8 },
+  { "EMPTY", 0 },
+  { "INIT_PROCESS", 5 },
+  { "LOGIN_PROCESS", 6 },
+  { "NEW_TIME", 3 },
+  { "OLD_TIME", 4 },
+  { "RUN_LVL", 1 },
+  { "USER_PROCESS", 7 }
+} ;
+
+static int uttype_cmp (void const *a, void const *b)
+{
+  char const *key = a ;
+  uttype const *element = b ;
+  return strcasecmp(key, element->s) ;
+}
+
+int main (int argc, char const *const *argv)
+{
+  char const *usocket = UTMPS_UTMPD_PATH ;
+  char const *wsocket = UTMPS_WTMPD_PATH ;
+  char const *stamp = 0 ;
+  char const *user = 0 ;
+  char const *ipstr = 0 ;
+  unsigned int what = 0 ;
+  tain tto ;
+  struct utmpx b ;
+  PROG = "utmps-write" ;
+  memset(&b, 0, sizeof(struct utmpx)) ;
+  b.ut_pid = -1 ;
+
+  {
+    unsigned int t = 0 ;
+    subgetopt l = SUBGETOPT_ZERO ;
+    for (;;)
+    {
+      int opt = subgetopt_r(argc, argv, "uwU:W:t:T:h:i:l:p:", &l) ;
+      if (opt == -1) break ;
+      switch (opt)
+      {
+        case 'u' : what |= 1 ; break ;
+        case 'w' : what |= 2 ; break ;
+        case 'U' : usocket = l.arg ; break ;
+        case 'W' : wsocket = l.arg ; break ;
+        case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; break ;
+        case 'T' : stamp = l.arg ; break ;
+        case 'h' : strncpy(b.ut_host, l.arg, UTMPS_UT_HOSTSIZE) ; break ;
+        case 'i' : ipstr = l.arg ; break ;
+        case 'l' : user = l.arg ; break ;
+        case 'p' : if (!pid0_scan(l.arg, &b.ut_pid)) dieusage() ; break ;
+        default : dieusage() ;
+      }
+    }
+    argc -= l.ind ; argv += l.ind ;
+    if (t) tain_from_millisecs(&tto, t) ;
+    else tto = tain_infinite_relative ;
+  }
+  if (argc < 3) dieusage() ;
+  if (!what) strerr_dief1x(100, "at least one of -u or -w must be used") ;
+
+  {
+    uttype const *p = bsearch(argv[1], uttypes, sizeof(uttypes) / sizeof(uttype), sizeof(uttype), &uttype_cmp) ;
+    if (!p) strerr_dief2x(100, "invalid ut_type: ", argv[1]) ;
+    b.ut_type = p->type ;
+  }  
+  strncpy(b.ut_id, argv[0], UTMPS_UT_IDSIZE) ;
+  strncpy(b.ut_line, argv[2], UTMPS_UT_LINESIZE) ;
+  if (ipstr)
+  {
+   /* ut_addr_v6 is in host byte order, don't ask */
+    size_t len = ip6_scan(ipstr, (char *)b.ut_addr_v6) ;
+    if (!len || ipstr[len])
+    {
+      len = ip4_scan(ipstr, (char *)b.ut_addr_v6) ;
+      if (!len || ipstr[len])
+        strerr_dief2x(100, "invalid IP address: ", ipstr) ;
+    }
+  }
+  if (b.ut_pid == -1) b.ut_pid = getpid() ;
+  if (user) strncpy(b.ut_user, user, UTMPS_UT_NAMESIZE) ;
+  else
+  {
+    struct passwd *pw = getpwuid(getuid()) ;
+    if (pw) strncpy(b.ut_user, pw->pw_name, UTMPS_UT_NAMESIZE) ;
+  }
+  tain_now_set_stopwatch_g() ;
+  tain_add_g(&tto, &tto) ;
+  {
+    tain when ;
+    if (stamp)
+    {
+      size_t n = timestamp_scan(stamp, &when) ;
+      if (!n || stamp[n]) dieusage() ;
+    }
+    else when = STAMP ;
+    if (!timeval_from_tain(&b.ut_tv, &when))
+      strerr_diefu1sys(111, "timeval_from_tain") ;
+  }
+
+  if (what & 1)
+  {
+    utmps a = UTMPS_ZERO ;
+    if (!utmps_start_g(&a, usocket, &tto))
+      strerr_diefu2sys(111, "connect to utmpd at ", usocket) ;
+    if (!utmps_putline_g(&a, &b, &tto))
+      strerr_diefu1sys(111, "write utmp entry") ;
+    utmps_end(&a) ;
+  }
+
+  if (what & 2)
+  {
+    if (!utmps_updwtmpx_g(wsocket, &b, &tto))
+      strerr_diefu2sys(111, "write wtmp entry via wtmpd at ", wsocket) ;
+  }
+
+  return 0 ;
+}
diff --git a/src/utmps/utmps_getid.c b/src/utmps/utmps_getid.c
index 90e7d2a..a341149 100644
--- a/src/utmps/utmps_getid.c
+++ b/src/utmps/utmps_getid.c
@@ -3,8 +3,11 @@
 #include <sys/types.h>
 #include <string.h>
 #include <errno.h>
+
+#include <skalibs/gccattributes.h>
 #include <skalibs/types.h>
 #include <skalibs/unix-timed.h>
+
 #include <utmps/utmpx.h>
 #include <utmps/utmps.h>
 #include "utmps-internal.h"
@@ -12,7 +15,7 @@
 int utmps_getid (utmps *a, unsigned short type, char const *id, struct utmpx *b, tain const *deadline, tain *stamp)
 {
   ssize_t r ;
-  char sbuf[1 + USHORT_PACK + UTMPS_UT_IDSIZE] __attribute__ ((nonstring)) ;
+  char sbuf[1 + USHORT_PACK + UTMPS_UT_IDSIZE] gccattr_nonstring ;
   char rbuf[1 + sizeof(struct utmpx)] ;
   sbuf[0] = 'i' ;
   ushort_pack_big(sbuf + 1, type) ;
diff --git a/src/utmps/utmps_getline.c b/src/utmps/utmps_getline.c
index 6375f5d..5026788 100644
--- a/src/utmps/utmps_getline.c
+++ b/src/utmps/utmps_getline.c
@@ -3,7 +3,10 @@
 #include <sys/types.h>
 #include <string.h>
 #include <errno.h>
+
+#include <skalibs/gccattributes.h>
 #include <skalibs/unix-timed.h>
+
 #include <utmps/utmpx.h>
 #include <utmps/utmps.h>
 #include "utmps-internal.h"
@@ -11,7 +14,7 @@
 int utmps_getline (utmps *a, char const *line, struct utmpx *b, tain const *deadline, tain *stamp)
 {
   ssize_t r ;
-  char sbuf[1 + UTMPS_UT_LINESIZE] __attribute__ ((nonstring)) ;
+  char sbuf[1 + UTMPS_UT_LINESIZE] gccattr_nonstring ;
   char rbuf[1 + sizeof(struct utmpx)] ;
   sbuf[0] = 'l' ;
   strncpy(sbuf + 1, line, UTMPS_UT_LINESIZE) ;