From: Jan Wielemaker (jan@swi.psy.uva.nl)
Date: 04/07/93


From: jan@swi.psy.uva.nl (Jan Wielemaker)
Subject: Controlling terminal
Date: Wed, 7 Apr 1993 12:45:45 GMT


Hi,

Nearly everything works! Just this. I'm trying to get a sub-process
hanging off a pty. The control terminal of the sub-process should be
the pty. I've got the code tested on SunOS, Ultrix and AIX, but it
refuses to switch the controlling tty on Linux. A bug?

Roughly, the program

        1) Finds and opens a pty
        2) Fork()'s
        3) the child discards it's /dev/tty using TIOCNOTTY ioctl()
        4) the child opens /dev/pty? and closes it again to make this
           pty the new /dev/tty
        5) the child dup2()'s stdin etc.
        6) the child exec()'s

Here is the source of the interesting peace:

        .....

      if ( (name = getPTty(p, &master, &slave)) == NULL )
        fail;

      if ( (pid = fork()) == 0 ) /* child process */
      { int fd, i, argc;
        char **argv;

        if ( notDefault(p->directory) )
          cdDirectory(p->directory);
        initEnvironment(p);

        if ( fd = open("/dev/tty", 2) ) /* detach from controlling tty */
        { ioctl(fd, TIOCNOTTY, NULL);
          close(fd);
        }
        if ( (fd = open(name, 0)) >= 0 ) /* attach to tty-p */
          close(fd);

        close(master); /* connect to tty-p */
        dup2(slave, 0);
        dup2(slave, 1);
        dup2(slave, 2);
        close(slave);

        argv = alloca(sizeof(char *) * (valInt(p->arguments->size) + 2));
        argc = valInt(p->arguments->size);

        argv[0] = p->name->text;

        for(i=0; i<argc; i++)
          argv[i+1] = toCharp(p->arguments->elements[i]);
        argv[i+1] = NULL;

        if ( execvp(p->name->text, argv) )
        { errorPce(p, NAME_cannotStart, OsError());
          exit(1);
        }
      } else /* parent process */
      { close(slave);

        assign(p, tty, CtoName(name));
        pidProcess(p, toInt(pid));
        p->rdfd = p->wrfd = master;
        p->rdstream = NULL;
        assign(p, status, NAME_running);
      }

        Thanks!

                --- Jan