From b2f0faf04264c13d7877646330da7f5954380342 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 5 Apr 2010 19:27:41 +0200 Subject: libutil/login: was totally broken. fixed Also made login() and logout() usable with utmpname(non_std_utmp_file) text data bss dec hex filename 111 0 0 111 6f libutil/login.o 217 0 0 217 d9 libutil/login.o text data bss dec hex filename 164 0 0 164 a4 libutil/logout.o 134 0 0 134 86 libutil/logout.o Signed-off-by: Denys Vlasenko --- libutil/login.c | 57 +++++++++++++++++++++++++++++++++++++++++++++----------- libutil/logout.c | 20 ++++++++++---------- 2 files changed, 56 insertions(+), 21 deletions(-) (limited to 'libutil') diff --git a/libutil/login.c b/libutil/login.c index bd1dd29ee..4007e4c7e 100644 --- a/libutil/login.c +++ b/libutil/login.c @@ -5,21 +5,56 @@ #include #include -/* Write the given entry into utmp and wtmp. */ -void login (const struct utmp *entry) +/* Write the given entry into utmp and wtmp. + * Note: the match in utmp is done against ut_id field, + * which is NOT set by this function - caller must set it. + */ +void login(const struct utmp *entry) { - struct utmp copy = *entry; + struct utmp copy; + char tty_name[sizeof(copy.ut_line) + 6]; + int fd; - utmpname(_PATH_UTMP); - setutent(); +// Manpage: +// login() takes the argument ut struct, fills the field ut->ut_type +// (if there is such a field) with the value USER_PROCESS, +// and fills the field ut->ut_pid (if there is such a field) +// with the process ID of the calling process. + copy = *entry; #if _HAVE_UT_TYPE - 0 - copy.ut_type = USER_PROCESS; + copy.ut_type = USER_PROCESS; #endif #if _HAVE_UT_PID - 0 - copy.ut_pid = getpid(); + copy.ut_pid = getpid(); #endif - strncpy (copy.ut_line, entry->ut_line, UT_LINESIZE); - pututline(entry); - endutent(); -} +// Then it tries to fill the field ut->ut_line. It takes the first of stdin, +// stdout, stderr that is a tty, and stores the corresponding pathname minus +// a possible leading /dev/ into this field, and then writes the struct +// to the utmp file. On the other hand, if no tty name was found, +// this field is filled with "???" and the struct is not written +// to the utmp file. + fd = 0; + while (fd != 3 && ttyname_r(fd, tty_name, sizeof(tty_name)) != 0) + fd++; + if (fd != 3) { + if (strncmp(tty_name, "/dev/", 5) == 0) + strncpy(copy.ut_line, tty_name + 5, sizeof(copy.ut_line)-1); + else + strncpy(copy.ut_line, tty_name, sizeof(copy.ut_line)-1); + copy.ut_line[sizeof(copy.ut_line)-1] = '\0'; + + /* utmpname(_PATH_UTMP); - why? + * this makes it impossible for caller to use other file! + * Does any standard or historical precedent says this must be done? */ + setutent(); + /* Replaces record with matching ut_id, or appends new one: */ + pututline(©); + endutent(); + } else { + strncpy(copy.ut_line, "???", sizeof(copy.ut_line)); + } + +// After this, the struct is written to the wtmp file. + updwtmp(_PATH_WTMP, ©); +} diff --git a/libutil/logout.c b/libutil/logout.c index e6d9565ab..5f58b8f42 100644 --- a/libutil/logout.c +++ b/libutil/logout.c @@ -29,9 +29,9 @@ logout (const char *line) struct utmp *ut; int result = 0; - /* Tell that we want to use the UTMP file. */ - if (utmpname (_PATH_UTMP) == -1) - return 0; + /* if (utmpname (_PATH_UTMP) == -1) return 0; - why? + * this makes it impossible for caller to use other file! + * Does any standard or historical precedent says this must be done? */ /* Open UTMP file. */ setutent (); @@ -43,7 +43,7 @@ logout (const char *line) strncpy (tmp.ut_line, line, sizeof tmp.ut_line); /* Read the record. */ - if( (ut = getutline(&tmp)) ) + if ((ut = getutline(&tmp)) != NULL) { /* Clear information about who & from where. */ memset (ut->ut_name, 0, sizeof ut->ut_name); @@ -54,12 +54,12 @@ logout (const char *line) # if !defined __WORDSIZE_COMPAT32 || __WORDSIZE_COMPAT32 == 0 gettimeofday (&ut->ut_tv, NULL); # else - { - struct timeval tv; - gettimeofday (&tv, NULL); - ut->ut_tv.tv_sec = tv.tv_sec; - ut->ut_tv.tv_usec = tv.tv_usec; - } + { + struct timeval tv; + gettimeofday (&tv, NULL); + ut->ut_tv.tv_sec = tv.tv_sec; + ut->ut_tv.tv_usec = tv.tv_usec; + } # endif #else time (&ut->ut_time); -- cgit v1.2.3