diff options
Diffstat (limited to 'src/misc')
-rw-r--r-- | src/misc/deps-exe/s6-linux-init-echo | 1 | ||||
-rw-r--r-- | src/misc/deps-exe/s6-linux-init-logouthookd | 4 | ||||
-rw-r--r-- | src/misc/deps-exe/s6-linux-init-umountall | 1 | ||||
-rw-r--r-- | src/misc/s6-linux-init-echo.c | 39 | ||||
-rw-r--r-- | src/misc/s6-linux-init-logouthookd.c | 69 | ||||
-rw-r--r-- | src/misc/s6-linux-init-umountall.c | 70 |
6 files changed, 184 insertions, 0 deletions
diff --git a/src/misc/deps-exe/s6-linux-init-echo b/src/misc/deps-exe/s6-linux-init-echo new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/misc/deps-exe/s6-linux-init-echo @@ -0,0 +1 @@ +-lskarnet diff --git a/src/misc/deps-exe/s6-linux-init-logouthookd b/src/misc/deps-exe/s6-linux-init-logouthookd new file mode 100644 index 0000000..5a7d2fd --- /dev/null +++ b/src/misc/deps-exe/s6-linux-init-logouthookd @@ -0,0 +1,4 @@ +${LIBUTMPS} +-lskarnet +${TAINNOW_LIB} +${SOCKET_LIB} diff --git a/src/misc/deps-exe/s6-linux-init-umountall b/src/misc/deps-exe/s6-linux-init-umountall new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/misc/deps-exe/s6-linux-init-umountall @@ -0,0 +1 @@ +-lskarnet diff --git a/src/misc/s6-linux-init-echo.c b/src/misc/s6-linux-init-echo.c new file mode 100644 index 0000000..d39e649 --- /dev/null +++ b/src/misc/s6-linux-init-echo.c @@ -0,0 +1,39 @@ +/* ISC license. */ + +#include <skalibs/sgetopt.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> + +#define USAGE "s6-linux-init-echo [ -n ] [ -s sep ] args..." + +int main (int argc, char const *const *argv) +{ + char sep = ' ' ; + char donl = 1 ; + PROG = "s6-echo" ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "ns:", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'n': donl = 0 ; break ; + case 's': sep = *l.arg ; break ; + default : strerr_dieusage(100, USAGE) ; + } + } + argc -= l.ind ; argv += l.ind ; + } + for ( ; *argv ; argv++) + if ((buffer_puts(buffer_1small, *argv) < 0) + || (argv[1] && (buffer_put(buffer_1small, &sep, 1) < 0))) + goto err ; + if (donl && (buffer_put(buffer_1small, "\n", 1) < 0)) goto err ; + if (!buffer_flush(buffer_1small)) goto err ; + return 0 ; + + err: + strerr_diefu1sys(111, "write to stdout") ; +} diff --git a/src/misc/s6-linux-init-logouthookd.c b/src/misc/s6-linux-init-logouthookd.c new file mode 100644 index 0000000..cc542ba --- /dev/null +++ b/src/misc/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 ; +} diff --git a/src/misc/s6-linux-init-umountall.c b/src/misc/s6-linux-init-umountall.c new file mode 100644 index 0000000..24b22fc --- /dev/null +++ b/src/misc/s6-linux-init-umountall.c @@ -0,0 +1,70 @@ +/* ISC license. */ + +#include <string.h> +#include <sys/mount.h> + +#include <skalibs/bytestr.h> +#include <skalibs/buffer.h> +#include <skalibs/strerr2.h> +#include <skalibs/stralloc.h> +#include <skalibs/djbunix.h> +#include <skalibs/skamisc.h> + +#define BUFSIZE 4096 +#define MAXLINES 512 + +int main (int argc, char const *const *argv) +{ + stralloc mountpoints[MAXLINES] ; + char buf[BUFSIZE] ; + buffer b ; + stralloc sa = STRALLOC_ZERO ; + unsigned int line = 0 ; + int e = 0 ; + int r ; + int fd ; + + PROG = "s6-linux-init-umountall" ; + + + /* + We need to go through /proc/mounts *in reverse order*, because later mounts + may depend on earlier mounts. + The getmntent() family of functions has obviously not been designed for that + use case at all, and it is actually more difficult to use it than to do the + /proc/mounts parsing by hand. So, we do it by hand with skalibs functions. + That's how you can tell a good API from a terrible one. + */ + + fd = open_readb("/proc/mounts") ; + if (fd < 0) strerr_diefu1sys(111, "open /proc/mounts") ; + memset(mountpoints, 0, sizeof(mountpoints)) ; + buffer_init(&b, &buffer_read, fd, buf, BUFSIZE) ; + for (;;) + { + size_t n, p ; + if (line >= MAXLINES) strerr_dief1x(111, "/proc/mounts too big") ; + sa.len = 0 ; + r = skagetln(&b, &sa, '\n') ; + if (r <= 0) break ; + p = byte_chr(sa.s, sa.len, ' ') ; + if (p >= sa.len) strerr_dief1x(111, "bad /proc/mounts format") ; + p++ ; + n = byte_chr(sa.s + p, sa.len - p, ' ') ; + if (n == sa.len - p) strerr_dief1x(111, "bad /proc/mounts format") ; + if (!stralloc_catb(&mountpoints[line], sa.s + p, n) || !stralloc_0(&mountpoints[line])) + strerr_diefu1sys(111, "store mount point") ; + line++ ; + } + fd_close(fd) ; + stralloc_free(&sa) ; + if (r < 0) strerr_diefu1sys(111, "read /proc/mounts") ; + + while (line--) + if (umount(mountpoints[line].s) == -1) + { + e++ ; + strerr_warnwu2sys("umount ", mountpoints[line].s) ; + } + return e ; +} |