aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libbb.h6
-rw-r--r--init/halt.c15
-rw-r--r--libbb/utmp.c123
-rw-r--r--loginutils/getty.c8
-rw-r--r--loginutils/login.c2
-rw-r--r--miscutils/last.c3
-rw-r--r--networking/telnetd.c33
7 files changed, 134 insertions, 56 deletions
diff --git a/include/libbb.h b/include/libbb.h
index ea61701b7..f3121eb47 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -797,9 +797,11 @@ void die_if_bad_username(const char* name) FAST_FUNC;
797#endif 797#endif
798 798
799#if ENABLE_FEATURE_UTMP 799#if ENABLE_FEATURE_UTMP
800void FAST_FUNC update_utmp(int new_type, const char *short_tty, const char *username, const char *opt_host); 800void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname);
801void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname);
801#else 802#else
802# define update_utmp(new_type, short_tty, username, opt_host) ((void)0) 803# define write_new_utmp(pid, new_type, tty_name, username, hostname) ((void)0)
804# define update_utmp(pid, new_type, tty_name, username, hostname) ((void)0)
803#endif 805#endif
804 806
805int execable_file(const char *name) FAST_FUNC; 807int execable_file(const char *name) FAST_FUNC;
diff --git a/init/halt.c b/init/halt.c
index a3459ee48..f1bb2c4a8 100644
--- a/init/halt.c
+++ b/init/halt.c
@@ -18,17 +18,18 @@ static void write_wtmp(void)
18{ 18{
19 struct utmp utmp; 19 struct utmp utmp;
20 struct utsname uts; 20 struct utsname uts;
21 if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) { 21 /* "man utmp" says wtmp file should *not* be created automagically */
22 /*if (access(bb_path_wtmp_file, R_OK|W_OK) == -1) {
22 close(creat(bb_path_wtmp_file, 0664)); 23 close(creat(bb_path_wtmp_file, 0664));
23 } 24 }*/
24 memset(&utmp, 0, sizeof(utmp)); 25 memset(&utmp, 0, sizeof(utmp));
25 utmp.ut_tv.tv_sec = time(NULL); 26 utmp.ut_tv.tv_sec = time(NULL);
26 safe_strncpy(utmp.ut_user, "shutdown", UT_NAMESIZE); 27 strcpy(utmp.ut_user, "shutdown"); /* it is wide enough */
27 utmp.ut_type = RUN_LVL; 28 utmp.ut_type = RUN_LVL;
28 safe_strncpy(utmp.ut_id, "~~", sizeof(utmp.ut_id)); 29 utmp.ut_id[0] = '~'; utmp.ut_id[1] = '~'; /* = strcpy(utmp.ut_id, "~~"); */
29 safe_strncpy(utmp.ut_line, "~~", UT_LINESIZE); 30 utmp.ut_line[0] = '~'; utmp.ut_line[1] = '~'; /* = strcpy(utmp.ut_line, "~~"); */
30 if (uname(&uts) == 0) 31 uname(&uts);
31 safe_strncpy(utmp.ut_host, uts.release, sizeof(utmp.ut_host)); 32 safe_strncpy(utmp.ut_host, uts.release, sizeof(utmp.ut_host));
32 updwtmp(bb_path_wtmp_file, &utmp); 33 updwtmp(bb_path_wtmp_file, &utmp);
33} 34}
34#else 35#else
diff --git a/libbb/utmp.c b/libbb/utmp.c
index 06b939b9d..d6ba336e3 100644
--- a/libbb/utmp.c
+++ b/libbb/utmp.c
@@ -15,37 +15,87 @@ static void touch(const char *filename)
15 close(open(filename, O_WRONLY | O_CREAT, 0664)); 15 close(open(filename, O_WRONLY | O_CREAT, 0664));
16} 16}
17 17
18// TODO: move to libbb
19static const char* skip_dev_pfx(const char *tty_name)
20{
21 if (strncmp(tty_name, "/dev/", 5) == 0)
22 tty_name += 5;
23 return tty_name;
24}
25
26void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname)
27{
28 struct utmp utent;
29 char *id;
30 unsigned width;
31
32 memset(&utent, 0, sizeof(utent));
33 utent.ut_pid = pid;
34 utent.ut_type = new_type;
35 tty_name = skip_dev_pfx(tty_name);
36 safe_strncpy(utent.ut_line, tty_name, sizeof(utent.ut_line));
37 if (username)
38 safe_strncpy(utent.ut_user, username, sizeof(utent.ut_user));
39 if (hostname)
40 safe_strncpy(utent.ut_host, hostname, sizeof(utent.ut_host));
41 utent.ut_tv.tv_sec = time(NULL);
42
43 /* Invent our own ut_id. ut_id is only 4 chars wide.
44 * Try to fit something remotely meaningful... */
45 id = utent.ut_id;
46 width = sizeof(utent.ut_id);
47 if (tty_name[0] == 'p') {
48 /* if "ptyXXX", map to "pXXX" */
49 /* if "pts/XX", map to "p/XX" */
50 *id++ = 'p';
51 width--;
52 } /* else: usually it's "ttyXXXX", map to "XXXX" */
53 if (strlen(tty_name) > 3)
54 tty_name += 3;
55 strncpy(id, tty_name, width);
56
57 touch(_PATH_UTMP);
58 //utmpname(_PATH_UTMP);
59 setutent();
60 /* Append new one (hopefully, unless we collide on ut_id) */
61 pututline(&utent);
62 endutent();
63
64#if ENABLE_FEATURE_WTMP
65 /* "man utmp" says wtmp file should *not* be created automagically */
66 /*touch(bb_path_wtmp_file);*/
67 updwtmp(bb_path_wtmp_file, &utent);
68#endif
69}
70
18/* 71/*
19 * Read "man utmp" to make sense out of it. 72 * Read "man utmp" to make sense out of it.
20 */ 73 */
21void FAST_FUNC update_utmp(int new_type, const char *short_tty, const char *username, const char *opt_host) 74void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname)
22{ 75{
23 struct utmp utent; 76 struct utmp utent;
24 struct utmp *ut; 77 struct utmp *utp;
25 pid_t pid;
26 78
27 touch(_PATH_UTMP); 79 touch(_PATH_UTMP);
28 utmpname(_PATH_UTMP); 80 //utmpname(_PATH_UTMP);
29 setutent(); 81 setutent();
30 82
31 pid = getpid();
32 /* Did init/getty/telnetd/sshd/... create an entry for us? 83 /* Did init/getty/telnetd/sshd/... create an entry for us?
33 * It should be (new_type-1), but we'd also reuse 84 * It should be (new_type-1), but we'd also reuse
34 * any other potentially stale xxx_PROCESS entry */ 85 * any other potentially stale xxx_PROCESS entry */
35 while ((ut = getutent()) != NULL) { 86 while ((utp = getutent()) != NULL) {
36 if (ut->ut_pid == pid 87 if (utp->ut_pid == pid
37 // && ut->ut_line[0] 88 // && ut->ut_line[0]
38 && ut->ut_id[0] /* must have nonzero id */ 89 && utp->ut_id[0] /* must have nonzero id */
39 && ( ut->ut_type == INIT_PROCESS 90 && ( utp->ut_type == INIT_PROCESS
40 || ut->ut_type == LOGIN_PROCESS 91 || utp->ut_type == LOGIN_PROCESS
41 || ut->ut_type == USER_PROCESS 92 || utp->ut_type == USER_PROCESS
42 || ut->ut_type == DEAD_PROCESS 93 || utp->ut_type == DEAD_PROCESS
43 ) 94 )
44 ) { 95 ) {
45 utent = *ut; /* struct copy */ 96 if (utp->ut_type >= new_type) {
46 if (ut->ut_type >= new_type) {
47 /* Stale record. Nuke hostname */ 97 /* Stale record. Nuke hostname */
48 memset(utent.ut_host, 0, sizeof(utent.ut_host)); 98 memset(utp->ut_host, 0, sizeof(utp->ut_host));
49 } 99 }
50 /* NB: pututline (see later) searches for matching utent 100 /* NB: pututline (see later) searches for matching utent
51 * using getutid(utent) - we must not change ut_id 101 * using getutid(utent) - we must not change ut_id
@@ -54,39 +104,38 @@ void FAST_FUNC update_utmp(int new_type, const char *short_tty, const char *user
54 break; 104 break;
55 } 105 }
56 } 106 }
57 endutent(); 107 //endutent(); - no need, pututline can deal with (and actually likes)
108 //the situation when utmp file is positioned on found record
58 109
59 if (!ut) { 110 if (!utp) {
60 /* Didn't find anything, create new one */ 111 if (new_type != DEAD_PROCESS)
61 memset(&utent, 0, sizeof(utent)); 112 write_new_utmp(pid, new_type, tty_name, username, hostname);
62 utent.ut_pid = pid; 113 else
63 /* Invent our own ut_id. ut_id is only 4 chars wide. 114 endutent();
64 * Try to fit something remotely meaningful... */ 115 return;
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 } 116 }
75 117
118 /* Make a copy. We can't use *utp, pututline's internal getutid
119 * will overwrite it before it is used! */
120 utent = *utp;
121
76 utent.ut_type = new_type; 122 utent.ut_type = new_type;
77 safe_strncpy(utent.ut_line, short_tty, sizeof(utent.ut_line)); 123 if (tty_name)
78 safe_strncpy(utent.ut_user, username, sizeof(utent.ut_user)); 124 safe_strncpy(utent.ut_line, skip_dev_pfx(tty_name), sizeof(utent.ut_line));
79 if (opt_host) 125 if (username)
80 safe_strncpy(utent.ut_host, opt_host, sizeof(utent.ut_host)); 126 safe_strncpy(utent.ut_user, username, sizeof(utent.ut_user));
127 if (hostname)
128 safe_strncpy(utent.ut_host, hostname, sizeof(utent.ut_host));
81 utent.ut_tv.tv_sec = time(NULL); 129 utent.ut_tv.tv_sec = time(NULL);
82 130
83 /* Update, or append new one */ 131 /* Update, or append new one */
84 setutent(); 132 //setutent();
85 pututline(&utent); 133 pututline(&utent);
86 endutent(); 134 endutent();
87 135
88#if ENABLE_FEATURE_WTMP 136#if ENABLE_FEATURE_WTMP
89 touch(bb_path_wtmp_file); 137 /* "man utmp" says wtmp file should *not* be created automagically */
138 /*touch(bb_path_wtmp_file);*/
90 updwtmp(bb_path_wtmp_file, &utent); 139 updwtmp(bb_path_wtmp_file, &utent);
91#endif 140#endif
92} 141}
diff --git a/loginutils/getty.c b/loginutils/getty.c
index 8d1d5254e..d032357e2 100644
--- a/loginutils/getty.c
+++ b/loginutils/getty.c
@@ -19,7 +19,7 @@
19#include <syslog.h> 19#include <syslog.h>
20 20
21#if ENABLE_FEATURE_UTMP 21#if ENABLE_FEATURE_UTMP
22#include <utmp.h> /* LOGIN_PROCESS */ 22# include <utmp.h> /* LOGIN_PROCESS */
23#endif 23#endif
24 24
25#ifndef IUCLC 25#ifndef IUCLC
@@ -579,6 +579,7 @@ int getty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
579int getty_main(int argc UNUSED_PARAM, char **argv) 579int getty_main(int argc UNUSED_PARAM, char **argv)
580{ 580{
581 int n; 581 int n;
582 pid_t pid;
582 char *fakehost = NULL; /* Fake hostname for ut_host */ 583 char *fakehost = NULL; /* Fake hostname for ut_host */
583 char *logname; /* login name, given to /bin/login */ 584 char *logname; /* login name, given to /bin/login */
584 /* Merging these into "struct local" may _seem_ to reduce 585 /* Merging these into "struct local" may _seem_ to reduce
@@ -651,17 +652,18 @@ int getty_main(int argc UNUSED_PARAM, char **argv)
651 /* tcgetattr() + error check */ 652 /* tcgetattr() + error check */
652 ioctl_or_perror_and_die(0, TCGETS, &termios, "%s: TCGETS", options.tty); 653 ioctl_or_perror_and_die(0, TCGETS, &termios, "%s: TCGETS", options.tty);
653 654
655 pid = getpid();
654#ifdef __linux__ 656#ifdef __linux__
655// FIXME: do we need this? Otherwise "-" case seems to be broken... 657// FIXME: do we need this? Otherwise "-" case seems to be broken...
656 // /* Forcibly make fd 0 our controlling tty, even if another session 658 // /* Forcibly make fd 0 our controlling tty, even if another session
657 // * has it as a ctty. (Another session loses ctty). */ 659 // * has it as a ctty. (Another session loses ctty). */
658 // ioctl(0, TIOCSCTTY, (void*)1); 660 // ioctl(0, TIOCSCTTY, (void*)1);
659 /* Make ourself a foreground process group within our session */ 661 /* Make ourself a foreground process group within our session */
660 tcsetpgrp(0, getpid()); 662 tcsetpgrp(0, pid);
661#endif 663#endif
662 664
663 /* Update the utmp file. This tty is ours now! */ 665 /* Update the utmp file. This tty is ours now! */
664 update_utmp(LOGIN_PROCESS, options.tty, "LOGIN", fakehost); 666 update_utmp(pid, LOGIN_PROCESS, options.tty, "LOGIN", fakehost);
665 667
666 /* Initialize the termios settings (raw mode, eight-bit, blocking i/o). */ 668 /* Initialize the termios settings (raw mode, eight-bit, blocking i/o). */
667 debug("calling termios_init\n"); 669 debug("calling termios_init\n");
diff --git a/loginutils/login.c b/loginutils/login.c
index 4a820379d..bf21d6121 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -384,7 +384,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
384 fchown(0, pw->pw_uid, pw->pw_gid); 384 fchown(0, pw->pw_uid, pw->pw_gid);
385 fchmod(0, 0600); 385 fchmod(0, 0600);
386 386
387 update_utmp(USER_PROCESS, short_tty, username, run_by_root ? opt_host : NULL); 387 update_utmp(getpid(), USER_PROCESS, short_tty, username, run_by_root ? opt_host : NULL);
388 388
389 /* We trust environment only if we run by root */ 389 /* We trust environment only if we run by root */
390 if (ENABLE_LOGIN_SCRIPTS && run_by_root) 390 if (ENABLE_LOGIN_SCRIPTS && run_by_root)
diff --git a/miscutils/last.c b/miscutils/last.c
index 6e3ed9093..55c03ae41 100644
--- a/miscutils/last.c
+++ b/miscutils/last.c
@@ -92,7 +92,8 @@ int last_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
92 goto next; 92 goto next;
93 } 93 }
94 if (ut.ut_type != DEAD_PROCESS 94 if (ut.ut_type != DEAD_PROCESS
95 && ut.ut_user[0] && ut.ut_line[0] 95 && ut.ut_user[0]
96 && ut.ut_line[0]
96 ) { 97 ) {
97 ut.ut_type = USER_PROCESS; 98 ut.ut_type = USER_PROCESS;
98 } 99 }
diff --git a/networking/telnetd.c b/networking/telnetd.c
index cab94f0f7..b3e66eb4b 100644
--- a/networking/telnetd.c
+++ b/networking/telnetd.c
@@ -20,18 +20,22 @@
20 * Vladimir Oleynik <dzo@simtreas.ru> 2001 20 * Vladimir Oleynik <dzo@simtreas.ru> 2001
21 * Set process group corrections, initial busybox port 21 * Set process group corrections, initial busybox port
22 */ 22 */
23
24#define DEBUG 0 23#define DEBUG 0
25 24
26#include "libbb.h" 25#include "libbb.h"
27#include <syslog.h> 26#include <syslog.h>
28 27
29#if DEBUG 28#if DEBUG
30#define TELCMDS 29# define TELCMDS
31#define TELOPTS 30# define TELOPTS
32#endif 31#endif
33#include <arpa/telnet.h> 32#include <arpa/telnet.h>
34 33
34#if ENABLE_FEATURE_UTMP
35# include <utmp.h> /* LOGIN_PROCESS */
36#endif
37
38
35struct tsession { 39struct tsession {
36 struct tsession *next; 40 struct tsession *next;
37 pid_t shell_pid; 41 pid_t shell_pid;
@@ -319,7 +323,11 @@ make_new_session(
319 xopen(tty_name, O_RDWR); /* becomes our ctty */ 323 xopen(tty_name, O_RDWR); /* becomes our ctty */
320 xdup2(0, 1); 324 xdup2(0, 1);
321 xdup2(0, 2); 325 xdup2(0, 2);
322 tcsetpgrp(0, getpid()); /* switch this tty's process group to us */ 326 pid = getpid();
327 tcsetpgrp(0, pid); /* switch this tty's process group to us */
328
329//TODO: fetch remote addr via getpeername (see ftpd.c)
330 write_new_utmp(pid, LOGIN_PROCESS, tty_name, /*username:*/ "LOGIN", /*hostname:*/ NULL);
323 331
324 /* The pseudo-terminal allocated to the client is configured to operate 332 /* The pseudo-terminal allocated to the client is configured to operate
325 * in cooked mode, and with XTABS CRMOD enabled (see tty(4)) */ 333 * in cooked mode, and with XTABS CRMOD enabled (see tty(4)) */
@@ -358,12 +366,13 @@ make_new_session(
358static void 366static void
359free_session(struct tsession *ts) 367free_session(struct tsession *ts)
360{ 368{
361 struct tsession *t = G.sessions; 369 struct tsession *t;
362 370
363 if (option_mask32 & OPT_INETD) 371 if (option_mask32 & OPT_INETD)
364 exit(EXIT_SUCCESS); 372 exit(EXIT_SUCCESS);
365 373
366 /* Unlink this telnet session from the session list */ 374 /* Unlink this telnet session from the session list */
375 t = G.sessions;
367 if (t == ts) 376 if (t == ts)
368 G.sessions = ts->next; 377 G.sessions = ts->next;
369 else { 378 else {
@@ -414,6 +423,7 @@ static void handle_sigchld(int sig UNUSED_PARAM)
414{ 423{
415 pid_t pid; 424 pid_t pid;
416 struct tsession *ts; 425 struct tsession *ts;
426 int save_errno = errno;
417 427
418 /* Looping: more than one child may have exited */ 428 /* Looping: more than one child may have exited */
419 while (1) { 429 while (1) {
@@ -424,11 +434,22 @@ static void handle_sigchld(int sig UNUSED_PARAM)
424 while (ts) { 434 while (ts) {
425 if (ts->shell_pid == pid) { 435 if (ts->shell_pid == pid) {
426 ts->shell_pid = -1; 436 ts->shell_pid = -1;
437// man utmp:
438// When init(8) finds that a process has exited, it locates its utmp entry
439// by ut_pid, sets ut_type to DEAD_PROCESS, and clears ut_user, ut_host
440// and ut_time with null bytes.
441// [same applies to other processes which maintain utmp entries, like telnetd]
442//
443// We do not bother actually clearing fields:
444// it might be interesting to know who was logged in and from where
445 update_utmp(pid, DEAD_PROCESS, /*tty_name:*/ NULL, /*username:*/ NULL, /*hostname:*/ NULL);
427 break; 446 break;
428 } 447 }
429 ts = ts->next; 448 ts = ts->next;
430 } 449 }
431 } 450 }
451
452 errno = save_errno;
432} 453}
433 454
434int telnetd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 455int telnetd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
@@ -689,6 +710,8 @@ int telnetd_main(int argc UNUSED_PARAM, char **argv)
689 ts = next; 710 ts = next;
690 continue; 711 continue;
691 kill_session: 712 kill_session:
713 if (ts->shell_pid > 0)
714 update_utmp(ts->shell_pid, DEAD_PROCESS, /*tty_name:*/ NULL, /*username:*/ NULL, /*hostname:*/ NULL);
692 free_session(ts); 715 free_session(ts);
693 ts = next; 716 ts = next;
694 } 717 }