On Fri, 15 Sep 2000, Russell King wrote:
> There are two ways for a tty to become a controlling terminal:
>
> 1. First tty opened after a successful setsid() call.
> 2. using the TIOCSCTTY ioctl after a successful setsid() call.
>
> Both will only suceed if the current process does not already have a
> controlling terminal.
>
> (Note that TIOCSCTTY takes an argument which means "steal the controlling
> tty from another session leader, if any" which only works if the calling
> process is UID0).
>
There was an argument, but strace didn't show it.
> Therefore...
>
> Richard B. Johnson writes:
> > setsid() = 6
> > open("/dev/tty1", O_RDWR|O_NONBLOCK) = 3
>
> at this point, tty1 is your controlling terminal (by condition 1 above),
> and
>
There is no controlling terminal, ^C doesn't work, etc. even though
the terminal parameters are properly set ISIG|ICANNON|ETC.
> > fcntl(3, F_GETFL) = 0x802 (flags O_RDWR|O_NONBLOCK)
> > fcntl(3, F_SETFL, O_RDWR) = 0
> > dup2(3, 0) = 0
> > dup2(3, 1) = 1
> > dup2(3, 2) = 2
> > ioctl(3, TIOCSCTTY) = -1 EPERM (Operation not permitted)
>
> fails because you already have a controlling terminal.
>
> Read:
> drivers/char/tty_io.c:tiocsctty
> drivers/char/tty_io.c:tty_open
> kernel/sys.c:sys_setsid
>
I have read these and I think I have found a long-standing bug.
The 'rules' you cite seem to work if there is an initial fork().
However, they certainly don't work with PID=1.
I got it to work as:
int main()
{
int stat, i, flags, fd;
sigset_t sig;
struct termios term;
struct sigaction sa;
i = 0;
[SNIPPED...]
(void)sigemptyset(&sig);
(void)sigprocmask(SIG_SETMASK, &sig, NULL);
memset(&sa, 0x00, sizeof(sa));
sa.sa_handler = reaper;
sa.sa_flags = SA_RESTART;
(void)sigaction(SIGCHLD, &sa, NULL);
sa.sa_handler = stopper;
(void)sigaction(SIGTSTP, &sa, NULL);
sa.sa_handler = starter;
(void)sigaction(SIGCONT, &sa, NULL);
sa.sa_handler = SIG_IGN;
(void)sigaction(SIGINT, &sa, NULL);
memset(&term, 0x00, sizeof(term));
term.c_cc[VINTR] = (char) 'C' - 64;
term.c_cc[VQUIT] = (char) '\\\\' - 64;
term.c_cc[VKILL] = (char) 'U' - 64;
term.c_cc[VEOF] = (char) 'D' - 64;
term.c_cc[VSTART] = (char) 'Q' - 64;
term.c_cc[VSTOP] = (char) 'S' - 64;
term.c_cc[VSUSP] = (char) 'Z' - 64;
term.c_cc[VERASE] = (char) 127;
term.c_cc[VTIME] = (char) 0;
term.c_cc[VMIN] = (char) 1;
term.c_oflag = OPOST|ONLCR;
term.c_iflag = ICRNL|IXON;
term.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOKE;
term.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
(void)tcsetattr(0, TCSANOW, &term);
for(;;) {
switch(fork()) {
case 0:
(void)ioctl(0, TIOCNOTTY, 0);
(void)close(0);
(void)close(1);
(void)close(2);
(void)setsid();
(void)open("/dev/tty1", O_RDWR|O_NDELAY,0);
flags = fcntl(0, F_GETFL, 0);
flags &= ~O_NDELAY;
(void)fcntl(0, F_SETFL, flags);
(void)dup(0);
(void)dup(0);
(void)tcsetattr(0, TCSANOW, &term);
if(ioctl(0, TIOCSCTTY, 1)<0)
perror("ioctl(TIOCSCTTY)");
i = 0;
sa.sa_handler = SIG_DFL;
for(i=1; i< NSIG; i++)
(void)sigaction(i, &sa, NULL);
sa.sa_handler = reaper;
(void)sigaction(SIGCHLD, &sa, NULL);
(void)execve(argv[0], argv, environ);
perror("execve");
exit(1);
case -1:
fprintf(stderr, "Fork failed\n");
break;
default:
(void)wait(&stat);
}
(void)sleep(1);
(void)tcsetattr(0, TCSANOW, &term);
(void)write(0, fixscr, sizeof(fixscr) -1 );
}
}
Cheers,
Dick Johnson
Penguin : Linux version 2.2.15 on an i686 machine (797.90 BogoMips).
"Memory is like gasoline. You use it up when you are running. Of
course you get it all back when you reboot..."; Actual explanation
obtained from the Micro$oft help desk.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/