summaryrefslogtreecommitdiffstats
path: root/term-utils/write.c
diff options
context:
space:
mode:
authorSami Kerola2016-05-14 20:39:37 +0200
committerSami Kerola2016-07-04 00:35:10 +0200
commita58b90255c247efc455e6e84ffa0601b325ac090 (patch)
tree870cd9309ccb76c3572feec6f8b8a08a32a3a8bf /term-utils/write.c
parentwrite: tell when effective gid and tty path group mismatch (diff)
downloadkernel-qcow2-util-linux-a58b90255c247efc455e6e84ffa0601b325ac090.tar.gz
kernel-qcow2-util-linux-a58b90255c247efc455e6e84ffa0601b325ac090.tar.xz
kernel-qcow2-util-linux-a58b90255c247efc455e6e84ffa0601b325ac090.zip
write: stop removing and adding /dev/ in front of tty string
Add both path and tty name representations of tty's to control structure, that point to same string beginning from different depths. This way there is no need to removing and adding /dev/ in front of tty string all the time. Secondly this change makes it possible to use of get_terminal_name() from ttyutils.c. Signed-off-by: Sami Kerola <kerolasa@iki.fi>
Diffstat (limited to 'term-utils/write.c')
-rw-r--r--term-utils/write.c81
1 files changed, 38 insertions, 43 deletions
diff --git a/term-utils/write.c b/term-utils/write.c
index 1b476473f..be91218cf 100644
--- a/term-utils/write.c
+++ b/term-utils/write.c
@@ -64,6 +64,7 @@
#include "closestream.h"
#include "nls.h"
#include "strutils.h"
+#include "ttyutils.h"
#include "xalloc.h"
static sig_atomic_t signal_received = 0;
@@ -71,9 +72,11 @@ static sig_atomic_t signal_received = 0;
struct write_control {
uid_t src_uid;
const char *src_login;
- char *src_tty;
+ const char *src_tty_path;
+ const char *src_tty_name;
const char *dst_login;
- char dst_tty[PATH_MAX];
+ char *dst_tty_path;
+ const char *dst_tty_name;
};
static void __attribute__((__noreturn__)) usage(FILE *out)
@@ -98,24 +101,20 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
* check_tty - check that a terminal exists, and get the message bit
* and the access time
*/
-static int check_tty(char *tty, int *tty_writeable, time_t *tty_atime, int showerror)
+static int check_tty(const char *tty, int *tty_writeable, time_t *tty_atime, int showerror)
{
struct stat s;
- char path[PATH_MAX];
- if (sizeof(path) < strlen(tty) + 6)
- return 1;
- sprintf(path, "/dev/%s", tty);
- if (stat(path, &s) < 0) {
+ if (stat(tty, &s) < 0) {
if (showerror)
- warn("%s", path);
+ warn("%s", tty);
return 1;
}
if (getuid() == 0) /* root can always write */
*tty_writeable = 1;
else {
if (getegid() != s.st_gid) {
- warnx(_("effective gid does not match group of %s"), path);
+ warnx(_("effective gid does not match group of %s"), tty);
return 1;
}
*tty_writeable = s.st_mode & S_IWGRP;
@@ -139,7 +138,7 @@ static int check_utmp(const struct write_control *ctl)
while ((u = getutent())) {
if (strncmp(ctl->dst_login, u->ut_user, sizeof(u->ut_user)) == 0 &&
- strncmp(ctl->dst_tty, u->ut_line, sizeof(u->ut_line)) == 0) {
+ strncmp(ctl->dst_tty_name, u->ut_line, sizeof(u->ut_line)) == 0) {
res = 0;
break;
}
@@ -165,6 +164,7 @@ static void search_utmp(struct write_control *ctl)
struct utmp *u;
time_t best_atime = 0, tty_atime;
int num_ttys = 0, valid_ttys = 0, tty_writeable = 0, user_is_me = 0;
+ char path[UT_LINESIZE + 6];
utmpname(_PATH_UTMP);
setutent();
@@ -173,13 +173,14 @@ static void search_utmp(struct write_control *ctl)
if (strncmp(ctl->dst_login, u->ut_user, sizeof(u->ut_user)) != 0)
continue;
num_ttys++;
- if (check_tty(u->ut_line, &tty_writeable, &tty_atime, 0))
+ sprintf(path, "/dev/%s", u->ut_line);
+ if (check_tty(path, &tty_writeable, &tty_atime, 0))
/* bad term? skip */
continue;
if (ctl->src_uid && !tty_writeable)
/* skip ttys with msgs off */
continue;
- if (strcmp(u->ut_line, ctl->src_tty) == 0) {
+ if (strcmp(u->ut_line, ctl->src_tty_name) == 0) {
user_is_me = 1;
/* don't write to yourself */
continue;
@@ -190,8 +191,9 @@ static void search_utmp(struct write_control *ctl)
valid_ttys++;
if (best_atime < tty_atime) {
best_atime = tty_atime;
- xstrncpy(ctl->dst_tty, u->ut_line,
- sizeof(ctl->dst_tty));
+ free(ctl->dst_tty_path);
+ ctl->dst_tty_path = xstrdup(path);
+ ctl->dst_tty_name = ctl->dst_tty_path + 5;
}
}
@@ -201,14 +203,17 @@ static void search_utmp(struct write_control *ctl)
if (valid_ttys == 0) {
if (user_is_me) {
/* ok, so write to yourself! */
- xstrncpy(ctl->dst_tty, ctl->src_tty, sizeof(ctl->dst_tty));
+ if (!ctl->src_tty_path)
+ errx(EXIT_FAILURE, _("can't find your tty's name"));
+ ctl->dst_tty_path = xstrdup(ctl->src_tty_path);
+ ctl->dst_tty_name = ctl->dst_tty_path + 5;
return;
}
errx(EXIT_FAILURE, _("%s has messages disabled"), ctl->dst_login);
}
if (1 < valid_ttys)
warnx(_("%s is logged in more than once; writing to %s"),
- ctl->dst_login, ctl->dst_tty);
+ ctl->dst_login, ctl->dst_tty_name);
}
/*
@@ -243,7 +248,7 @@ static void do_write(const struct write_control *ctl)
struct passwd *pwd;
time_t now;
struct tm *tm;
- char path[PATH_MAX], *host, line[512];
+ char *host, line[512];
struct sigaction sigact;
/* Determine our login name(s) before the we reopen() stdout */
@@ -254,11 +259,8 @@ static void do_write(const struct write_control *ctl)
if ((login = getlogin()) == NULL)
login = pwuid;
- if (sizeof(path) < strlen(ctl->dst_tty) + 6)
- errx(EXIT_FAILURE, _("tty path %s too long"), ctl->dst_tty);
- snprintf(path, sizeof(path), "/dev/%s", ctl->dst_tty);
- if ((freopen(path, "w", stdout)) == NULL)
- err(EXIT_FAILURE, "%s", path);
+ if ((freopen(ctl->dst_tty_path, "w", stdout)) == NULL)
+ err(EXIT_FAILURE, "%s", ctl->dst_tty_path);
sigact.sa_handler = signal_handler;
sigemptyset(&sigact.sa_mask);
@@ -277,10 +279,10 @@ static void do_write(const struct write_control *ctl)
printf("\r\n\a\a\a");
if (strcmp(login, pwuid))
printf(_("Message from %s@%s (as %s) on %s at %s ..."),
- login, host, pwuid, ctl->src_tty, timestamp);
+ login, host, pwuid, ctl->src_tty_name, timestamp);
else
printf(_("Message from %s@%s on %s at %s ..."),
- login, host, ctl->src_tty, timestamp);
+ login, host, ctl->src_tty_name, timestamp);
free(host);
printf("\r\n");
@@ -329,25 +331,16 @@ int main(int argc, char **argv)
else
src_fd = -1;
- if (src_fd != -1) {
- if (!(ctl.src_tty = ttyname(src_fd)))
- errx(EXIT_FAILURE,
- _("can't find your tty's name"));
- /*
- * We may have /dev/ttyN but also /dev/pts/xx. Below,
- * check_tty() will put "/dev/" in front, so remove that
- * part.
- */
- if (!strncmp(ctl.src_tty, "/dev/", 5))
- ctl.src_tty += 5;
- if (check_tty(ctl.src_tty, &tty_writeable, NULL, 1))
+ if (src_fd != -1 &&
+ get_terminal_name(src_fd, &ctl.src_tty_path, &ctl.src_tty_name, NULL) == 0) {
+ if (check_tty(ctl.src_tty_path, &tty_writeable, NULL, 1))
exit(EXIT_FAILURE);
if (!tty_writeable)
errx(EXIT_FAILURE,
_("you have write permission turned off"));
tty_writeable = 0;
} else
- ctl.src_tty = "<no tty>";
+ ctl.src_tty_name = "<no tty>";
ctl.src_uid = getuid();
@@ -361,23 +354,25 @@ int main(int argc, char **argv)
case 3:
ctl.dst_login = argv[1];
if (!strncmp(argv[2], "/dev/", 5))
- xstrncpy(ctl.dst_tty, argv[2] + 5, sizeof(ctl.dst_tty));
+ ctl.dst_tty_path = xstrdup(argv[2]);
else
- xstrncpy(ctl.dst_tty, argv[2], sizeof(ctl.dst_tty));
+ xasprintf(&ctl.dst_tty_path, "/dev/%s", argv[2]);
+ ctl.dst_tty_name = ctl.dst_tty_path + 5;
if (check_utmp(&ctl))
errx(EXIT_FAILURE,
_("%s is not logged in on %s"),
- ctl.dst_login, ctl.dst_tty);
- if (check_tty(ctl.dst_tty, &tty_writeable, NULL, 1))
+ ctl.dst_login, ctl.dst_tty_name);
+ if (check_tty(ctl.dst_tty_path, &tty_writeable, NULL, 1))
exit(EXIT_FAILURE);
if (ctl.src_uid && !tty_writeable)
errx(EXIT_FAILURE,
_("%s has messages disabled on %s"),
- ctl.dst_login, ctl.dst_tty);
+ ctl.dst_login, ctl.dst_tty_name);
do_write(&ctl);
break;
default:
usage(stderr);
}
+ free(ctl.dst_tty_path);
return EXIT_SUCCESS;
}