aboutsummaryrefslogtreecommitdiff
path: root/utils/w.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/w.c')
-rw-r--r--utils/w.c195
1 files changed, 137 insertions, 58 deletions
diff --git a/utils/w.c b/utils/w.c
index 0b31385e..37555088 100644
--- a/utils/w.c
+++ b/utils/w.c
@@ -1,8 +1,8 @@
/* Hurdish w
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1995,96,97,98,99,2001,02 Free Software Foundation, Inc.
- Written by Miles Bader <miles@gnu.ai.mit.edu>
+ Written by Miles Bader <miles@gnu.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
#include <paths.h>
#include <ctype.h>
@@ -29,6 +30,7 @@
#include <pwd.h>
#include <grp.h>
#include <netdb.h>
+#include <version.h>
#include <sys/fcntl.h>
@@ -42,13 +44,13 @@
#include "psout.h"
-#define DEFAULT_FMT_STRING "%^%user %tty %from %login %idle %what"
+#define DEFAULT_FMT_STRING "%^%user %tty %from %login %idle %pid %what"
extern char *canon_host (char *host);
extern char *shared_domain (char *host1, char *host2);
extern char *localhost ();
-char *argp_program_version = "w 1.0 (GNU " HURD_RELEASE ")";
+const char *argp_program_version = STANDARD_HURD_VERSION (w);
#define OA OPTION_ARG_OPTIONAL
@@ -71,7 +73,7 @@ static struct argp_option options[] =
{0, 0}
};
static char *args_doc = "[USER...]";
-static char *doc = 0;
+static char *doc = "Show logged in users and what they are doing";
/* The current time of day. */
static struct timeval now;
@@ -93,6 +95,14 @@ struct w_hook
#define W_PSTAT_LOGIN (PSTAT_USER_BASE << 3)
static ps_flags_t
+w_deps (ps_flags_t flags)
+{
+ if (flags & W_PSTAT_IDLE)
+ flags |= PSTAT_TTY;
+ return flags;
+}
+
+static ps_flags_t
w_fetch (struct proc_stat *ps, ps_flags_t need, ps_flags_t have)
{
struct w_hook *hook = ps->hook;
@@ -121,23 +131,34 @@ w_fetch (struct proc_stat *ps, ps_flags_t need, ps_flags_t have)
if (sd)
*sd = '\0';
}
-
- have |= W_PSTAT_HOST;
}
+ have |= W_PSTAT_HOST;
}
if (need & W_PSTAT_IDLE)
{
- struct stat stat;
- struct ps_tty *tty = ps->tty;
-
- hook->idle.tv_usec = 0;
- if (io_stat (tty->port, &stat) == 0)
+ if (have & PSTAT_TTY)
{
- hook->idle.tv_sec = now.tv_sec - stat.st_mtime;
- if (hook->idle.tv_sec > 0)
- have |= W_PSTAT_IDLE;
+ struct stat stat;
+ struct ps_tty *tty = ps->tty;
+
+ hook->idle.tv_usec = 0;
+ if (! tty)
+ {
+ hook->idle.tv_sec = 0;
+ have |= W_PSTAT_IDLE;
+ }
+ else
+ {
+ if (io_stat (tty->port, &stat) == 0)
+ {
+ hook->idle.tv_sec = now.tv_sec - stat.st_atime;
+ have |= W_PSTAT_IDLE;
+ }
+ }
}
+ else if (ps->inapp & PSTAT_TTY)
+ ps->inapp |= W_PSTAT_IDLE;
}
if (need & W_PSTAT_USER)
@@ -204,21 +225,22 @@ w_get_host (struct proc_stat *ps, char **host, unsigned *host_len)
{
struct w_hook *hook = ps->hook;
*host = hook->host;
- *host_len = strlen (*host);
+ *host_len = *host ? strlen (*host) : 0;
}
const struct ps_getter w_host_getter =
{"host", W_PSTAT_HOST, w_get_host};
extern error_t ps_emit_past_time (), ps_emit_string (), ps_emit_minutes ();
extern error_t ps_emit_user_name ();
-extern int ps_cmp_times (), ps_cmp_strings ();
+extern int ps_cmp_times (), ps_cmp_strings (), ps_cmp_unames ();
+extern int ps_nominal_string ();
const struct ps_fmt_spec _w_specs[] =
{
{"User", 0, 8, -1,0, &w_uname_getter,ps_emit_string, ps_cmp_strings},
- {"Name", 0, 20, -1,0, &w_user_getter, ps_emit_user_name,ps_cmp_strings},
+ {"Name", 0, 16, -1,0, &w_user_getter, ps_emit_user_name,ps_cmp_unames,ps_nominal_string},
{"Login","Login@", -7, -1,0,&w_login_getter,ps_emit_past_time,ps_cmp_times},
- {"From", 0, 16, -1,0, &w_host_getter, ps_emit_string, ps_cmp_strings},
- {"Idle", 0, -5, -1,0, &w_idle_getter, ps_emit_minutes,ps_cmp_times},
+ {"From", 0, 14, -1,0, &w_host_getter, ps_emit_string, ps_cmp_strings, ps_nominal_string},
+ {"Idle", 0, -5, -1,PS_FMT_FIELD_COLON_MOD, &w_idle_getter, ps_emit_minutes,ps_cmp_times},
{"What=args"},
{0}
};
@@ -231,7 +253,7 @@ static void
add_utmp_procs (struct proc_stat_list *procs, struct utmp *u)
{
/* The tty name, with space for '\0' termination and an
- appropiate prefix. */
+ appropriate prefix. */
char tty[sizeof _PATH_DEV + sizeof u->ut_line];
io_t tty_node;
error_t err;
@@ -239,6 +261,19 @@ add_utmp_procs (struct proc_stat_list *procs, struct utmp *u)
int pos;
struct proc_stat *ps;
+ switch (u->ut_type)
+ {
+ case LOGIN_PROCESS:
+ case USER_PROCESS:
+ /* These are the types that indicate a user job that we might
+ find processes for. */
+ if (u->ut_name[0] != '\0' && u->ut_line[0] != '\0')
+ break;
+ default:
+ /* This entry is not for a user, skip it. */
+ return;
+ }
+
strncpy (tty, u->ut_line, sizeof u->ut_line);
tty[sizeof u->ut_line] = '\0'; /* Ensure it's '\0' terminated. */
@@ -271,7 +306,7 @@ add_utmp_procs (struct proc_stat_list *procs, struct utmp *u)
else
{
struct proc_stat **pgrp_procs;
- unsigned num_procs;
+ size_t num_procs;
err = proc_stat_list_add_pgrp (procs, -pid, &pgrp_procs, &num_procs);
if (! err)
@@ -301,62 +336,74 @@ add_utmp_procs (struct proc_stat_list *procs, struct utmp *u)
tty, pid < 0 ? "pgrp" : "pid", pid < 0 ? -pid : pid);
}
-/* Read into PROCS from the utmp file called NAME. */
-static void
-read_utmp_procs (struct proc_stat_list *procs, char *name)
+/* Find the absolute timestamp of when the system was booted.
+ We define "system boot time" as the task creation time of PID 1 (init). */
+
+static error_t
+fetch_boot_time (struct timeval *when)
{
- int rd, fd;
- struct utmp buf[64];
+ struct ps_context *context;
+ struct proc_stat *ps;
+ error_t err;
- fd = open (name, O_RDONLY);
- if (fd < 0)
- error (9, errno, "%s", name);
+ err = ps_context_create (getproc (), &context);
+ if (err)
+ error (2, err, "ps_context_create");
+
+ err = ps_context_find_proc_stat (context, 1, &ps);
+ if (err)
+ error (3, err, "ps_context_find_proc_stat");
- while ((rd = read (fd, buf, sizeof (buf))) > 0)
+ err = proc_stat_set_flags (ps, PSTAT_TASK_BASIC);
+ if (!err && !(ps->flags & PSTAT_TASK_BASIC))
+ err = EGRATUITOUS;
+ if (err)
{
- struct utmp *u = buf;
- while (rd >= sizeof (*u))
- {
- if (*u->ut_name && *u->ut_line)
- /* An active entry. */
- add_utmp_procs (procs, u);
- rd -= sizeof (*u);
- u++;
- }
+ error (0, err, "cannot find boot time");
+ return err;
+ }
+ else
+ {
+ time_value_t *const tv = &proc_stat_task_basic_info (ps)->creation_time;
+ when->tv_sec = tv->seconds;
+ when->tv_usec = tv->microseconds;
}
- close (fd);
+ ps_context_free (context);
+
+ return 0;
}
-
+
static void
uptime (struct proc_stat_list *procs)
{
- struct stat st;
+ error_t err;
+ struct timeval boot_time;
char uptime_rep[20], tod_rep[20];
struct host_load_info *load;
unsigned nusers = 0;
- int maybe_add_user (struct proc_stat *ps) { if (ps->hook) nusers++; return 0; }
+ int maybe_add_user (struct proc_stat *ps)
+ { if (ps->hook) nusers++; return 0; }
proc_stat_list_for_each (procs, maybe_add_user);
- /* Until we get a better way of finding out how long the system's been
- up... XXX */
- if (stat ("/var/run/uptime", &st) != 0)
+ if (fetch_boot_time (&boot_time))
strcpy (uptime_rep, "chuck");
else
{
- struct timeval uptime = { now.tv_sec - st.st_ctime, 0 };
+ struct timeval uptime;
+ timersub (&now, &boot_time, &uptime);
fmt_named_interval (&uptime, 0, uptime_rep, sizeof (uptime_rep));
}
- strftime (tod_rep, sizeof (tod_rep), "%r",
+ strftime (tod_rep, sizeof (tod_rep), "%r",
localtime ((time_t *)&now.tv_sec));
if (tod_rep[0] == '0')
tod_rep[0] = ' '; /* Get rid of bletcherous leading 0. */
- errno = ps_host_load_info (&load);
- if (errno)
- error (0, errno, "ps_host_load_info");
+ err = ps_host_load_info (&load);
+ if (err)
+ error (0, err, "ps_host_load_info");
printf ("%s up %s, %u user%s, load averages: %.2f, %.2f, %.2f\n",
tod_rep, uptime_rep, nusers, nusers == 1 ? "" : "s",
@@ -365,10 +412,11 @@ uptime (struct proc_stat_list *procs)
(double)load->avenrun[2] / (double)LOAD_SCALE);
}
-void
+int
main(int argc, char *argv[])
{
error_t err;
+ struct utmp *ut;
struct ps_context *context;
int output_width = -1;
char *fmt_string = DEFAULT_FMT_STRING, *sort_key_name = NULL;
@@ -378,12 +426,23 @@ main(int argc, char *argv[])
#if 0
char *tty_names = 0;
unsigned num_tty_names = 0;
- struct idvec *only_uids = make_idvec (), *not_uids = make_idvec ();
#endif
- struct ps_user_hooks ps_hooks = { 0, w_fetch, w_cleanup };
+ uid_t *users = 0;
+ size_t num_users = 0;
+ struct ps_user_hooks ps_hooks = { w_deps, w_fetch, w_cleanup };
int has_hook (struct proc_stat *ps) { return ps->hook != 0; }
+ int keep_users (struct proc_stat *ps)
+ {
+ int i;
+ struct w_hook *h = ps->hook;
+ for (i = 0; i < num_users; i++)
+ if (users[i] == h->user->uid)
+ return 1;
+ return 0;
+ }
+
/* Parse our options... */
error_t parse_opt (int key, char *arg, struct argp_state *state)
{
@@ -400,6 +459,19 @@ main(int argc, char *argv[])
case 'w': output_width = arg ? atoi (arg) : 0; break;
case ARGP_KEY_ARG:
+ num_users++;
+ users = realloc (users, num_users * sizeof (*users));
+ if (! users)
+ argp_failure (state, 5, ENOMEM, "%s", arg);
+ else if (isdigit (*arg))
+ users[num_users - 1] = atoi (arg);
+ else
+ {
+ struct passwd *pw = getpwnam (arg);
+ if (! pw)
+ argp_failure (state, 6, 0, "%s: Unknown user", arg);
+ users[num_users - 1] = pw->pw_uid;
+ }
break;
default:
@@ -424,18 +496,25 @@ main(int argc, char *argv[])
/* Parse our options. */
argp_parse (&argp, argc, argv, 0, 0, 0);
- read_utmp_procs (procs, _PATH_UTMP);
+ /* Read the utmp file. */
+ setutent ();
+ while ((ut = getutent ()) != NULL)
+ add_utmp_procs (procs, ut);
+ endutent ();
/* Keep only processes that have our hooks attached. */
proc_stat_list_filter1 (procs, has_hook, 0, 0);
+ if (num_users > 0)
+ proc_stat_list_filter1 (procs, keep_users, W_PSTAT_USER, 0);
+
if (show_uptime)
uptime (procs);
if (show_entries)
psout (procs, fmt_string, 0, &w_specs, sort_key_name, sort_reverse,
output_width, print_heading,
- squash_bogus_fields, squash_nominal_fields);
+ squash_bogus_fields, squash_nominal_fields, 0);
- exit(0);
+ return 0;
}