Subject: Re: last(1) vs. utmpx: print new fields (patch)
To: Simon Burge <simonb@NetBSD.org>
From: Hubert Feyrer <hubert@feyrer.de>
List: tech-userlevel
Date: 09/19/2006 13:35:04
On Tue, 19 Sep 2006, Simon Burge wrote:
> Personally, I think that's a little verbose for "-u" output, especially
> once host names are added. How about printing the extra info with say
> "-v" (currently unused)?
>
> Note also that SUSv3 says "-u" is for idle time, not idle time plus
> extra info.
If you look a bit closer, SUSv3 also mentions printing the PID for -u.
But you're right about the amount of data: Looking at Solaris, I have
changed the patch to make -d print the 'extra' process information
beyond PID when -u is also given:
miyu% ./obj.i386/who -H
USER LINE WHEN
feyrer ttyp6 Sep 19 13:13
feyrer ttyp8 Sep 19 13:13 (:0:S.1)
feyrer ttypa Sep 19 13:14
miyu% ./obj.i386/who -Hu
USER LINE WHEN IDLE PID COMMENT
feyrer ttyp6 Sep 19 13:13 00:20 887
feyrer ttyp8 Sep 19 13:13 old 326 (:0:S.1)
feyrer ttypa Sep 19 13:14 00:19 1968
miyu% ./obj.i386/who -Hud
USER LINE WHEN IDLE PID COMMENT
feyrer ttyp6 Sep 19 13:13 00:20 887 term=0 exit=2 sess=1 type=USER_PROCESS
feyrer ttyp8 Sep 19 13:13 old 326 term=0 exit=0 sess=0 type=USER_PROCESS (:0:S.1)
feyrer ttypa Sep 19 13:14 00:19 1968 term=0 exit=2 sess=1 type=USER_PROCESS
Patch appended below.
- Hubert
? TODO
Index: utmpentry.c
===================================================================
RCS file: /cvsroot/src/usr.bin/who/utmpentry.c,v
retrieving revision 1.7
diff -u -r1.7 utmpentry.c
--- utmpentry.c 17 Mar 2006 20:44:28 -0000 1.7
+++ utmpentry.c 19 Sep 2006 11:31:39 -0000
@@ -277,6 +277,11 @@
e->name[sizeof(e->name) - 1] = '\0';
e->tv.tv_sec = up->ut_time;
e->tv.tv_usec = 0;
+ e->pid = 0;
+ e->term = 0;
+ e->exit = 0;
+ e->sess = 0;
+ e->type = 0;
adjust_size(e);
}
#endif
@@ -292,6 +297,11 @@
(void)strncpy(e->host, up->ut_host, sizeof(up->ut_host));
e->name[sizeof(e->name) - 1] = '\0';
e->tv = up->ut_tv;
+ e->pid = up->ut_pid;
+ e->term = up->ut_exit.e_termination;
+ e->exit = up->ut_exit.e_exit;
+ e->sess = up->ut_session;
+ e->type = up->ut_type;
adjust_size(e);
}
#endif
Index: utmpentry.h
===================================================================
RCS file: /cvsroot/src/usr.bin/who/utmpentry.h,v
retrieving revision 1.2
diff -u -r1.2 utmpentry.h
--- utmpentry.h 28 Nov 2003 23:52:34 -0000 1.2
+++ utmpentry.h 19 Sep 2006 11:31:39 -0000
@@ -36,11 +36,29 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#if defined(SUPPORT_UTMPX)
+# define WHO_NAME_LEN _UTX_USERSIZE
+# define WHO_LINE_LEN _UTX_LINESIZE
+# define WHO_HOST_LEN _UTX_HOSTSIZE
+#elif defined(SUPPORT_UTMP)
+# define WHO_NAME_LEN UT_NAMESIZE
+# define WHO_LINE_LEN UT_LINESIZE
+# define WHO_HOST_LEN UT_HOSTSIZE
+#else
+# error Either SUPPORT_UTMPX or SUPPORT_UTMP must be defined!
+#endif
+
+
struct utmpentry {
- char name[65];
- char line[65];
- char host[257];
+ char name[ WHO_NAME_LEN + 1];
+ char line[ WHO_LINE_LEN + 1 ];
+ char host[ WHO_HOST_LEN + 1 ];
struct timeval tv;
+ pid_t pid;
+ uint16_t term;
+ uint16_t exit;
+ uint16_t sess;
+ uint16_t type;
struct utmpentry *next;
};
Index: who.1
===================================================================
RCS file: /cvsroot/src/usr.bin/who/who.1,v
retrieving revision 1.16
diff -u -r1.16 who.1
--- who.1 22 Jul 2005 14:23:05 -0000 1.16
+++ who.1 19 Sep 2006 11:31:39 -0000
@@ -29,7 +29,7 @@
.\"
.\" @(#)who.1 8.2 (Berkeley) 12/30/93
.\"
-.Dd July 22, 2005
+.Dd September 19, 2006
.Dt WHO 1
.Os
.Sh NAME
@@ -37,7 +37,7 @@
.Nd display who is logged in
.Sh SYNOPSIS
.Nm
-.Op Fl HmqsTu
+.Op Fl dHmqsTu
.Op Ar file
.Nm
.Ar am i
@@ -51,6 +51,15 @@
Available options:
.Pp
.Bl -tag -width file
+.It Fl d
+When printing of more information is requested with
+.Fl u ,
+this switch can be used to also printed
+process termination signals,
+process exit status,
+session id for windowing
+and the type of the entry, see documentation of ut_type in
+.Xr getutxent 3 .
.It Fl H
Write column headings above the regular output.
.It Fl m
@@ -78,38 +87,46 @@
.Sq \&?
if a bad line is encountered.
.It Fl u
-Print the idle time for each user.
+Print the idle time for each user, and the associated process ID.
.It Ar \&am I
Returns the invoker's real user name.
.It Ar file
By default,
.Nm
gathers information from the file
-.Pa /var/run/utmp .
+.Pa /var/run/utmpx .
An alternative
.Ar file
may be specified which is usually
-.Pa /var/log/wtmp
+.Pa /var/log/wtmpx
(or
+.Pa /var/log/wtmp
+or
.Pa /var/log/wtmp.[0-6]
depending on site policy as
-.Pa wtmp
+.Pa wtmpx
can grow quite large and daily versions may or may not
be kept around after compression by
.Xr ac 8 ) .
The
+.Pa wtmpx
+and
.Pa wtmp
file contains a record of every login, logout,
crash, shutdown and date change
since
+.Pa wtmpx
+and
.Pa wtmp
-was last truncated or
+were last truncated or
created.
.El
.Pp
If
+.Pa /var/log/wtmpx
+or
.Pa /var/log/wtmp
-is being used as the file, the user name may be empty
+are being used as the file, the user name may be empty
or one of the special characters '|', '}' and '~'.
Logouts produce an output line without any user name.
For more information on the
@@ -118,8 +135,10 @@
.Sh FILES
.Bl -tag -width /var/log/wtmp.[0-6] -compact
.It Pa /var/run/utmp
+.It Pa /var/run/utmpx
.It Pa /var/log/wtmp
.It Pa /var/log/wtmp.[0-6]
+.It Pa /var/log/wtmpx
.El
.Sh SEE ALSO
.Xr last 1 ,
Index: who.c
===================================================================
RCS file: /cvsroot/src/usr.bin/who/who.c,v
retrieving revision 1.16
diff -u -r1.16 who.c
--- who.c 22 Jul 2005 14:23:05 -0000 1.16
+++ who.c 19 Sep 2006 11:31:39 -0000
@@ -57,6 +57,12 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+#ifdef SUPPORT_UTMP
+#include <utmp.h>
+#endif
+#ifdef SUPPORT_UTMPX
+#include <utmpx.h>
+#endif
#include "utmpentry.h"
@@ -64,14 +70,37 @@
static void who_am_i(const char *, int);
static void usage(void);
static void process(const char *, int);
-static void print(const char *, const char *, time_t, const char *);
+static void print(const char *, const char *, time_t, const char *, pid_t pid, uint16_t term, uint16_t xit, uint16_t sess, uint16_t type);
static void quick(const char *);
static int show_term; /* show term state */
static int show_idle; /* show idle time */
+static int show_details; /* show exit status etc. */
extern int maxname, maxline, maxhost;
+struct ut_type_names {
+ int type;
+ char name[30];
+} ut_type_names[] = {
+#ifdef SUPPORT_UTMPX
+ { EMPTY, "EMPTY" },
+ { RUN_LVL, "RUN_LVL" },
+ { BOOT_TIME, "BOOT_TIME" },
+ { OLD_TIME, "OLD_TIME" },
+ { NEW_TIME, "NEW_TIME" },
+ { INIT_PROCESS, "INIT_PROCESS" },
+ { LOGIN_PROCESS, "LOGIN_PROCESS" },
+ { USER_PROCESS, "USER_PROCESS" },
+ { DEAD_PROCESS, "DEAD_PROCESS" },
+#if defined(_NETBSD_SOURCE)
+ { ACCOUNTING, "ACCOUNTING" },
+ { SIGNATURE, "SIGNATURE" },
+#endif /* _NETBSD_SOURCE */
+#endif /* SUPPORT_UTMPX */
+ { -1, "unknown" }
+};
+
int
main(int argc, char *argv[])
{
@@ -82,8 +111,11 @@
only_current_term = show_term = show_idle = show_labels = 0;
quick_mode = default_mode = 0;
- while ((c = getopt(argc, argv, "HmqsTu")) != -1) {
+ while ((c = getopt(argc, argv, "dHmqsTu")) != -1) {
switch (c) {
+ case 'd':
+ show_details = 1;
+ break;
case 'H':
show_labels = 1;
break;
@@ -169,8 +201,14 @@
if (strcmp(ep->line, p) == 0) {
if (show_labels)
output_labels();
- print(ep->name, ep->line, (time_t)ep->tv.tv_sec,
- ep->host);
+ print(ep->name, ep->line,
+ (time_t)ep->tv.tv_sec,
+ ep->host,
+ ep->pid,
+ ep->term,
+ ep->exit,
+ ep->sess,
+ ep->type );
return;
}
} else
@@ -180,7 +218,7 @@
pw = getpwuid(getuid());
if (show_labels)
output_labels();
- print(pw ? pw->pw_name : "?", p, now, "");
+ print(pw ? pw->pw_name : "?", p, now, "", getpid(), 0, 0, 0, 0);
}
static void
@@ -191,20 +229,30 @@
if (show_labels)
output_labels();
for (ep = ehead; ep != NULL; ep = ep->next)
- print(ep->name, ep->line, (time_t)ep->tv.tv_sec, ep->host);
+ print(ep->name, ep->line, (time_t)ep->tv.tv_sec,
+ ep->host, ep->pid, ep->term, ep->exit,
+ ep->sess, ep->type);
}
static void
-print(const char *name, const char *line, time_t t, const char *host)
+print(const char *name, const char *line, time_t t, const char *host, pid_t pid, uint16_t term, uint16_t xit, uint16_t sess, uint16_t type)
{
struct stat sb;
char state;
static time_t now = 0;
time_t idle;
+ char *types = NULL;
+ int i;
state = '?';
idle = 0;
+ for (i=0; ut_type_names[i].type >= 0; i++) {
+ types = ut_type_names[i].name;
+ if ( ut_type_names[i].type == type )
+ break;
+ }
+
if (show_term || show_idle) {
if (now == 0)
time(&now);
@@ -233,6 +281,14 @@
(long)(idle % (60 * 60)) / 60);
else
(void)printf(" old ");
+
+ (void)printf("\t%6d", pid);
+
+ if (show_details) {
+ (void)printf("\tterm=%d exit=%d", term, xit);
+ (void)printf(" sess=%d", sess);
+ (void)printf(" type=%s ", types);
+ }
}
if (*host)
@@ -251,10 +307,12 @@
(void)printf("%-*.*s ", maxline, maxline, "LINE");
(void)printf("WHEN ");
- if (show_idle)
+ if (show_idle) {
(void)printf("IDLE ");
+ (void)printf("\t PID");
- (void)printf("\t%.*s", maxhost, "FROM");
+ (void)printf("\tCOMMENT");
+ }
(void)putchar('\n');
}
@@ -280,7 +338,7 @@
static void
usage(void)
{
- (void)fprintf(stderr, "usage: %s [-HmqsTu] [file]\n %s am i\n",
+ (void)fprintf(stderr, "usage: %s [-dHmqsTu] [file]\n %s am i\n",
getprogname(), getprogname());
exit(EXIT_FAILURE);
}