diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/Kbuild | 2 | ||||
-rw-r--r-- | libbb/utmp.c | 92 |
2 files changed, 94 insertions, 0 deletions
diff --git a/libbb/Kbuild b/libbb/Kbuild index 4606d5aa7..1b11d5d39 100644 --- a/libbb/Kbuild +++ b/libbb/Kbuild | |||
@@ -120,6 +120,8 @@ lib-y += xgethostbyname.o | |||
120 | lib-y += xreadlink.o | 120 | lib-y += xreadlink.o |
121 | lib-y += xrealloc_vector.o | 121 | lib-y += xrealloc_vector.o |
122 | 122 | ||
123 | lib-$(CONFIG_FEATURE_UTMP) += utmp.o | ||
124 | |||
123 | # A mix of optimizations (why build stuff we know won't be used) | 125 | # A mix of optimizations (why build stuff we know won't be used) |
124 | # and objects which may fail to build (SELinux on selinux-less system) | 126 | # and objects which may fail to build (SELinux on selinux-less system) |
125 | lib-$(CONFIG_SELINUX) += selinux_common.o | 127 | lib-$(CONFIG_SELINUX) += selinux_common.o |
diff --git a/libbb/utmp.c b/libbb/utmp.c new file mode 100644 index 000000000..06b939b9d --- /dev/null +++ b/libbb/utmp.c | |||
@@ -0,0 +1,92 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * utmp/wtmp support routines. | ||
4 | * | ||
5 | * Copyright (C) 2010 Denys Vlasenko | ||
6 | * | ||
7 | * Licensed under GPL version 2, see file LICENSE in this tarball for details. | ||
8 | */ | ||
9 | #include "libbb.h" | ||
10 | #include <utmp.h> | ||
11 | |||
12 | static void touch(const char *filename) | ||
13 | { | ||
14 | if (access(filename, R_OK | W_OK) == -1) | ||
15 | close(open(filename, O_WRONLY | O_CREAT, 0664)); | ||
16 | } | ||
17 | |||
18 | /* | ||
19 | * Read "man utmp" to make sense out of it. | ||
20 | */ | ||
21 | void FAST_FUNC update_utmp(int new_type, const char *short_tty, const char *username, const char *opt_host) | ||
22 | { | ||
23 | struct utmp utent; | ||
24 | struct utmp *ut; | ||
25 | pid_t pid; | ||
26 | |||
27 | touch(_PATH_UTMP); | ||
28 | utmpname(_PATH_UTMP); | ||
29 | setutent(); | ||
30 | |||
31 | pid = getpid(); | ||
32 | /* Did init/getty/telnetd/sshd/... create an entry for us? | ||
33 | * It should be (new_type-1), but we'd also reuse | ||
34 | * any other potentially stale xxx_PROCESS entry */ | ||
35 | while ((ut = getutent()) != NULL) { | ||
36 | if (ut->ut_pid == pid | ||
37 | // && ut->ut_line[0] | ||
38 | && ut->ut_id[0] /* must have nonzero id */ | ||
39 | && ( ut->ut_type == INIT_PROCESS | ||
40 | || ut->ut_type == LOGIN_PROCESS | ||
41 | || ut->ut_type == USER_PROCESS | ||
42 | || ut->ut_type == DEAD_PROCESS | ||
43 | ) | ||
44 | ) { | ||
45 | utent = *ut; /* struct copy */ | ||
46 | if (ut->ut_type >= new_type) { | ||
47 | /* Stale record. Nuke hostname */ | ||
48 | memset(utent.ut_host, 0, sizeof(utent.ut_host)); | ||
49 | } | ||
50 | /* NB: pututline (see later) searches for matching utent | ||
51 | * using getutid(utent) - we must not change ut_id | ||
52 | * if we want *exactly this* record to be overwritten! | ||
53 | */ | ||
54 | break; | ||
55 | } | ||
56 | } | ||
57 | endutent(); | ||
58 | |||
59 | if (!ut) { | ||
60 | /* Didn't find anything, create new one */ | ||
61 | memset(&utent, 0, sizeof(utent)); | ||
62 | utent.ut_pid = pid; | ||
63 | /* Invent our own ut_id. ut_id is only 4 chars wide. | ||
64 | * Try to fit something remotely meaningful... */ | ||
65 | if (short_tty[0] == 'p') { | ||
66 | /* if "ptyXXX", map to "pXXX" */ | ||
67 | /* if "pts/XX", map to "p/XX" */ | ||
68 | utent.ut_id[0] = 'p'; | ||
69 | strncpy(utent.ut_id + 1, short_tty + 3, sizeof(utent.ut_id)-1); | ||
70 | } else { | ||
71 | /* assuming it's "ttyXXXX", map to "XXXX" */ | ||
72 | strncpy(utent.ut_id, short_tty + 3, sizeof(utent.ut_id)); | ||
73 | } | ||
74 | } | ||
75 | |||
76 | utent.ut_type = new_type; | ||
77 | safe_strncpy(utent.ut_line, short_tty, sizeof(utent.ut_line)); | ||
78 | safe_strncpy(utent.ut_user, username, sizeof(utent.ut_user)); | ||
79 | if (opt_host) | ||
80 | safe_strncpy(utent.ut_host, opt_host, sizeof(utent.ut_host)); | ||
81 | utent.ut_tv.tv_sec = time(NULL); | ||
82 | |||
83 | /* Update, or append new one */ | ||
84 | setutent(); | ||
85 | pututline(&utent); | ||
86 | endutent(); | ||
87 | |||
88 | #if ENABLE_FEATURE_WTMP | ||
89 | touch(bb_path_wtmp_file); | ||
90 | updwtmp(bb_path_wtmp_file, &utent); | ||
91 | #endif | ||
92 | } | ||