summaryrefslogtreecommitdiff
path: root/src/logout-hook/s6-linux-init-logouthookd.c
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2019-03-02 09:41:24 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2019-03-02 09:41:24 +0000
commit23fba266a9454ee6ca095b7f6eccf523f6526607 (patch)
tree7350fdaba49b1529a13d50f6396aea35f340954d /src/logout-hook/s6-linux-init-logouthookd.c
parent54d0dc0990f13a86680fa55c623f0570853749ac (diff)
downloads6-linux-init-23fba266a9454ee6ca095b7f6eccf523f6526607.tar.xz
Save pending changes in 1.0.0.0 branch
Diffstat (limited to 'src/logout-hook/s6-linux-init-logouthookd.c')
-rw-r--r--src/logout-hook/s6-linux-init-logouthookd.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/logout-hook/s6-linux-init-logouthookd.c b/src/logout-hook/s6-linux-init-logouthookd.c
new file mode 100644
index 0000000..cc542ba
--- /dev/null
+++ b/src/logout-hook/s6-linux-init-logouthookd.c
@@ -0,0 +1,69 @@
+/* ISC license. */
+
+#include <skalibs/sysdeps.h>
+
+#ifndef SKALIBS_HASSOPEERCRED
+#error "The SO_PEERCRED option to getsockopt() is required."
+#endif
+
+#include <skalibs/nonposix.h>
+
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <utmpx.h>
+
+#include <skalibs/allreadwrite.h>
+#include <skalibs/strerr2.h>
+
+#ifndef UT_NAMESIZE
+#define UT_NAMESIZE 32
+#endif
+
+#ifndef UT_HOSTSIZE
+#define UT_HOSTSIZE 256
+#endif
+
+int main (void)
+{
+ struct utmpx *utx ;
+ struct ucred client ;
+ socklen_t len = sizeof(client) ;
+ ssize_t r ;
+ char c ;
+
+ close(1) ;
+ if (getsockopt(0, SOL_SOCKET, SO_PEERCRED, &client, &len) == -1)
+ strerr_diefu1sys(111, "getsockopt") ;
+
+ /* Only take connections from root. */
+ if (client.uid) return 1 ;
+
+ /* Wait for the client to die. */
+ r = fd_read(0, &c, 1) ;
+ if (r < 0) strerr_diefu1sys(111, "read from stdin") ;
+ if (r) strerr_dief1x(2, "client attempted to write") ;
+
+ /* Clean up utmpx record for the client's pid, then exit. */
+ for (;;)
+ {
+ errno = 0 ;
+ utx = getutxent() ;
+ if (!utx) break ;
+ if (utx->ut_pid == client.pid) goto gotit ;
+ }
+ if (errno) strerr_diefu1sys(111, "getutxent") ;
+ return 0 ;
+
+ gotit:
+ utx->ut_type = DEAD_PROCESS ;
+ memset(utx->ut_user, 0, UT_NAMESIZE) ;
+ memset(utx->ut_host, 0, UT_HOSTSIZE) ;
+ utx->ut_tv.tv_sec = 0 ;
+ utx->ut_tv.tv_usec = 0 ;
+ setutxent() ;
+ if (!pututxline(utx)) strerr_diefu1sys(111, "pututxline") ;
+ return 0 ;
+}