Properly match (ttymaj, ttymin) pairs to tty names in /dev - ubase - suckless l… | |
git clone git://git.suckless.org/ubase | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit d76319f838dfb42c13c099012e72ca11d37d7178 | |
parent 2a0deb76009631af15b1dd7b435392bf2511b319 | |
Author: sin <[email protected]> | |
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: | |
M libutil/tty.c | 75 ++++++++++++++++++++++++-----… | |
M ps.c | 20 ++++++-------------- | |
M util.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); |