svn commit: r201637 - in user/ed/utmpx: include lib/libc/gen
Ed Schouten
ed at FreeBSD.org
Wed Jan 6 10:29:54 UTC 2010
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)); \
More information about the svn-src-user
mailing list