[comp.unix.questions] PTY's

wileyjm@turing.cs.rpi.edu (John-Michael Wiley) (07/24/90)

I am trying to write a process that sits between the csh and the 
terminal (See code below). The routine openpty simply opens
up the master and slave side of a psuedo-terminal using the 
flags O_RDWR | O_NDELAY. 

Whenever I run the code I get the message

Stopped (tty input)

and then I get my normal shell prompt. I know it is not the child's
prompt because I have the command number in my prompt. Can anyone tell
me what I am doing wrong? Please email responses to
    wileyjm@turing.cs.rpi.edu

Thanks in advance,
J.M. Wiley

/***********************************************************************/
/* #includes and globale vars declared .... */

main(argc, argv)
  int argc;
  char *argv[];
  
{
  char out_buff[MAXLINE];
  char in_buff[MAXLINE];
  char program[128];
  fd_set rd, wr, ex;
  int width = getdtablesize();
  int code;
  
  
  openpty(&master, &slave, masterPath, slavePath);
  
  /*** Now start the child process                          ***/
  child_pid = fork();
  switch(child_pid) {
  case -1 :
  perror("Can't create a new process");
  exit(-1);
 case 0:
  close(master);
  if((dup2(slave, 0) == -1)  ||
     (dup2(slave, 1) == -1) ||
     (dup2(slave, 2) == -1)) {
    perror("Clef Trying to Dupe child");
    exit(-1);
  }
  if(slave > 2) close(slave);
  sprintf(program, "/bin/csh");
  execlp( program,program, NULL);
  perror("Trying to exec");
  break;
 case 1:  
  close(slave);
  while(1)  {   
    FD_ZERO(&rd);
    FD_SET(master, &rd); 
    FD_SET(0, &rd); 
    code = select(width, &rd, (fd_set *) NULL, (fd_set *) NULL, NULL);
    if(code < 0) {
      perror("Select");
      exit(-1);
    }
    
    if(FD_ISSET(master, &rd)) {
      if((num_read = read(master, out_buff, MAXLINE)) == -1) { 
	perror("Reading child output");
	exit(-1);
      } else 
      write(1,out_buff, num_read);
    } else if(FD_ISSET(0, &rd)) {
      num_read = read(0, in_buff, MAXLINE);
      if(num_read < 0) {
	perror("Reading stdin");
	exit(-1);
      } else 
      write(master, in_buff, num_read);
    }
  }
}
J.M. Wiley               ------            wileyjm@turing.cs.rpi.edu

Go Heels'                       

maart@cs.vu.nl (Maarten Litmaath) (07/25/90)

In article <*%2$X6-@rpi.edu>,
	wileyjm@turing.cs.rpi.edu (John-Michael Wiley) writes:
)
)I am trying to write a process that sits between the csh and the 
)terminal [...]

It is not that trivial.  I'd say it's almost impossible to get it
_completely_ right when using the BSD pty driver...
You could use the `mtty' package I've just posted to alt.sources.
Check the accompanying documentation and you'll understand the
difficulties...
--
 "and with a sudden plop it lands on usenet.  what is it? omigosh, it must[...]
   be a new user! quick kill it before it multiplies!"      (Loren J. Miller)

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (07/26/90)

In article <7170@star.cs.vu.nl> maart@cs.vu.nl (Maarten Litmaath) writes:
> It is not that trivial.  I'd say it's almost impossible to get it
> _completely_ right when using the BSD pty driver...
> You could use the `mtty' package I've just posted to alt.sources.

Or the more powerful ``pty'' package I just posted to alt.sources. An
official version should appear sometime in comp.sources.unix.

> Check the accompanying documentation and you'll understand the
> difficulties...

No offense, Maarten, but I think some of your ``difficulties'' are blown
a bit out of proportion.

Convention dictates that the pty is used only until the child exits; so
the master need not close the slave side. (In fact, it should not close
the slave side, as it has to reset the slave's modes before exiting.
This is more of a problem for pty, which is meant to act as the sole
interface between pseudo-terminals and the rest of the system, than it
is for mtty.)

The master *can* handle the I/O while waiting for a SIGCHLD; it just
mustn't die within the SIGCHLD handler. Look at the pty code for an
example of how to do this correctly.

You complain that ``anyone can open the tty slave,'' but in fact that's
only a reflection of a poor security model. pty is much more careful
about security matters, though it can be compiled and run without
privileges.

---Dan

maart@cs.vu.nl (Maarten Litmaath) (07/26/90)

In article <5756:Jul2520:37:5490@kramden.acf.nyu.edu>,
	brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
)...
)Convention dictates that the pty is used only until the child exits; [...]

Hmm, this seems normal behavior indeed, but in general I'd like _any_
pipeline using `pty' or `mtty' to work just like it would without using
the pseudo tty utility...  [Note: both `pty' and `mtty' close the pty if
the child exits.]

)...
)The master *can* handle the I/O while waiting for a SIGCHLD; it just
)mustn't die within the SIGCHLD handler.

That was not my problem; I was thinking of output getting lost without
proper indication how much has been written, but this can be fixed indeed
using restartable system calls.

)Look at the pty code [...]

I will.
--
 "and with a sudden plop it lands on usenet.  what is it? omigosh, it must[...]
   be a new user! quick kill it before it multiplies!"      (Loren J. Miller)

jay@gdx.UUCP (Jay A. Snyder) (11/23/90)

I'd like to write a program the emulates a different terminal than the
one that you are actually using.  The best way seems to be a pty.
I'd appreciate any info on using ptys, both Xenix specific and general
info is welcome.

Use email, I'll  post a summary.

J.
-- 
==============================================================================
Jay A. Snyder 					 "Let Me Up!  I've had enough"
wa3wbu!gdx!jay@uunet.uu.net
uunet!wa3wbu!gdx!jay