util: beef up logic to find ctty name
This commit is contained in:
parent
4ff21d8582
commit
fc116c6a19
|
@ -353,13 +353,13 @@ finish:
|
|||
|
||||
static int wall_tty_block(void) {
|
||||
char *p;
|
||||
const char *t;
|
||||
int fd;
|
||||
int fd, r;
|
||||
dev_t devnr;
|
||||
|
||||
if (!(t = ttyname(STDIN_FILENO)))
|
||||
return -errno;
|
||||
if ((r = get_ctty_devnr(&devnr)) < 0)
|
||||
return -r;
|
||||
|
||||
if (asprintf(&p, "/dev/.systemd/ask-password-block/%s", file_name_from_path(t)) < 0)
|
||||
if (asprintf(&p, "/dev/.systemd/ask-password-block/%u:%u", major(devnr), minor(devnr)) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
mkdir_parents(p, 0700);
|
||||
|
@ -375,8 +375,25 @@ static int wall_tty_block(void) {
|
|||
}
|
||||
|
||||
static bool wall_tty_match(const char *path) {
|
||||
int fd;
|
||||
int fd, k;
|
||||
char *p;
|
||||
struct stat st;
|
||||
|
||||
if (path_is_absolute(path))
|
||||
k = lstat(path, &st);
|
||||
else {
|
||||
if (asprintf(&p, "/dev/%s", path) < 0)
|
||||
return true;
|
||||
|
||||
k = lstat(p, &st);
|
||||
free(p);
|
||||
}
|
||||
|
||||
if (k < 0)
|
||||
return true;
|
||||
|
||||
if (!S_ISCHR(st.st_mode))
|
||||
return true;
|
||||
|
||||
/* We use named pipes to ensure that wall messages suggesting
|
||||
* password entry are not printed over password prompts
|
||||
|
@ -386,7 +403,7 @@ static bool wall_tty_match(const char *path) {
|
|||
* advantage that the block will automatically go away if the
|
||||
* process dies. */
|
||||
|
||||
if (asprintf(&p, "/dev/.systemd/ask-password-block/%s", file_name_from_path(path)) < 0)
|
||||
if (asprintf(&p, "/dev/.systemd/ask-password-block/%u:%u", major(st.st_rdev), minor(st.st_rdev)) < 0)
|
||||
return true;
|
||||
|
||||
fd = open(p, O_WRONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
|
||||
|
|
109
src/util.c
109
src/util.c
|
@ -2749,28 +2749,121 @@ char* getlogname_malloc(void) {
|
|||
return name;
|
||||
}
|
||||
|
||||
int getttyname_malloc(char **r) {
|
||||
char path[PATH_MAX], *p, *c;
|
||||
int getttyname_malloc(int fd, char **r) {
|
||||
char path[PATH_MAX], *c;
|
||||
int k;
|
||||
|
||||
assert(r);
|
||||
|
||||
if ((k = ttyname_r(STDIN_FILENO, path, sizeof(path))) != 0)
|
||||
if ((k = ttyname_r(fd, path, sizeof(path))) != 0)
|
||||
return -k;
|
||||
|
||||
char_array_0(path);
|
||||
|
||||
p = path;
|
||||
if (startswith(path, "/dev/"))
|
||||
p += 5;
|
||||
|
||||
if (!(c = strdup(p)))
|
||||
if (!(c = strdup(startswith(path, "/dev/") ? path + 5 : path)))
|
||||
return -ENOMEM;
|
||||
|
||||
*r = c;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getttyname_harder(int fd, char **r) {
|
||||
int k;
|
||||
char *s;
|
||||
|
||||
if ((k = getttyname_malloc(fd, &s)) < 0)
|
||||
return k;
|
||||
|
||||
if (streq(s, "tty")) {
|
||||
free(s);
|
||||
return get_ctty(r);
|
||||
}
|
||||
|
||||
*r = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_ctty_devnr(dev_t *d) {
|
||||
int k;
|
||||
char line[256], *p;
|
||||
unsigned long ttynr;
|
||||
FILE *f;
|
||||
|
||||
if (!(f = fopen("/proc/self/stat", "r")))
|
||||
return -errno;
|
||||
|
||||
if (!(fgets(line, sizeof(line), f))) {
|
||||
k = -errno;
|
||||
fclose(f);
|
||||
return k;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (!(p = strrchr(line, ')')))
|
||||
return -EIO;
|
||||
|
||||
p++;
|
||||
|
||||
if (sscanf(p, " "
|
||||
"%*c " /* state */
|
||||
"%*d " /* ppid */
|
||||
"%*d " /* pgrp */
|
||||
"%*d " /* session */
|
||||
"%lu ", /* ttynr */
|
||||
&ttynr) != 1)
|
||||
return -EIO;
|
||||
|
||||
*d = (dev_t) ttynr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_ctty(char **r) {
|
||||
int k;
|
||||
char fn[128], *s, *b, *p;
|
||||
dev_t devnr;
|
||||
|
||||
assert(r);
|
||||
|
||||
if ((k = get_ctty_devnr(&devnr)) < 0)
|
||||
return k;
|
||||
|
||||
snprintf(fn, sizeof(fn), "/dev/char/%u:%u", major(devnr), minor(devnr));
|
||||
char_array_0(fn);
|
||||
|
||||
if ((k = readlink_malloc(fn, &s)) < 0) {
|
||||
|
||||
if (k != -ENOENT)
|
||||
return k;
|
||||
|
||||
/* Probably something like the ptys which have no
|
||||
* symlink in /dev/char. Let's return something
|
||||
* vaguely useful. */
|
||||
|
||||
if (!(b = strdup(fn + 5)))
|
||||
return -ENOMEM;
|
||||
|
||||
*r = b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (startswith(s, "/dev/"))
|
||||
p = s + 5;
|
||||
else if (startswith(s, "../"))
|
||||
p = s + 3;
|
||||
else
|
||||
p = s;
|
||||
|
||||
b = strdup(p);
|
||||
free(s);
|
||||
|
||||
if (!b)
|
||||
return -ENOMEM;
|
||||
|
||||
*r = b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rm_rf_children(int fd, bool only_dirs) {
|
||||
DIR *d;
|
||||
int ret = 0;
|
||||
|
|
|
@ -331,7 +331,12 @@ void sigset_add_many(sigset_t *ss, ...);
|
|||
|
||||
char* gethostname_malloc(void);
|
||||
char* getlogname_malloc(void);
|
||||
int getttyname_malloc(char **r);
|
||||
|
||||
int getttyname_malloc(int fd, char **r);
|
||||
int getttyname_harder(int fd, char **r);
|
||||
|
||||
int get_ctty_devnr(dev_t *d);
|
||||
int get_ctty(char **r);
|
||||
|
||||
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
|
|
|
@ -370,7 +370,7 @@ int utmp_wall(const char *message, bool (*match_tty)(const char *tty)) {
|
|||
goto finish;
|
||||
}
|
||||
|
||||
getttyname_malloc(&tty);
|
||||
getttyname_harder(STDIN_FILENO, &tty);
|
||||
|
||||
if (asprintf(&text,
|
||||
"\a\r\n"
|
||||
|
|
Loading…
Reference in a new issue