ubase

suckless linux base utils
git clone git://git.2f30.org/ubase
Log | Files | Refs | README | LICENSE

commit d76319f838dfb42c13c099012e72ca11d37d7178
parent 2a0deb76009631af15b1dd7b435392bf2511b319
Author: sin <sin@2f30.org>
Date:   Fri, 16 Jan 2015 15:32:55 +0000

Properly match (ttymaj, ttymin) pairs to tty names in /dev

For the common case where we have pts/ or tty do it straight
away.  Otherwise traverse /dev for a match.  This fixes ps(1) when
it is executed over a serial terminal with tty names like ttyAMA0.

Diffstat:
Mlibutil/tty.c | 75++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mps.c | 20++++++--------------
Mutil.h | 2+-
3 files changed, 65 insertions(+), 32 deletions(-)

diff --git a/libutil/tty.c b/libutil/tty.c @@ -1,7 +1,13 @@ /* See LICENSE file for copyright and license details. */ +#include <sys/types.h> +#include <sys/stat.h> + +#include <dirent.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "../util.h" @@ -12,28 +18,63 @@ devtotty(int dev, int *tty_maj, int *tty_min) *tty_min = (dev & 0xff) | ((dev >> 12) & 0xfff00); } -char * -ttytostr(int tty_maj, int tty_min) +int +ttytostr(int tty_maj, int tty_min, char *str, size_t n) { - const char *pts = "pts/"; - const char *tty = "tty"; - char *ttystr; - size_t len; - - /* Up to 10k ttys */ - len = strlen(pts) + 4 + 1; - ttystr = emalloc(len); + struct stat sb; + struct dirent *dp; + DIR *dirp; + char path[PATH_MAX]; + switch (tty_maj) { case 136: - snprintf(ttystr, len, "%s%d", pts, tty_min); - break; + snprintf(str, n, "pts/%d", tty_min); + return 0; case 4: - snprintf(ttystr, len, "%s%d", tty, tty_min); - break; + snprintf(str, n, "tty%d", tty_min); + return 0; default: - ttystr[0] = '?'; - ttystr[1] = '\0'; + str[0] = '?'; + str[1] = '\0'; break; } - return ttystr; + + dirp = opendir("/dev"); + if (!dirp) { + weprintf("opendir /dev:"); + return -1; + } + + while ((dp = readdir(dirp))) { + if (!strcmp(dp->d_name, ".") || + !strcmp(dp->d_name, "..")) + continue; + + if (strlcpy(path, "/dev/", sizeof(path)) >= sizeof(path)) { + weprintf("path too long\n"); + return -1; + } + if (strlcat(path, dp->d_name, sizeof(path)) >= sizeof(path)) { + weprintf("path too long\n"); + return -1; + } + + if (stat(path, &sb) < 0) { + weprintf("stat %s:", dp->d_name); + return -1; + } + + if ((int)major(sb.st_rdev) == tty_maj && + (int)minor(sb.st_rdev) == tty_min) { + strlcpy(str, dp->d_name, n); + break; + } + } + + if (closedir(dirp) < 0) { + weprintf("closedir /dev:"); + return -1; + } + + return 0; } diff --git a/ps.c b/ps.c @@ -70,7 +70,7 @@ psout(struct procstat *ps) struct procstatus pstatus; char cmdline[BUFSIZ], *cmd; char buf[BUFSIZ]; - char *ttystr, *myttystr; + char ttystr[PATH_MAX], *myttystr; int tty_maj, tty_min; uid_t myeuid; unsigned sutime; @@ -86,16 +86,13 @@ psout(struct procstat *ps) return; devtotty(ps->tty_nr, &tty_maj, &tty_min); - ttystr = ttytostr(tty_maj, tty_min); + ttytostr(tty_maj, tty_min, ttystr, sizeof(ttystr)); /* 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] == '?') { - free(ttystr); + if (flags & PS_aflag) + if (ps->pid == ps->sid || ttystr[0] == '?') return; - } - } if (parsestatus(ps->pid, &pstatus) < 0) return; @@ -106,10 +103,8 @@ psout(struct procstat *ps) if (!(flags & (PS_aflag | PS_Aflag | PS_dflag))) { myttystr = ttyname(0); if (myttystr) { - if (strcmp(myttystr + strlen("/dev/"), ttystr)) { - free(ttystr); + if (strcmp(myttystr + strlen("/dev/"), ttystr)) return; - } } else { /* The invoker has no controlling terminal - just * go ahead and print the processes anyway */ @@ -117,10 +112,8 @@ psout(struct procstat *ps) ttystr[1] = '\0'; } myeuid = geteuid(); - if (myeuid != pstatus.euid) { - free(ttystr); + if (myeuid != pstatus.euid) return; - } } sutime = (ps->stime + ps->utime) / sysconf(_SC_CLK_TCK); @@ -166,7 +159,6 @@ psout(struct procstat *ps) else printf("%s\n", buf); } - free(ttystr); } static void diff --git a/util.h b/util.h @@ -50,4 +50,4 @@ size_t strlcpy(char *, const char *, size_t); /* tty.c */ void devtotty(int, int *, int *); -char *ttytostr(int, int); +int ttytostr(int, int, char *, size_t);