From 6e3bc8a67ad30991ea22b7bd691a1533d864b53e Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Fri, 26 Aug 2011 12:15:09 +0200 Subject: login: utmp code refactoring Signed-off-by: Karel Zak --- login-utils/login.c | 170 ++++++++++++++++++++++++---------------------------- 1 file changed, 77 insertions(+), 93 deletions(-) (limited to 'login-utils/login.c') diff --git a/login-utils/login.c b/login-utils/login.c index 91f5b815c..c4f3d9cd0 100644 --- a/login-utils/login.c +++ b/login-utils/login.c @@ -289,9 +289,8 @@ static void logbtmp(struct login_context *cxt) memcpy(&ut.ut_addr_v6, cxt->hostaddress, sizeof(ut.ut_addr_v6)); } -#if HAVE_UPDWTMP /* bad luck for ancient systems */ + updwtmp(_PATH_BTMP, &ut); -#endif } static int child_pid = 0; @@ -390,6 +389,81 @@ static void log_lastlog(struct login_context *cxt) close(fd); } +/* + * Update wtmp and utmp logs + */ +static void log_utmp(struct login_context *cxt) +{ + struct utmp ut; + struct utmp *utp; + struct timeval tv; + + utmpname(_PATH_UTMP); + setutent(); + + /* Find pid in utmp. + * + * login sometimes overwrites the runlevel entry in /var/run/utmp, + * confusing sysvinit. I added a test for the entry type, and the + * problem was gone. (In a runlevel entry, st_pid is not really a pid + * but some number calculated from the previous and current runlevel). + * -- Michael Riepe + */ + while ((utp = getutent())) + if (utp->ut_pid == cxt->pid + && utp->ut_type >= INIT_PROCESS + && utp->ut_type <= DEAD_PROCESS) + break; + + /* If we can't find a pre-existing entry by pid, try by line. + * BSD network daemons may rely on this. + */ + if (utp == NULL) { + setutent(); + ut.ut_type = LOGIN_PROCESS; + strncpy(ut.ut_line, cxt->tty_name, sizeof(ut.ut_line)); + utp = getutline(&ut); + } + + if (utp) + memcpy(&ut, utp, sizeof(ut)); + else + /* some gettys/telnetds don't initialize utmp... */ + memset(&ut, 0, sizeof(ut)); + + if (ut.ut_id[0] == 0) + strncpy(ut.ut_id, cxt->tty_number, sizeof(ut.ut_id)); + + strncpy(ut.ut_user, cxt->username, sizeof(ut.ut_user)); + xstrncpy(ut.ut_line, cxt->tty_name, sizeof(ut.ut_line)); + +#ifdef _HAVE_UT_TV /* in included by */ + gettimeofday(&tv, NULL); + ut.ut_tv.tv_sec = tv.tv_sec; + ut.ut_tv.tv_usec = tv.tv_usec; +#else + { + time_t t; + time(&t); + ut.ut_time = t; /* ut_time is not always a time_t */ + /* glibc2 #defines it as ut_tv.tv_sec */ + } +#endif + ut.ut_type = USER_PROCESS; + ut.ut_pid = cxt->pid; + if (cxt->hostname) { + xstrncpy(ut.ut_host, cxt->hostname, sizeof(ut.ut_host)); + if (cxt->hostaddress && *cxt->hostaddress) + memcpy(&ut.ut_addr_v6, cxt->hostaddress, + sizeof(ut.ut_addr_v6)); + } + + pututline(&ut); + endutent(); + + updwtmp(_PATH_WTMP, &ut); +} + /* encapsulate stupid "void **" pam_get_item() API */ static int loginpam_get_username(pam_handle_t * pamh, char **name) { @@ -772,97 +846,7 @@ int main(int argc, char **argv) } } - /* for linux, write entries in utmp and wtmp */ - { - struct utmp ut; - struct utmp *utp; - struct timeval tv; - - utmpname(_PATH_UTMP); - setutent(); - - /* Find pid in utmp. - login sometimes overwrites the runlevel entry in /var/run/utmp, - confusing sysvinit. I added a test for the entry type, and the problem - was gone. (In a runlevel entry, st_pid is not really a pid but some number - calculated from the previous and current runlevel). - Michael Riepe - */ - while ((utp = getutent())) - if (utp->ut_pid == cxt.pid - && utp->ut_type >= INIT_PROCESS - && utp->ut_type <= DEAD_PROCESS) - break; - - /* If we can't find a pre-existing entry by pid, try by line. - BSD network daemons may rely on this. (anonymous) */ - if (utp == NULL) { - setutent(); - ut.ut_type = LOGIN_PROCESS; - strncpy(ut.ut_line, cxt.tty_name, sizeof(ut.ut_line)); - utp = getutline(&ut); - } - - if (utp) { - memcpy(&ut, utp, sizeof(ut)); - } else { - /* some gettys/telnetds don't initialize utmp... */ - memset(&ut, 0, sizeof(ut)); - } - - if (ut.ut_id[0] == 0) - strncpy(ut.ut_id, cxt.tty_number, sizeof(ut.ut_id)); - - strncpy(ut.ut_user, cxt.username, sizeof(ut.ut_user)); - xstrncpy(ut.ut_line, cxt.tty_name, sizeof(ut.ut_line)); -#ifdef _HAVE_UT_TV /* in included by */ - gettimeofday(&tv, NULL); - ut.ut_tv.tv_sec = tv.tv_sec; - ut.ut_tv.tv_usec = tv.tv_usec; -#else - { - time_t t; - time(&t); - ut.ut_time = t; /* ut_time is not always a time_t */ - /* glibc2 #defines it as ut_tv.tv_sec */ - } -#endif - ut.ut_type = USER_PROCESS; - ut.ut_pid = cxt.pid; - if (cxt.hostname) { - xstrncpy(ut.ut_host, cxt.hostname, sizeof(ut.ut_host)); - if (cxt.hostaddress[0]) - memcpy(&ut.ut_addr_v6, cxt.hostaddress, - sizeof(ut.ut_addr_v6)); - } - - pututline(&ut); - endutent(); - -#if HAVE_UPDWTMP - updwtmp(_PATH_WTMP, &ut); -#else - /* Probably all this locking below is just nonsense, - and the short version is OK as well. */ - { - int lf, wtmp; - if ((lf = - open(_PATH_WTMPLOCK, O_CREAT | O_WRONLY, - 0660)) >= 0) { - flock(lf, LOCK_EX); - if ((wtmp = - open(_PATH_WTMP, - O_APPEND | O_WRONLY)) >= 0) { - write(wtmp, (char *)&ut, sizeof(ut)); - close(wtmp); - } - flock(lf, LOCK_UN); - close(lf); - } - } -#endif - } - + log_utmp(&cxt); log_audit(&cxt, pwd, 1); log_lastlog(&cxt); -- cgit v1.2.3-55-g7522