user: implement mlibc as the libc, finally.
It's finally done.. Signed-off-by: kaguya <vpshinomiya@protonmail.com>
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user