#include <sys/types.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <utmpx.h>
static int last_fd = -1;
static void
utempter_update_utmpx(int type, int fd, const char *host)
{
struct utmpx ut;
struct passwd *pw;
uid_t uid;
(void) memset(&ut, 0, sizeof (ut));
ut.ut_type = type;
ut.ut_pid = getpid();
ut.ut_session = getsid(0);
(void) gettimeofday(&ut.ut_tv, NULL);
if (snprintf(ut.ut_id, sizeof (ut.ut_id), "f%d", fd) >=
sizeof (ut.ut_id))
return;
uid = getuid();
if ((pw = getpwuid(uid)) == NULL)
return;
(void) strlcpy(ut.ut_user, pw->pw_name, sizeof (ut.ut_user));
if (type == DEAD_PROCESS) {
struct utmpx *ut1;
struct utmpx ut2;
(void) memset(&ut2, 0, sizeof (ut2));
ut2.ut_type = USER_PROCESS;
if (snprintf(ut2.ut_id, sizeof (ut2.ut_id), "f%d", fd) >=
sizeof (ut2.ut_id))
return;
if ((ut1 = getutxid(&ut2)) == NULL)
return;
(void) strlcpy(ut.ut_line, ut1->ut_line, sizeof (ut.ut_line));
} else {
char *line = ptsname(fd);
if (line == NULL)
return;
(void) strlcpy(ut.ut_line, line + strlen("/dev/"),
sizeof (ut.ut_line));
}
if (host != NULL) {
(void) strlcpy(ut.ut_host, host, sizeof (ut.ut_host));
ut.ut_syslen = strlen(ut.ut_host) + 1;
}
setutxent();
(void) pututxline(&ut);
endutxent();
}
int
utempter_add_record(int fd, const char *host)
{
utempter_update_utmpx(USER_PROCESS, fd, host);
last_fd = fd;
return (0);
}
int
utempter_remove_record(int fd)
{
utempter_update_utmpx(DEAD_PROCESS, fd, NULL);
if (last_fd == fd)
last_fd = -1;
return (0);
}
int
utempter_remove_added_record(void)
{
if (last_fd < 0)
return (0);
utempter_update_utmpx(DEAD_PROCESS, last_fd, NULL);
last_fd = -1;
return (0);
}
void
addToUtmp(const char *pty __unused, const char *host, int fd)
{
(void) utempter_add_record(fd, host);
}
void
removeFromUtmp(void)
{
(void) utempter_remove_added_record();
}
void
removeLineFromUtmp(const char *pty __unused, int fd)
{
(void) utempter_remove_record(fd);
}