9a9b91c940
It's finally done.. Signed-off-by: kaguya <vpshinomiya@protonmail.com>
173 lines
3.4 KiB
C++
173 lines
3.4 KiB
C++
#include <bits/ensure.h>
|
|
#include <errno.h>
|
|
#include <frg/mutex.hpp>
|
|
#include <frg/spinlock.hpp>
|
|
#include <mlibc/debug.hpp>
|
|
#include <paths.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <utmpx.h>
|
|
|
|
#include <mlibc/posix-sysdeps.hpp>
|
|
#include <mlibc/utmp.hpp>
|
|
|
|
namespace {
|
|
|
|
constexpr const char *defaultUtmpxPath = UTMPX_FILE;
|
|
|
|
const char *utmpxPath = defaultUtmpxPath;
|
|
frg::ticket_spinlock utmpxMutex;
|
|
|
|
frg::optional<int> utmpxFd = frg::null_opt;
|
|
|
|
utmpx returned;
|
|
|
|
} // namespace
|
|
|
|
void updwtmpx(const char *file, const struct utmpx *ut) {
|
|
int fd;
|
|
int err = mlibc::sys_open(file, O_RDWR | O_CREAT | O_CLOEXEC | O_APPEND, 0644, &fd);
|
|
if(err) {
|
|
mlibc::infoLogger() << "\e[31mmlibc: updwtmpx() failed to open " << file << ": "
|
|
<< strerror(err) << "\e[39m" << frg::endlog;
|
|
return;
|
|
}
|
|
|
|
mlibc::putUtmpEntry(fd, ut);
|
|
|
|
mlibc::sys_close(fd);
|
|
}
|
|
|
|
void endutxent(void) {
|
|
frg::unique_lock lock{utmpxMutex};
|
|
|
|
if(utmpxFd) {
|
|
mlibc::sys_close(utmpxFd.value());
|
|
utmpxFd = frg::null_opt;
|
|
}
|
|
}
|
|
|
|
void setutxent(void) {
|
|
frg::unique_lock lock{utmpxMutex};
|
|
|
|
if(!utmpxFd) {
|
|
int fd;
|
|
|
|
// If we are opening the utmp file as a non-root user with a root-made
|
|
// utmp, we need to open as a reader instead of a writer, O_RDWR will
|
|
// fail as no write permission can be obtained with 0644.
|
|
//
|
|
// The operations that need writing like updates will naturally fail
|
|
// because of the underlying sysdep failing.
|
|
int err = mlibc::sys_open(utmpxPath, O_RDWR | O_CREAT | O_CLOEXEC, 0644, &fd);
|
|
if(err == EACCES) {
|
|
err = mlibc::sys_open(utmpxPath, O_RDONLY | O_CLOEXEC, 0644, &fd);
|
|
}
|
|
|
|
if(err) {
|
|
mlibc::infoLogger() << "\e[31mmlibc: setutxent() failed to open " << utmpxPath << ": "
|
|
<< strerror(err) << "\e[39m" << frg::endlog;
|
|
utmpxFd = frg::null_opt;
|
|
} else {
|
|
utmpxFd = fd;
|
|
}
|
|
} else {
|
|
off_t discard;
|
|
mlibc::sys_seek(utmpxFd.value(), 0, SEEK_SET, &discard);
|
|
}
|
|
}
|
|
|
|
struct utmpx *getutxent(void) {
|
|
frg::unique_lock lock{utmpxMutex};
|
|
|
|
if(!utmpxFd)
|
|
setutxent();
|
|
if(!utmpxFd) {
|
|
errno = ENOENT;
|
|
return nullptr;
|
|
}
|
|
|
|
if(int e = mlibc::getUtmpEntry(*utmpxFd, &returned); e) {
|
|
errno = e;
|
|
return nullptr;
|
|
}
|
|
|
|
return &returned;
|
|
}
|
|
|
|
struct utmpx *pututxline(const struct utmpx *ut) {
|
|
frg::unique_lock lock{utmpxMutex};
|
|
|
|
if(!utmpxFd)
|
|
setutxent();
|
|
if(!utmpxFd) {
|
|
errno = ENOENT;
|
|
return nullptr;
|
|
}
|
|
|
|
if(int e = mlibc::putUtmpEntry(*utmpxFd, ut); e) {
|
|
errno = e;
|
|
return nullptr;
|
|
}
|
|
|
|
return (utmpx *) ut;
|
|
}
|
|
|
|
int utmpxname(const char *file) {
|
|
frg::unique_lock lock{utmpxMutex};
|
|
|
|
if(strcmp(file, utmpxPath)) {
|
|
if(!strcmp(file, defaultUtmpxPath)) {
|
|
free((void *) utmpxPath);
|
|
utmpxPath = defaultUtmpxPath;
|
|
} else {
|
|
char *name = strdup(file);
|
|
if(!name)
|
|
return -1;
|
|
|
|
if(utmpxPath != defaultUtmpxPath)
|
|
free((void *) utmpxPath);
|
|
|
|
utmpxPath = name;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct utmpx *getutxid(const struct utmpx *ut) {
|
|
frg::unique_lock lock{utmpxMutex};
|
|
|
|
if(!utmpxFd)
|
|
setutxent();
|
|
if(!utmpxFd) {
|
|
errno = ENOENT;
|
|
return nullptr;
|
|
}
|
|
|
|
if(int e = mlibc::getUtmpEntryById(*utmpxFd, ut, &returned); e) {
|
|
errno = e;
|
|
return nullptr;
|
|
}
|
|
|
|
return &returned;
|
|
}
|
|
|
|
struct utmpx *getutxline(const struct utmpx *ut) {
|
|
frg::unique_lock lock{utmpxMutex};
|
|
|
|
if(!utmpxFd)
|
|
setutxent();
|
|
if(!utmpxFd) {
|
|
errno = ENOENT;
|
|
return nullptr;
|
|
}
|
|
|
|
if(int e = mlibc::getUtmpEntryByType(*utmpxFd, ut, &returned); e) {
|
|
errno = e;
|
|
return nullptr;
|
|
}
|
|
|
|
return &returned;
|
|
}
|