/* chowntty.c - control ownership of your own tty
**
** v2 by Pegasus Epsilon <pegasus@pimpninjas.org>
** (C) 2013 Distribute Unmodified
** http://pegasus.pimpninjas.org/license
**
** rationale: if you're connected to it, it's yours, do what you want with it.
**
** known issues:
** you can use this to take ownership of /dev/tty and /dev/ptmx
** possibly other special "tty devices" as well. not sure how to stop this
** without making assumptions about the system.
**
** the redirected() function is my feeble attempt at avoiding this, but it
** still fails if you're clever.
*/
#define _XOPEN_SOURCE 500
/* >= 500, snprintf(), strdup(), readlink() */
#include <linux/limits.h> /* PATH_MAX */
#include <stdio.h> /* printf(), fileno(), puts(), snprintf() */
#include <string.h> /* strdup(), strcmp() */
#include <stdlib.h> /* exit(), free() */
#include <unistd.h> /* isatty(), ttyname(), chown(), readlink() */
#include <sys/types.h> /* getpwnam() */
#include <pwd.h> /* getpwnam() */
void usage (char *myself) {
printf("Usage: %s [LOGIN]\n", myself);
exit(-1);
}
int redirected (void) {
int i;
ssize_t len;
char link[PATH_MAX + 1], *last = NULL;
for (i = 0; i < 256; i++) {
snprintf(link, PATH_MAX + 1, "/proc/self/fd/%d", i);
len = readlink(link, link, PATH_MAX);
if (0 <= len) {
link[len] = 0;
if (!last) last = strdup(link);
else if (strcmp(last, link)) return 1;
}
}
if (last) free(last);
return 0;
}
int main (int argc, char **argv) {
struct passwd *pwd;
if (argc != 2 || NULL == (pwd = getpwnam(argv[1]))) usage(argv[0]);
if (isatty(fileno(stdin)) && !redirected())
chown(ttyname(fileno(stdin)), pwd->pw_uid, -1);
else puts("Nice try. No dice.");
return 0;
}