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. */
gid = getgid();
/* Drop all privileges. */
- if (setresuid(uid, uid, uid) != 0) {
- perror("setresuid");
- exit(EXIT_FAILURE);
- }
if (setresgid(gid, gid, gid) != 0) {
perror("setresgid");
exit(EXIT_FAILURE);
}
+ if (setresuid(uid, uid, uid) != 0) {
+ perror("setresuid");
+ exit(EXIT_FAILURE);
+ }
/* Verify all privileges were dropped. */
if (getresuid(&ruid, &euid, &suid) != 0) {
#endif
static void usage(const char *argv0) {
- fprintf(stderr, "usage: %s [-X] [-m] <cmd args..>\n", argv0);
+ fprintf(stderr, "usage: %s [-X] [-m] [-v] <cmd args..>\n", argv0);
fprintf(stderr, "Pass wall messages to <cmd args..>.\n");
fprintf(stderr, "\n");
fprintf(stderr, "-X quit when the current X session terminates\n");
fprintf(stderr, "-m allow messages from normal users (like `mesg y`)\n");
+ fprintf(stderr, "-v display version\n");
#ifdef DONT_USE_X11
fprintf(stderr, "\n");
fprintf(stderr, "compiled without X11 support, -X disabled\n");
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
* the optstring with "+" fixes this behaver. This is not POSIX
* compatible, but the option should be ignored on other systems.
*/
- while ((option = getopt(argc, argv, "+Xmh")) != -1) {
+ while ((option = getopt(argc, argv, "+Xmhv")) != -1) {
switch (option) {
case 'X':
enable_x11 = 1;
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);
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);