summaryrefslogtreecommitdiff
path: root/lib/mlibc/options/linux/generic/utmp-stubs.cpp
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-03-07 17:28:00 -0500
committerIan Moffett <ian@osmora.org>2024-03-07 17:28:32 -0500
commitbd5969fc876a10b18613302db7087ef3c40f18e1 (patch)
tree7c2b8619afe902abf99570df2873fbdf40a4d1a1 /lib/mlibc/options/linux/generic/utmp-stubs.cpp
parenta95b38b1b92b172e6cc4e8e56a88a30cc65907b0 (diff)
lib: Add mlibc
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'lib/mlibc/options/linux/generic/utmp-stubs.cpp')
-rw-r--r--lib/mlibc/options/linux/generic/utmp-stubs.cpp116
1 files changed, 116 insertions, 0 deletions
diff --git a/lib/mlibc/options/linux/generic/utmp-stubs.cpp b/lib/mlibc/options/linux/generic/utmp-stubs.cpp
new file mode 100644
index 0000000..658dfd3
--- /dev/null
+++ b/lib/mlibc/options/linux/generic/utmp-stubs.cpp
@@ -0,0 +1,116 @@
+#include <utmp.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <bits/ensure.h>
+#include <mlibc/debug.hpp>
+
+/*
+ * The code in this file is largely based on glibc.
+ * This includes:
+ * - setutent
+ * - read_last_entry
+ * - getutent
+ * - getutent_r
+ * - endutent
+ */
+static int fd = -1;
+static off_t offset;
+
+static struct utmp last_entry;
+
+void setutent(void) {
+ if(fd < 0) {
+ fd = open("/run/utmp", O_RDONLY | O_LARGEFILE | O_CLOEXEC);
+ if(fd == -1) {
+ return;
+ }
+ }
+
+ lseek(fd, 0, SEEK_SET);
+ offset = 0;
+}
+
+static ssize_t read_last_entry(void) {
+ struct utmp buf;
+ ssize_t bytes_read = pread(fd, &buf, sizeof(buf), offset);
+
+ if(bytes_read < 0) {
+ return -1;
+ } else if(bytes_read != sizeof(buf)) {
+ // EOF
+ return 0;
+ } else {
+ last_entry = buf;
+ offset += sizeof(buf);
+ return 1;
+ }
+}
+
+struct utmp *getutent(void) {
+ struct utmp *result;
+ static struct utmp *buf;
+ if(buf == NULL) {
+ buf = (struct utmp *)malloc(sizeof(struct utmp));
+ if(buf == NULL) {
+ return NULL;
+ }
+ }
+
+ if(getutent_r(buf, &result) < 0) {
+ return NULL;
+ }
+ return result;
+}
+
+int getutent_r(struct utmp *buf, struct utmp **res) {
+ int saved_errno = errno;
+
+ if(fd < 0) {
+ setutent();
+ }
+
+ ssize_t bytes_read = read_last_entry();
+
+ if(bytes_read <= 0) {
+ if(bytes_read == 0) {
+ errno = saved_errno;
+ *res = NULL;
+ return -1;
+ }
+ }
+
+ memcpy(buf, &last_entry, sizeof(struct utmp));
+ *res = buf;
+
+ return 0;
+}
+
+void endutent(void) {
+ if(fd >= 0) {
+ close(fd);
+ fd = -1;
+ }
+}
+
+struct utmp *pututline(const struct utmp *) {
+ mlibc::infoLogger() << "\e[31mmlibc: pututline() is a stub!\e[39m" << frg::endlog;
+ return NULL;
+}
+
+struct utmp *getutline(const struct utmp *) {
+ mlibc::infoLogger() << "\e[31mmlibc: getutline() is a stub!\e[39m" << frg::endlog;
+ return NULL;
+}
+
+int utmpname(const char *) {
+ mlibc::infoLogger() << "\e[31mmlibc: utmpname() is a stub!\e[39m" << frg::endlog;
+ return -1;
+}
+
+struct utmp *getutid(const struct utmp *) {
+ mlibc::infoLogger() << "\e[31mmlibc: getutid() is a stub!\e[39m" << frg::endlog;
+ return NULL;
+}