summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-04-05 19:27:41 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-04-05 19:27:41 +0200
commitb2f0faf04264c13d7877646330da7f5954380342 (patch)
tree5250f364c843fdb62bcfbd285df36c176b7c49b2
parent56f80b6cb62323fbaf0fc8620d10fc242e136ee6 (diff)
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 <vda.linux@googlemail.com>
-rw-r--r--libutil/login.c57
-rw-r--r--libutil/logout.c20
2 files changed, 56 insertions, 21 deletions
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 <stdlib.h>
#include <utmp.h>
-/* 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(&copy);
+ endutent();
+ } else {
+ strncpy(copy.ut_line, "???", sizeof(copy.ut_line));
+ }
+
+// After this, the struct is written to the wtmp file.
+ updwtmp(_PATH_WTMP, &copy);
+}
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);