aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2015-11-07 11:29:36 -0800
committerRob Landley <rob@landley.net>2015-11-09 17:37:47 -0600
commitb0f4710754fde8cea483c4ca89ccef0d85d32219 (patch)
treedd35509d57482383c7ff10bf447175a7847ec5d3
parent86cef660e4a5a2d9e764486bc62c37a1c75fac6d (diff)
downloadtoybox-b0f4710754fde8cea483c4ca89ccef0d85d32219.tar.gz
Make ps try harder to find a name for a tty.
-rw-r--r--toys/posix/ps.c68
1 files changed, 48 insertions, 20 deletions
diff --git a/toys/posix/ps.c b/toys/posix/ps.c
index f3ff39bf..bc3060ca 100644
--- a/toys/posix/ps.c
+++ b/toys/posix/ps.c
@@ -181,6 +181,32 @@ static int match_process(long long *slot)
return 1;
}
+static void find_tty_name(char *out, int rdev) {
+ int major = (rdev>>8)&0xfff, minor = ((rdev>>12)&0xfff00)|(rdev&0xff);
+ FILE *fp = fopen("/proc/tty/drivers", "r");
+
+ if (fp) {
+ int tty_major;
+
+ while (fscanf(fp, "%*s %s %d %*s %*s", out, &tty_major) == 2) {
+ // TODO: we could parse the minor range too.
+ if (tty_major == major) {
+ struct stat st;
+
+ sprintf(out + strlen(out), "%d", minor);
+ if (!stat(out, &st) && S_ISCHR(st.st_mode) && st.st_rdev == rdev) {
+ fclose(fp);
+ return;
+ }
+ }
+ }
+ fclose(fp);
+ }
+
+ // Really couldn't find it, so just show major:minor.
+ sprintf(out, "%d:%d", major, minor);
+}
+
// dirtree callback.
// toybuf used as: 1024 /proc/$PID/stat, 1024 slot[], 2048 /proc/$PID/cmdline
static int do_ps(struct dirtree *new)
@@ -315,28 +341,30 @@ static int do_ps(struct dirtree *new)
// TTY
} else if (i==12) {
-
- // Can we readlink() our way to a name?
- for (i=0; i<3; i++) {
- struct stat st;
-
- sprintf(scratch, "%lld/fd/%i", *slot, i);
- fd = dirtree_parentfd(new);
- if (!fstatat(fd, scratch, &st, 0) && S_ISCHR(st.st_mode)
- && st.st_rdev == slot[4]
- && 0<(len = readlinkat(fd, scratch, out, 2047)))
- {
- out[len] = 0;
- if (!strncmp(out, "/dev/", 5)) out += 5;
-
- break;
+ int rdev = slot[4];
+
+ // The common case is no tty, and we call that "?" rather than "0:0".
+ if (rdev == 0) strcpy(out, "?");
+ else {
+ // Can we readlink() our way to a name?
+ for (i=0; i<3; i++) {
+ struct stat st;
+
+ sprintf(scratch, "%lld/fd/%i", *slot, i);
+ fd = dirtree_parentfd(new);
+ if (!fstatat(fd, scratch, &st, 0) && S_ISCHR(st.st_mode)
+ && st.st_rdev == rdev
+ && 0<(len = readlinkat(fd, scratch, out, 2047)))
+ {
+ out[len] = 0;
+ break;
+ }
}
- }
- // Couldn't find it, show major:minor
- if (i==3) {
- i = slot[4];
- sprintf(out, "%d:%d", (i>>8)&0xfff, ((i>>12)&0xfff00)|(i&0xff));
+ // Couldn't find it, try all the tty drivers.
+ if (i == 3) find_tty_name(out, rdev);
+
+ if (!strncmp(out, "/dev/", 5)) out += 5;
}
// TIME ELAPSED