diff options
Diffstat (limited to 'libc/misc/utmp/utent.c')
-rw-r--r-- | libc/misc/utmp/utent.c | 312 |
1 files changed, 147 insertions, 165 deletions
diff --git a/libc/misc/utmp/utent.c b/libc/misc/utmp/utent.c index a35bb2b84..3671bb05c 100644 --- a/libc/misc/utmp/utent.c +++ b/libc/misc/utmp/utent.c @@ -1,3 +1,4 @@ +/* vi: set sw=4 ts=4: */ /* utent.c <ndf@linux.mit.edu> */ /* Let it be known that this is very possibly the worst standard ever. HP-UX does one thing, someone else does another, linux another... If anyone @@ -18,230 +19,211 @@ #include <paths.h> #include <errno.h> #include <string.h> -#include <utmp.h> -#ifdef __UCLIBC_HAS_UTMPX__ -# include <utmpx.h> -#endif +#include "internal/utmp.h" #include <not-cancel.h> - #include <bits/uClibc_mutex.h> + __UCLIBC_MUTEX_STATIC(utmplock, PTHREAD_MUTEX_INITIALIZER); /* Some global crap */ static int static_fd = -1; -static struct utmp static_utmp; -static const char default_file_name[] = _PATH_UTMP; -static const char *static_ut_name = default_file_name; +static struct UT static_utmp; +static const char default_file[] = __DEFAULT_PATH_UTMP; +static const char *current_file = default_file; /* This function must be called with the LOCK held */ -static void __setutent_unlocked(void) +static void __set_unlocked(void) { - if (static_fd < 0) { - static_fd = open_not_cancel_2(static_ut_name, O_RDWR | O_CLOEXEC); if (static_fd < 0) { - static_fd = open_not_cancel_2(static_ut_name, O_RDONLY | O_CLOEXEC); - if (static_fd < 0) { - return; /* static_fd remains < 0 */ - } - } + static_fd = open_not_cancel_2(current_file, O_RDWR | O_CLOEXEC); + if (static_fd < 0) { + static_fd = open_not_cancel_2(current_file, O_RDONLY | O_CLOEXEC); + if (static_fd < 0) { + return; /* static_fd remains < 0 */ + } + } #ifndef __ASSUME_O_CLOEXEC - /* Make sure the file will be closed on exec() */ - fcntl_not_cancel(static_fd, F_SETFD, FD_CLOEXEC); + /* Make sure the file will be closed on exec() */ + fcntl_not_cancel(static_fd, F_SETFD, FD_CLOEXEC); #endif - return; - } - lseek(static_fd, 0, SEEK_SET); + return; + } + lseek(static_fd, 0, SEEK_SET); } #if defined __UCLIBC_HAS_THREADS__ -static void __setutent(void) +void set(void) { - __UCLIBC_MUTEX_LOCK(utmplock); - __setutent_unlocked(); - __UCLIBC_MUTEX_UNLOCK(utmplock); + __UCLIBC_MUTEX_LOCK(utmplock); + __set_unlocked(); + __UCLIBC_MUTEX_UNLOCK(utmplock); } #else -static void __setutent(void); -strong_alias(__setutent_unlocked,__setutent) -#endif -strong_alias(__setutent,setutent) - -#ifdef __UCLIBC_HAS_UTMPX__ -strong_alias(__setutent,setutxent) +strong_alias(__set_unlocked,set) #endif +/* not used in libc_hidden_def(set) */ +other(setutxent,setutent) /* This function must be called with the LOCK held */ -static struct utmp *__getutent_unlocked(void) +static struct UT *__get_unlocked(void) { - if (static_fd < 0) { - __setutent(); if (static_fd < 0) { - return NULL; + __set_unlocked(); + if (static_fd < 0) + return NULL; } - } - if (read_not_cancel(static_fd, &static_utmp, sizeof(static_utmp)) == sizeof(static_utmp)) { - return &static_utmp; - } + if (read_not_cancel(static_fd, &static_utmp, + sizeof(static_utmp)) == sizeof(static_utmp)) { + return &static_utmp; + } - return NULL; + return NULL; } #if defined __UCLIBC_HAS_THREADS__ -static struct utmp *__getutent(void) +struct UT *get(void) { - struct utmp *ret; + struct UT *ret; - __UCLIBC_MUTEX_LOCK(utmplock); - ret = __getutent_unlocked(); - __UCLIBC_MUTEX_UNLOCK(utmplock); - return ret; + __UCLIBC_MUTEX_LOCK(utmplock); + ret = __get_unlocked(); + __UCLIBC_MUTEX_UNLOCK(utmplock); + return ret; } #else -static struct utmp *__getutent(void); -strong_alias(__getutent_unlocked,__getutent) +strong_alias(__get_unlocked,get) #endif -strong_alias(__getutent,getutent) +/* not used in libc_hidden_def(get) */ +other(getutxent,getutent) -#ifdef __UCLIBC_HAS_UTMPX__ -struct utmpx *getutxent(void) +void end(void) { - return (struct utmpx *) __getutent (); -} -#endif - -static void __endutent(void) -{ - __UCLIBC_MUTEX_LOCK(utmplock); - if (static_fd >= 0) - close_not_cancel_no_status(static_fd); - static_fd = -1; - __UCLIBC_MUTEX_UNLOCK(utmplock); + __UCLIBC_MUTEX_LOCK(utmplock); + if (static_fd >= 0) + close_not_cancel_no_status(static_fd); + static_fd = -1; + __UCLIBC_MUTEX_UNLOCK(utmplock); } -strong_alias(__endutent,endutent) - -#ifdef __UCLIBC_HAS_UTMPX__ -strong_alias(__endutent,endutxent) -#endif +/* not used in libc_hidden_def(end) */ +other(endutxent,endutent) /* This function must be called with the LOCK held */ -static struct utmp *__getutid_unlocked(const struct utmp *utmp_entry) +static struct UT *__getid_unlocked(const struct UT *utmp_entry) { - struct utmp *lutmp; - unsigned type; - - /* We use the fact that constants we are interested in are: */ - /* RUN_LVL=1, ... OLD_TIME=4; INIT_PROCESS=5, ... USER_PROCESS=8 */ - type = utmp_entry->ut_type - 1; - type /= 4; - - while ((lutmp = __getutent_unlocked()) != NULL) { - if (type == 0 && lutmp->ut_type == utmp_entry->ut_type) { - /* one of RUN_LVL, BOOT_TIME, NEW_TIME, OLD_TIME */ - return lutmp; + struct UT *lutmp; + unsigned type; + + /* We use the fact that constants we are interested in are: */ + /* RUN_LVL=1, ... OLD_TIME=4; INIT_PROCESS=5, ... USER_PROCESS=8 */ + type = utmp_entry->ut_type - 1; + type /= 4; + + while ((lutmp = __get_unlocked()) != NULL) { + if (type == 0 && lutmp->ut_type == utmp_entry->ut_type) { + /* one of RUN_LVL, BOOT_TIME, NEW_TIME, OLD_TIME */ + return lutmp; + } + if (type == 1 + && strncmp(lutmp->ut_id, utmp_entry->ut_id, + sizeof(lutmp->ut_id)) == 0) { + /* INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, DEAD_PROCESS */ + return lutmp; + } } - if (type == 1 && strncmp(lutmp->ut_id, utmp_entry->ut_id, sizeof(lutmp->ut_id)) == 0) { - /* INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, DEAD_PROCESS */ - return lutmp; - } - } - return NULL; + return NULL; } #if defined __UCLIBC_HAS_THREADS__ -static struct utmp *__getutid(const struct utmp *utmp_entry) +struct UT *getid(const struct UT *utmp_entry) { - struct utmp *ret; + struct UT *ret; - __UCLIBC_MUTEX_LOCK(utmplock); - ret = __getutid_unlocked(utmp_entry); - __UCLIBC_MUTEX_UNLOCK(utmplock); - return ret; + __UCLIBC_MUTEX_LOCK(utmplock); + ret = __getid_unlocked(utmp_entry); + __UCLIBC_MUTEX_UNLOCK(utmplock); + return ret; } #else -static struct utmp *__getutid(const struct utmp *utmp_entry); -strong_alias(__getutid_unlocked,__getutid) -#endif -strong_alias(__getutid,getutid) - -#ifdef __UCLIBC_HAS_UTMPX__ -struct utmpx *getutxid(const struct utmpx *utmp_entry) -{ - return (struct utmpx *) __getutid ((const struct utmp *) utmp_entry); -} +strong_alias(__getid_unlocked,getid) #endif +/* not used in libc_hidden_def(getid) */ +other(getutxid,getutid) -static struct utmp *__getutline(const struct utmp *utmp_entry) +struct UT *getline(const struct UT *utmp_entry) { - struct utmp *lutmp; - - __UCLIBC_MUTEX_LOCK(utmplock); - while ((lutmp = __getutent_unlocked()) != NULL) { - if (lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) { - if (strncmp(lutmp->ut_line, utmp_entry->ut_line, sizeof(lutmp->ut_line)) == 0) { - break; - } + struct UT *lutmp; + + __UCLIBC_MUTEX_LOCK(utmplock); + while ((lutmp = __get_unlocked()) != NULL) { + if (lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) { + if (strncmp(lutmp->ut_line, utmp_entry->ut_line, + sizeof(lutmp->ut_line)) == 0) { + break; + } + } } - } - __UCLIBC_MUTEX_UNLOCK(utmplock); - return lutmp; + __UCLIBC_MUTEX_UNLOCK(utmplock); + return lutmp; } -strong_alias(__getutline,getutline) +/* libc_hidden_def(getline) */ +other(getutxline,getutline) -#ifdef __UCLIBC_HAS_UTMPX__ -struct utmpx *getutxline(const struct utmpx *utmp_entry) +struct UT *putline(const struct UT *utmp_entry) { - return (struct utmpx *) __getutline ((const struct utmp *) utmp_entry); + __UCLIBC_MUTEX_LOCK(utmplock); + /* Ignore the return value. That way, if they've already positioned + the file pointer where they want it, everything will work out. */ + lseek(static_fd, (off_t) - sizeof(struct UT), SEEK_CUR); + + if (__getid_unlocked(utmp_entry) != NULL) + lseek(static_fd, (off_t) - sizeof(struct UT), SEEK_CUR); + else + lseek(static_fd, (off_t) 0, SEEK_END); + if (write(static_fd, utmp_entry, sizeof(struct UT)) + != sizeof(struct UT)) + utmp_entry = NULL; + + __UCLIBC_MUTEX_UNLOCK(utmplock); + return (struct UT *)utmp_entry; } -#endif +/* not used in libc_hidden_def(putline) */ +other(pututxline,pututline) -static struct utmp *__pututline(const struct utmp *utmp_entry) +int name(const char *new_file) { - __UCLIBC_MUTEX_LOCK(utmplock); - /* Ignore the return value. That way, if they've already positioned - the file pointer where they want it, everything will work out. */ - lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); - - if (__getutid_unlocked(utmp_entry) != NULL) - lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); - else - lseek(static_fd, (off_t) 0, SEEK_END); - if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) - utmp_entry = NULL; - - __UCLIBC_MUTEX_UNLOCK(utmplock); - return (struct utmp *)utmp_entry; -} -strong_alias(__pututline,pututline) + __UCLIBC_MUTEX_LOCK(utmplock); + if (new_file != NULL) { + if (current_file != default_file) + free((char *)current_file); + current_file = strdup(new_file); + if (current_file == NULL) { + /* We should probably whine about out-of-memory + * errors here... Instead just reset to the default */ + current_file = default_file; + } + } -#ifdef __UCLIBC_HAS_UTMPX__ -struct utmpx *pututxline (const struct utmpx *utmp_entry) -{ - return (struct utmpx *) __pututline ((const struct utmp *) utmp_entry); + if (static_fd >= 0) { + close_not_cancel_no_status(static_fd); + static_fd = -1; + } + __UCLIBC_MUTEX_UNLOCK(utmplock); + return 0; /* or maybe return -(current_file != new_file)? */ } -#endif +/* not used in libc_hidden_def(name) */ +other(utmpxname,utmpname) -static int __utmpname(const char *new_ut_name) +void updw(const char *wtmp_file, const struct UT *lutmp) { - __UCLIBC_MUTEX_LOCK(utmplock); - if (new_ut_name != NULL) { - if (static_ut_name != default_file_name) - free((char *)static_ut_name); - static_ut_name = strdup(new_ut_name); - if (static_ut_name == NULL) { - /* We should probably whine about out-of-memory - * errors here... Instead just reset to the default */ - static_ut_name = default_file_name; + int fd; + + fd = open_not_cancel_2(wtmp_file, O_APPEND | O_WRONLY); + if (fd >= 0) { + if (lockf(fd, F_LOCK, 0) == 0) { + write_not_cancel(fd, lutmp, sizeof(struct UT)); + lockf(fd, F_ULOCK, 0); + close_not_cancel_no_status(fd); + } } - } - - if (static_fd >= 0) { - close_not_cancel_no_status(static_fd); - static_fd = -1; - } - __UCLIBC_MUTEX_UNLOCK(utmplock); - return 0; /* or maybe return -(static_ut_name != new_ut_name)? */ } -strong_alias(__utmpname,utmpname) - -#ifdef __UCLIBC_HAS_UTMPX__ -strong_alias(__utmpname,utmpxname) -#endif +/* not used in libc_hidden_def(updw) */ +other(updwtmpx,updwtmp) |