ubase/ps.c

181 lines
3.8 KiB
C
Raw Normal View History

2013-08-14 14:38:43 +00:00
/* See LICENSE file for copyright and license details. */
2014-06-30 18:03:41 +00:00
#include <sys/ioctl.h>
#include <sys/sysinfo.h>
2013-08-14 14:38:43 +00:00
#include <errno.h>
#include <libgen.h>
2014-06-30 14:39:42 +00:00
#include <limits.h>
#include <pwd.h>
2013-08-14 14:38:43 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
2014-06-30 14:39:42 +00:00
#include <unistd.h>
2014-06-30 18:03:41 +00:00
2013-08-14 14:38:43 +00:00
#include "proc.h"
#include "util.h"
static void psout(struct procstat *ps);
2013-08-16 15:40:29 +00:00
static void psr(const char *file);
2013-08-14 14:38:43 +00:00
enum {
PS_aflag = 1 << 0,
PS_Aflag = 1 << 1,
PS_dflag = 1 << 2,
PS_fflag = 1 << 3
2013-08-14 14:38:43 +00:00
};
static int flags;
2013-08-14 14:38:43 +00:00
static void
psout(struct procstat *ps)
{
2013-08-16 15:36:52 +00:00
struct procstatus pstatus;
char cmdline[BUFSIZ], *cmd;
char buf[BUFSIZ];
2015-01-16 15:54:15 +00:00
char ttystr[TTY_NAME_MAX], *myttystr;
2013-08-14 14:38:43 +00:00
int tty_maj, tty_min;
2013-08-16 15:36:52 +00:00
uid_t myeuid;
2013-08-16 14:57:57 +00:00
unsigned sutime;
time_t start;
char stimestr[sizeof("%H:%M")];
2013-08-16 14:53:07 +00:00
struct sysinfo info;
struct passwd *pw;
struct winsize w;
2013-08-14 14:38:43 +00:00
/* Ignore session leaders */
if (flags & PS_dflag)
if (ps->pid == ps->sid)
return;
devtotty(ps->tty_nr, &tty_maj, &tty_min);
ttytostr(tty_maj, tty_min, ttystr, sizeof(ttystr));
2013-08-16 14:57:57 +00:00
2013-08-14 14:38:43 +00:00
/* Only print processes that are associated with
* a terminal and they are not session leaders */
if (flags & PS_aflag)
if (ps->pid == ps->sid || ttystr[0] == '?')
return;
2013-08-14 14:38:43 +00:00
if (parsestatus(ps->pid, &pstatus) < 0)
return;
2013-08-16 15:36:52 +00:00
2013-08-16 14:57:57 +00:00
/* This is the default case, only print processes that have
* the same controlling terminal as the invoker and the same
* euid as the current user */
if (!(flags & (PS_aflag | PS_Aflag | PS_dflag))) {
2014-11-30 13:12:15 +00:00
myttystr = ttyname(0);
2013-08-14 14:38:43 +00:00
if (myttystr) {
if (strcmp(myttystr + strlen("/dev/"), ttystr))
2013-08-14 14:38:43 +00:00
return;
} else {
2013-08-16 14:57:57 +00:00
/* The invoker has no controlling terminal - just
* go ahead and print the processes anyway */
2013-08-14 14:38:43 +00:00
ttystr[0] = '?';
ttystr[1] = '\0';
}
myeuid = geteuid();
if (myeuid != pstatus.euid)
2013-08-14 14:38:43 +00:00
return;
}
2013-08-16 14:57:57 +00:00
sutime = (ps->stime + ps->utime) / sysconf(_SC_CLK_TCK);
2014-11-30 13:12:15 +00:00
ioctl(1, TIOCGWINSZ, &w);
if (!(flags & PS_fflag)) {
snprintf(buf, sizeof(buf), "%5d %-6s %02u:%02u:%02u %s", ps->pid, ttystr,
sutime / 3600, (sutime % 3600) / 60, sutime % 60,
ps->comm);
if (w.ws_col)
printf("%.*s\n", w.ws_col, buf);
else
printf("%s\n", buf);
} else {
errno = 0;
2013-08-16 15:36:52 +00:00
pw = getpwuid(pstatus.uid);
2014-07-12 20:32:36 +00:00
if (!pw)
eprintf("getpwuid %d:", pstatus.uid);
2013-08-16 14:51:37 +00:00
if (sysinfo(&info) < 0)
eprintf("sysinfo:");
2013-08-16 14:57:57 +00:00
start = time(NULL) - info.uptime;
start += (ps->starttime / sysconf(_SC_CLK_TCK));
strftime(stimestr, sizeof(stimestr),
2013-08-16 14:53:07 +00:00
"%H:%M", localtime(&start));
2013-08-16 14:57:57 +00:00
/* For kthreads/zombies /proc/<pid>/cmdline will be
* empty so use ps->comm in that case */
if (parsecmdline(ps->pid, cmdline, sizeof(cmdline)) < 0)
cmd = ps->comm;
else
cmd = cmdline;
snprintf(buf, sizeof(buf), "%-8s %5d %5d ? %5s %-5s %02u:%02u:%02u %s%s%s",
pw->pw_name, ps->pid,
ps->ppid, stimestr, ttystr,
sutime / 3600, (sutime % 3600) / 60, sutime % 60,
(cmd == ps->comm) ? "[" : "", cmd,
(cmd == ps->comm) ? "]" : "");
if (w.ws_col)
printf("%.*s\n", w.ws_col, buf);
else
printf("%s\n", buf);
}
2013-08-14 14:38:43 +00:00
}
static void
2013-08-16 15:40:29 +00:00
psr(const char *file)
2013-08-14 14:38:43 +00:00
{
2014-06-30 14:39:42 +00:00
char path[PATH_MAX], *p;
2013-08-14 14:38:43 +00:00
struct procstat ps;
pid_t pid;
2014-06-30 14:39:42 +00:00
if (strlcpy(path, file, sizeof(path)) >= sizeof(path))
eprintf("path too long\n");
p = basename(path);
if (pidfile(p) == 0)
2013-08-14 14:38:43 +00:00
return;
2014-06-30 14:39:42 +00:00
pid = estrtol(p, 10);
if (parsestat(pid, &ps) < 0)
return;
2013-08-14 14:38:43 +00:00
psout(&ps);
}
2015-03-08 12:08:32 +00:00
static void
usage(void)
{
eprintf("usage: %s [-aAdef]\n", argv0);
2015-03-08 12:08:32 +00:00
}
int
main(int argc, char *argv[])
{
ARGBEGIN {
case 'a':
flags |= PS_aflag;
break;
case 'A':
flags |= PS_Aflag;
break;
case 'd':
flags |= PS_dflag;
break;
case 'e':
flags |= PS_Aflag;
break;
case 'f':
flags |= PS_fflag;
break;
default:
usage();
} ARGEND;
if (!(flags & PS_fflag))
printf(" PID TTY TIME CMD\n");
else
printf("UID PID PPID C STIME TTY TIME CMD\n");
recurse("/proc", psr);
return 0;
}