2 * Copyright 2011 Christian Hofstaedtler. Licensed under GPL Version 2.
4 * Most of this is copied from fgetty, which is
5 * Copyright Felix von Leitner, licensed under GPL Version 2.
16 #include <sys/param.h>
17 #include <sys/ioctl.h>
18 #include <sys/types.h>
28 void error(const char* message, int exitcode) {
30 write(2, message, strlen(message));
32 syslog(LOG_CRIT, "%s", message);
38 void sigquit_handler(int signum) {
39 error("SIGQUIT received\n",23);
45 if (chown(tty,0,0) || chmod(tty,0600))
46 error("could not chown/chmod tty device\n",1);
47 sa.sa_handler=SIG_IGN;
49 sigemptyset(&sa.sa_mask);
50 sigaction(SIGHUP,&sa,NULL);
51 sa.sa_handler=sigquit_handler;
52 sigaction(SIGQUIT,&sa,NULL);
55 if ((fd=open(tty, O_RDWR, 0))<0)
56 error("open tty failed", errno);
57 if (ioctl (fd, TIOCSCTTY, (void *)1) == -1)
58 error("ioctl TIOCSCTTY failed", errno);
60 error("\"not a typewriter\" (isatty failed)", errno);
61 if (vhangup()) /* linux specific */
62 error("vhangup failed", errno);
63 close(2); close(1); close(0); close(fd);
64 if (open(tty, O_RDWR,0) != 0)
65 error("could not (re)open tty", errno);
66 if (dup(0) != 1 || dup(0) != 2)
67 error("could not dup stdout and stderr", errno);
69 sa.sa_handler=SIG_DFL;
71 sigemptyset(&sa.sa_mask);
72 sigaction(SIGHUP,&sa,NULL);
75 void setenvvar(char* envvar, char* value) {
76 /* buf ends up directly in env. can't use alloca */
77 char* buf = malloc(strlen(envvar) + strlen(value) + 2);
84 int main(int argc, char* argv[]) {
91 openlog("grml-runtty", LOG_CONS | LOG_PID, LOG_AUTHPRIV);
93 if (tty == NULL || prog == NULL || user == NULL)
94 error("Usage: grml-runtty /dev/ttyX /bin/bash user", 1);
98 error("User does not exist", 1);
101 putenv("TERM=linux");
102 if (pw->pw_uid == 0) {
103 putenv("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
105 putenv("PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games");
107 setenvvar("TTY", tty);
108 setenvvar("USER", pw->pw_name);
109 setenvvar("LOGNAME", pw->pw_name);
110 setenvvar("SHELL", pw->pw_shell);
111 setenvvar("HOME", pw->pw_dir);
114 sprintf(uidbuf, "%i", pw->pw_uid);
115 setenvvar("UID", uidbuf);
121 chown(tty, pw->pw_uid, pw->pw_gid);
123 if (initgroups(pw->pw_name, pw->pw_gid) == -1)
124 error("initgroups failed", 1);
125 if (setgid(pw->pw_gid) == -1)
126 error("setgid failed", 1);
127 if (setuid(pw->pw_uid) == -1)
128 error("setuid failed", 1);
131 char *Argv[] = {prog, 0};
132 execve(prog, Argv, environ);
135 /* should never come here */
136 error("Program startup failed", 99);