From 755a6d84a307a02fefb7c6f3d8d9cbc41da4e92a Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 15 Oct 2002 12:29:52 +0000 Subject: [PATCH] Support for utmp, wtmp and lastlog. Probably not terribly portable as yet, but seems to work plausibly on Linux. git-svn-id: svn://svn.tartarus.org/sgt/putty@2058 cda61777-01e9-0310-a592-d414129be87e --- unix/pterm.c | 14 ++++-- unix/pty.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ unix/unix.h | 2 + 3 files changed, 162 insertions(+), 4 deletions(-) diff --git a/unix/pterm.c b/unix/pterm.c index 58f9846e..0a72d3b8 100644 --- a/unix/pterm.c +++ b/unix/pterm.c @@ -1275,6 +1275,11 @@ void modalfatalbox(char *p, ...) exit(1); } +char *get_x_display(void) +{ + return gdk_get_display(); +} + int main(int argc, char **argv) { extern int pty_master_fd; /* declared in pty.c */ @@ -1338,9 +1343,6 @@ int main(int argc, char **argv) init_ucs(); - back = &pty_backend; - back->init(NULL, 0, NULL, 0); - inst->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); if (cfg.wintitle[0]) @@ -1404,7 +1406,6 @@ int main(int argc, char **argv) gtk_signal_connect(GTK_OBJECT(inst->sbar_adjust), "value_changed", GTK_SIGNAL_FUNC(scrollbar_moved), inst); gtk_timeout_add(20, timer_func, inst); - gdk_input_add(pty_master_fd, GDK_INPUT_READ, pty_input_func, inst); gtk_widget_add_events(GTK_WIDGET(inst->area), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | @@ -1422,6 +1423,11 @@ int main(int argc, char **argv) inst->currcursor = inst->textcursor; show_mouseptr(1); + back = &pty_backend; + back->init(NULL, 0, NULL, 0); + + gdk_input_add(pty_master_fd, GDK_INPUT_READ, pty_input_func, inst); + term_init(); term_size(24, 80, 2000); diff --git a/unix/pty.c b/unix/pty.c index 9774deaf..8edbe484 100644 --- a/unix/pty.c +++ b/unix/pty.c @@ -10,6 +10,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -23,9 +26,26 @@ #define TRUE 1 #endif +#ifndef UTMP_FILE +#define UTMP_FILE "/var/run/utmp" +#endif +#ifndef WTMP_FILE +#define WTMP_FILE "/var/log/wtmp" +#endif +#ifndef LASTLOG_FILE +#ifdef _PATH_LASTLOG +#define LASTLOG_FILE _PATH_LASTLOG +#else +#define LASTLOG_FILE "/var/log/lastlog" +#endif +#endif + int pty_master_fd; static int pty_child_pid; static sig_atomic_t pty_child_dead; +#ifndef OMIT_UTMP +static struct utmp utmp_entry; +#endif char **pty_argv; int pty_child_is_dead(void) @@ -35,6 +55,81 @@ int pty_child_is_dead(void) static void pty_size(void); +static void setup_utmp(char *ttyname) +{ +#ifndef OMIT_UTMP +#ifdef HAVE_LASTLOG + struct lastlog lastlog_entry; + FILE *lastlog; +#endif + struct passwd *pw; + char *location = get_x_display(); + FILE *wtmp; + + pw = getpwuid(getuid()); + memset(&utmp_entry, 0, sizeof(utmp_entry)); + utmp_entry.ut_type = USER_PROCESS; + utmp_entry.ut_pid = getpid(); + strncpy(utmp_entry.ut_line, ttyname+5, lenof(utmp_entry.ut_line)); + strncpy(utmp_entry.ut_id, ttyname+8, lenof(utmp_entry.ut_id)); + strncpy(utmp_entry.ut_user, pw->pw_name, lenof(utmp_entry.ut_user)); + strncpy(utmp_entry.ut_host, location, lenof(utmp_entry.ut_host)); + time(&utmp_entry.ut_time); + +#if defined HAVE_PUTUTLINE + utmpname(UTMP_FILE); + setutent(); + pututline(&utmp_entry); + endutent(); +#endif + + if ((wtmp = fopen(WTMP_FILE, "a")) != NULL) { + fwrite(&utmp_entry, 1, sizeof(utmp_entry), wtmp); + fclose(wtmp); + } + +#ifdef HAVE_LASTLOG + memset(&lastlog_entry, 0, sizeof(lastlog_entry)); + strncpy(lastlog_entry.ll_line, ttyname+5, lenof(lastlog_entry.ll_line)); + strncpy(lastlog_entry.ll_host, location, lenof(lastlog_entry.ll_host)); + time(&lastlog_entry.ll_time); + if ((lastlog = fopen(LASTLOG_FILE, "r+")) != NULL) { + fseek(lastlog, sizeof(lastlog_entry) * getuid(), SEEK_SET); + fwrite(&lastlog_entry, 1, sizeof(lastlog_entry), lastlog); + fclose(lastlog); + } +#endif + +#endif +} + +static void cleanup_utmp(void) +{ +#ifndef OMIT_UTMP + FILE *wtmp; + + utmp_entry.ut_type = DEAD_PROCESS; + memset(utmp_entry.ut_user, 0, lenof(utmp_entry.ut_user)); + time(&utmp_entry.ut_time); + + if ((wtmp = fopen(WTMP_FILE, "a")) != NULL) { + fwrite(&utmp_entry, 1, sizeof(utmp_entry), wtmp); + fclose(wtmp); + } + + memset(utmp_entry.ut_line, 0, lenof(utmp_entry.ut_line)); + utmp_entry.ut_time = 0; + +#if defined HAVE_PUTUTLINE + utmpname(UTMP_FILE); + setutent(); + pututline(&utmp_entry); + endutent(); +#endif + +#endif +} + static void sigchld_handler(int signum) { pid_t pid; @@ -44,6 +139,14 @@ static void sigchld_handler(int signum) pty_child_dead = TRUE; } +static void fatal_sig_handler(int signum) +{ + signal(signum, SIG_DFL); + cleanup_utmp(); + setuid(getuid()); + raise(signum); +} + /* * Called to set up the pty. * @@ -108,6 +211,53 @@ static char *pty_init(char *host, int port, char **realhost, int nodelay) #endif /* + * Trap as many fatal signals as we can in the hope of having + * the best chance to clean up utmp before termination. + */ + signal(SIGHUP, fatal_sig_handler); + signal(SIGINT, fatal_sig_handler); + signal(SIGQUIT, fatal_sig_handler); + signal(SIGILL, fatal_sig_handler); + signal(SIGABRT, fatal_sig_handler); + signal(SIGFPE, fatal_sig_handler); + signal(SIGPIPE, fatal_sig_handler); + signal(SIGALRM, fatal_sig_handler); + signal(SIGTERM, fatal_sig_handler); + signal(SIGSEGV, fatal_sig_handler); + signal(SIGUSR1, fatal_sig_handler); + signal(SIGUSR2, fatal_sig_handler); +#ifdef SIGBUS + signal(SIGBUS, fatal_sig_handler); +#endif +#ifdef SIGPOLL + signal(SIGPOLL, fatal_sig_handler); +#endif +#ifdef SIGPROF + signal(SIGPROF, fatal_sig_handler); +#endif +#ifdef SIGSYS + signal(SIGSYS, fatal_sig_handler); +#endif +#ifdef SIGTRAP + signal(SIGTRAP, fatal_sig_handler); +#endif +#ifdef SIGVTALRM + signal(SIGVTALRM, fatal_sig_handler); +#endif +#ifdef SIGXCPU + signal(SIGXCPU, fatal_sig_handler); +#endif +#ifdef SIGXFSZ + signal(SIGXFSZ, fatal_sig_handler); +#endif +#ifdef SIGIO + signal(SIGIO, fatal_sig_handler); +#endif + /* Also clean up utmp on normal exit. */ + atexit(cleanup_utmp); + setup_utmp(name); + + /* * Fork and execute the command. */ pid = fork(); diff --git a/unix/unix.h b/unix/unix.h index d4c3328f..8e645a2d 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -37,6 +37,8 @@ int wc_to_mb(int codepage, int flags, wchar_t *wcstr, int wclen, char *mbstr, int mblen, char *defchr, int *defused); void init_ucs(void); +char *get_x_display(void); + #define DEFAULT_CODEPAGE 0 /* FIXME: no idea how to do this */ #endif -- 2.11.0