Date: Wed, 6 Jan 2010 10:29:54 +0000 (UTC) From: Ed Schouten <ed@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r201637 - in user/ed/utmpx: include lib/libc/gen Message-ID: <201001061029.o06ATsvs096571@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ed Date: Wed Jan 6 10:29:53 2010 New Revision: 201637 URL: http://svn.freebsd.org/changeset/base/201637 Log: Make utmpx actually work. Modified: user/ed/utmpx/include/utmpx.h user/ed/utmpx/lib/libc/gen/Symbol.map user/ed/utmpx/lib/libc/gen/getutxent.c user/ed/utmpx/lib/libc/gen/pututxline.c user/ed/utmpx/lib/libc/gen/utxdb.h Modified: user/ed/utmpx/include/utmpx.h ============================================================================== --- user/ed/utmpx/include/utmpx.h Wed Jan 6 10:21:16 2010 (r201636) +++ user/ed/utmpx/include/utmpx.h Wed Jan 6 10:29:53 2010 (r201637) @@ -42,7 +42,11 @@ struct utmpx { char ut_user[32]; char ut_id[8]; char ut_line[32]; - char ut_host[256]; +#if __BSD_VISIBLE + char ut_host[128]; +#else + char __ut_host[128]; +#endif pid_t ut_pid; short ut_type; #define EMPTY 0 @@ -59,6 +63,12 @@ struct utmpx { struct timeval ut_tv; }; +#if __BSD_VISIBLE +#define UTXDB_ACTIVE 0 +#define UTXDB_LASTLOGIN 1 +#define UTXDB_LOG 2 +#endif + __BEGIN_DECLS void endutxent(void); struct utmpx *getutxent(void); @@ -66,6 +76,10 @@ struct utmpx *getutxid(const struct utmp struct utmpx *getutxline(const struct utmpx *); struct utmpx *pututxline(const struct utmpx *); void setutxent(void); + +#if __BSD_VISIBLE +int setutxdb(int, const char *); +#endif __END_DECLS #endif /* !_UTMPX_H_ */ Modified: user/ed/utmpx/lib/libc/gen/Symbol.map ============================================================================== --- user/ed/utmpx/lib/libc/gen/Symbol.map Wed Jan 6 10:21:16 2010 (r201636) +++ user/ed/utmpx/lib/libc/gen/Symbol.map Wed Jan 6 10:29:53 2010 (r201637) @@ -373,6 +373,7 @@ FBSD_1.2 { getutxid; getutxline; pututxline; + setutxdb; setutxent; }; Modified: user/ed/utmpx/lib/libc/gen/getutxent.c ============================================================================== --- user/ed/utmpx/lib/libc/gen/getutxent.c Wed Jan 6 10:21:16 2010 (r201636) +++ user/ed/utmpx/lib/libc/gen/getutxent.c Wed Jan 6 10:29:53 2010 (r201637) @@ -22,45 +22,219 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); #include "namespace.h" +#include <errno.h> #include <stdio.h> +#include <string.h> #include <utmpx.h> +#include "utxdb.h" #include "un-namespace.h" +static FILE *uf = NULL; +static int udb; +static struct utmpx utx; + +int +setutxdb(int db, const char *file) +{ + + switch (db) { + case UTXDB_ACTIVE: + if (file == NULL) + file = _PATH_UTX_ACTIVE; + break; + case UTXDB_LASTLOGIN: + if (file == NULL) + file = _PATH_UTX_LASTLOGIN; + break; + case UTXDB_LOG: + if (file == NULL) + file = _PATH_UTX_LOG; + break; + default: + errno = EINVAL; + return (-1); + } + + if (uf != NULL) + fclose(uf); + uf = fopen(file, "r"); + if (uf == NULL) + return (-1); + udb = db; + return (0); +} + +void +setutxent(void) +{ + + setutxdb(UTXDB_ACTIVE, NULL); +} + void endutxent(void) { + + if (uf != NULL) { + fclose(uf); + uf = NULL; + } +} + +static void +futx_to_utx(const struct futx *fu, struct utmpx *ut) +{ + + memset(ut, 0, sizeof *ut); + + switch (fu->fu_type) { + case BOOT_TIME: + case OLD_TIME: + case NEW_TIME: + /* Extension: shutdown time. */ + case SHUTDOWN_TIME: + break; + case USER_PROCESS: + FTOU_STRING(fu, ut, id); + FTOU_STRING(fu, ut, user); + FTOU_STRING(fu, ut, line); + /* Extension: host name. */ + FTOU_STRING(fu, ut, host); + FTOU_PID(fu, ut); + break; + case INIT_PROCESS: + FTOU_STRING(fu, ut, id); + FTOU_PID(fu, ut); + break; + case LOGIN_PROCESS: + FTOU_STRING(fu, ut, id); + FTOU_STRING(fu, ut, user); + FTOU_PID(fu, ut); + break; + case DEAD_PROCESS: + FTOU_STRING(fu, ut, id); + FTOU_PID(fu, ut); + break; + default: + ut->ut_type = EMPTY; + return; + } + + FTOU_TYPE(fu, ut); + FTOU_TV(fu, ut); +} + +static struct futx * +getfutxent(void) +{ + static struct futx fu; + + if (uf == NULL) + setutxent(); + if (uf == NULL) + return (NULL); + + if (udb == UTXDB_LOG) { + uint16_t len; + + if (fread(&len, sizeof len, 1, uf) != 1) + return (NULL); + len = be16toh(len); + if (len > sizeof fu) { + /* Forward compatibility. */ + if (fread(&fu, sizeof fu, 1, uf) != 1) + return (NULL); + fseek(uf, len - sizeof fu, SEEK_CUR); + } else { + /* Partial record. */ + memset(&fu, 0, sizeof fu); + if (fread(&fu, len, 1, uf) != 1) + return (NULL); + } + return (NULL); + } else { + if (fread(&fu, sizeof fu, 1, uf) != 1) + return (NULL); + } + return (&fu); } struct utmpx * getutxent(void) { + struct futx *fu; - return (NULL); + fu = getfutxent(); + if (fu == NULL) + return (NULL); + futx_to_utx(fu, &utx); + return (&utx); } struct utmpx * getutxid(const struct utmpx *id) { + struct futx *fu; - return (NULL); + for (;;) { + fu = getfutxent(); + if (fu == NULL) + return (NULL); + + switch (fu->fu_type) { + case BOOT_TIME: + case OLD_TIME: + case NEW_TIME: + case SHUTDOWN_TIME: + if (fu->fu_type == id->ut_type) + goto found; + case USER_PROCESS: + case INIT_PROCESS: + case LOGIN_PROCESS: + case DEAD_PROCESS: + switch (id->ut_type) { + case USER_PROCESS: + case INIT_PROCESS: + case LOGIN_PROCESS: + case DEAD_PROCESS: + if (strncmp(fu->fu_id, id->ut_id, + MIN(sizeof fu->fu_id, sizeof id->ut_id)) == 0) + goto found; + } + } + } + +found: + futx_to_utx(fu, &utx); + return (&utx); } struct utmpx * getutxline(const struct utmpx *line) { + struct futx *fu; - return (NULL); -} - -void -setutxent(void) -{ + for (;;) { + fu = getfutxent(); + if (fu == NULL) + return (NULL); + + switch (fu->fu_type) { + case USER_PROCESS: + case LOGIN_PROCESS: + if (strncmp(fu->fu_line, line->ut_line, + MIN(sizeof fu->fu_line, sizeof line->ut_line)) == 0) + goto found; + } + } + +found: + futx_to_utx(fu, &utx); + return (&utx); } Modified: user/ed/utmpx/lib/libc/gen/pututxline.c ============================================================================== --- user/ed/utmpx/lib/libc/gen/pututxline.c Wed Jan 6 10:21:16 2010 (r201636) +++ user/ed/utmpx/lib/libc/gen/pututxline.c Wed Jan 6 10:29:53 2010 (r201637) @@ -22,14 +22,13 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); #include "namespace.h" +#include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <unistd.h> @@ -38,6 +37,25 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" static int +futx_open(const char *file) +{ + int fd; + struct stat sb; + + fd = _open(file, O_CREAT|O_RDWR, 0644); + if (fd < 0) + return (-1); + + /* Safety check: never use broken files. */ + if (_fstat(fd, &sb) != -1 && sb.st_size % sizeof(struct futx) != 0) { + _close(fd); + return (-1); + } + + return (fd); +} + +static int utx_to_futx(const struct utmpx *ut, struct futx *fu) { @@ -58,7 +76,6 @@ utx_to_futx(const struct utmpx *ut, stru UTOF_STRING(ut, fu, host); UTOF_PID(ut, fu); break; -#if 0 case INIT_PROCESS: UTOF_STRING(ut, fu, id); UTOF_PID(ut, fu); @@ -68,7 +85,6 @@ utx_to_futx(const struct utmpx *ut, stru UTOF_STRING(ut, fu, user); UTOF_PID(ut, fu); break; -#endif case DEAD_PROCESS: UTOF_STRING(ut, fu, id); UTOF_PID(ut, fu); @@ -93,7 +109,7 @@ utx_active_add(const struct futx *fu) * Register user login sessions. Overwrite entries of sessions * that have already been terminated. */ - fd = _open(_PATH_UTX_ACTIVE, O_CREAT|O_RDWR, 0644); + fd = futx_open(_PATH_UTX_ACTIVE); if (fd < 0) return; if (lockf(fd, F_LOCK, 0) == -1) { @@ -101,15 +117,19 @@ utx_active_add(const struct futx *fu) return; } while (_read(fd, &fe, sizeof fe) == sizeof fe) { - /* - * XXX: This check is invalid. We should perform a - * similar comparison as getutxid(). - */ - if (fe.fu_type != USER_PROCESS) { + switch (fe.fu_type) { + case USER_PROCESS: + case INIT_PROCESS: + case LOGIN_PROCESS: + if (strncmp(fu->fu_id, fe.fu_id, sizeof fe.fu_id) != 0) + continue; + /* FALLTHROUGH */ + default: lseek(fd, -sizeof fe, SEEK_CUR); - break; + goto found; } } +found: _write(fd, fu, sizeof *fu); lockf(fd, F_ULOCK, 0); _close(fd); @@ -118,8 +138,37 @@ utx_active_add(const struct futx *fu) static int utx_active_remove(const struct futx *fu) { + int fd; + struct futx fe; - return (0); + /* + * Remove user login sessions, having the same ut_id. + */ + fd = futx_open(_PATH_UTX_ACTIVE); + if (fd < 0) + return (0); + if (lockf(fd, F_LOCK, 0) == -1) { + _close(fd); + return (0); + } + while (_read(fd, &fe, sizeof fe) == sizeof fe) { + switch (fe.fu_type) { + case USER_PROCESS: + case INIT_PROCESS: + case LOGIN_PROCESS: + if (strncmp(fu->fu_id, fe.fu_id, sizeof fe.fu_id) != 0) + continue; + lseek(fd, -sizeof fe, SEEK_CUR); + _write(fd, fu, sizeof *fu); + lockf(fd, F_ULOCK, 0); + _close(fd); + return (0); + } + } + + lockf(fd, F_ULOCK, 0); + _close(fd); + return (1); } static void @@ -133,7 +182,7 @@ utx_lastlogin_add(const struct futx *fu) * current user already has an entry. If not, append a new * entry. */ - fd = _open(_PATH_UTX_LASTLOGIN, O_CREAT|O_RDWR, 0644); + fd = futx_open(_PATH_UTX_LASTLOGIN); if (fd < 0) return; if (lockf(fd, F_LOCK, 0) == -1) { @@ -164,8 +213,8 @@ utx_log_add(const struct futx *fu) /* * Append an entry to the log file. We only need to append * records to this file, so to conserve space, trim any trailing - * zero-bytes. Prepend a length field, indicating the record of - * the length, excluding the length field itself. + * zero-bytes. Prepend a length field, indicating the length of + * the record, excluding the length field itself. */ for (l = sizeof *fu; l > 0 && ((char *)fu)[l - 1] == '\0'; l--); r.len = htobe16(l); @@ -186,7 +235,7 @@ pututxline(const struct utmpx *utmpx) if (utx_to_futx(utmpx, &fu) != 0) return (NULL); - switch (utmpx->ut_type) { + switch (fu.fu_type) { case BOOT_TIME: case OLD_TIME: case NEW_TIME: @@ -196,9 +245,11 @@ pututxline(const struct utmpx *utmpx) utx_active_add(&fu); utx_lastlogin_add(&fu); break; -#if 0 +#if 0 /* XXX: Are these records of any use to us? */ case INIT_PROCESS: case LOGIN_PROCESS: + utx_active_add(&fu); + break; #endif case DEAD_PROCESS: if (utx_active_remove(&fu) != 0) Modified: user/ed/utmpx/lib/libc/gen/utxdb.h ============================================================================== --- user/ed/utmpx/lib/libc/gen/utxdb.h Wed Jan 6 10:21:16 2010 (r201636) +++ user/ed/utmpx/lib/libc/gen/utxdb.h Wed Jan 6 10:29:53 2010 (r201637) @@ -53,9 +53,26 @@ struct futx { uint32_t fu_pid; char fu_user[32]; char fu_line[32]; - char fu_host[256]; + char fu_host[128]; } __packed; +#define FTOU_STRING(fu, ut, field) do { \ + strncpy((ut)->ut_ ## field, (fu)->fu_ ## field, \ + MIN(sizeof (ut)->ut_ ## field - 1, sizeof (fu)->fu_ ## field)); \ +} while (0) +#define FTOU_PID(fu, ut) do { \ + (ut)->ut_pid = be32toh((fu)->fu_pid); \ +} while (0) +#define FTOU_TYPE(fu, ut) do { \ + (ut)->ut_type = (fu)->fu_type; \ +} while (0) +#define FTOU_TV(fu, ut) do { \ + uint64_t t; \ + t = be64toh((fu)->fu_tv); \ + (ut)->ut_tv.tv_sec = t / 1000000; \ + (ut)->ut_tv.tv_usec = t % 1000000; \ +} while (0) + #define UTOF_STRING(ut, fu, field) do { \ strncpy((fu)->fu_ ## field, (ut)->ut_ ## field, \ MIN(sizeof (fu)->fu_ ## field, sizeof (ut)->ut_ ## field)); \
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001061029.o06ATsvs096571>