/*
* Receive wall messages and pass them to a notification program via stdin.
*
- * Copyright (C) 2014 Simon Ruderich
+ * Copyright (C) 2014-2015 Simon Ruderich
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#endif
+static sig_atomic_t signaled = 0;
+
+
static void sig_handler(int signal) {
(void)signal;
+
+ signaled = 1;
}
static void setup_signals(void) {
struct sigaction action;
sigaction(SIGUSR2, &action, NULL);
}
+static int set_cloexec(int fd) {
+ int flags = fcntl(fd, F_GETFD);
+ if (flags == -1) {
+ return 0;
+ }
+ if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
+ return 0;
+ }
+ return 1;
+}
+
static int open_tty(int public) {
int ptm;
const char *name;
if (grantpt(ptm) != 0) {
return -1;
}
+ if (!set_cloexec(ptm)) {
+ return -1;
+ }
/* Prevent write access for other users so they can't use wall to send
* messages to this program. */
ssize_t r;
assert(SSIZE_MAX <= SIZE_MAX);
- while ((r = read(fd, buffer, sizeof(buffer))) > 0) {
+ while (!signaled && (r = read(fd, buffer, sizeof(buffer))) > 0) {
size_t space;
ssize_t r2;
int main(int argc, char **argv) {
int option, enable_x11, mesg_yes;
+ const char *argv0;
int ptm, pts;
char *name;
enable_x11 = 0;
mesg_yes = 0;
+ argv0 = argv[0];
+
/*
* Glibc violates POSIX by default and skips over non-option arguments and
* parses later arguments which look like options as well. But we want to
mesg_yes = 1;
break;
case 'h':
- usage(argv[0]);
+ usage(argv0);
break;
case 'v':
printf("%s%s\n",
PACKAGE_STRING,
strlen(GIT_VERSION) ? " (Git " GIT_VERSION ")" : "");
- exit(0);
+ exit(EXIT_SUCCESS);
break;
default:
fprintf(stderr, "%s: unknown option '%s'!\n\n",
- argv[0], argv[optind - 1]);
- usage(argv[0]);
+ argv0, argv[optind - 1]);
+ usage(argv0);
break;
}
}
/* No arguments remaining, abort. */
if (!argv[optind]) {
- usage(argv[0]);
+ usage(argv0);
}
/* Arguments for notification program. */
argv += optind;
/* We need to open the slave or reading from the master yields EOF after
* the first wall write to it. */
- pts = open(name, O_RDWR);
+ pts = open(name, O_RDWR | O_CLOEXEC);
if (pts < 0) {
perror(name);
exit(EXIT_FAILURE);