delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin-developers/1998/02/16/07:44:38

From: ian AT cygnus DOT com (Ian Lance Taylor)
Subject: Re: tty.cc fix.
16 Feb 1998 07:44:38 -0800 :
Message-ID: <199802161528.KAA18780.cygnus.cygwin32.developers@subrogation.cygnus.com>
References: <01BD3AC4 DOT 7157C360 AT gater DOT krystalbank DOT msk DOT ru>
Reply-To: cygwin32-developers AT cygnus DOT com
To: sos AT prospect DOT com DOT ru
Cc: cygwin32-developers AT cygnus DOT com

   From: Sergey Okhapkin <sos AT prospect DOT com DOT ru>
   Date: Mon, 16 Feb 1998 10:20:01 +0300

   Ian Lance Taylor wrote:
   >    From: Sergey Okhapkin <sos AT buggy DOT prospect DOT com DOT ru>
   >    Date: Sun, 15 Feb 1998 19:35:16 +0300
   >
   >    tty.cc	(fhandler_tty_slave::open): call DuplicateHandle() instead of 
   copying.
   >
   > This patch looks wrong.  It looks like it will break the EOF handling.
   > You have to remember that the whole point of the handle manipulation
   > in tty.cc is so that when the slave is closed, the pipe is closed.  If
   > there is somewhere I need to add comments, please let me know.

   The code in fhandler_tty_slave::close() closes _both_ fhandler's internal 
   handles and ttyp pointed. I see no difference in expect's behavior with and 
   without this patch, but with this patch it's safe to open/close tty slave 
   in pty_master owner process.

I guess I don't understand this.  I thought it was already safe for
the master to open and close the tty slave, particularly with the
patch I checked in a few days ago.  Can you give an example of a
program which fails without this patch?

I've appended one simple pty testing program I use.  It works on Unix,
and needs to continue to work on cygwin32.  When it works, it should
print the output of stty.

Ian

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#if ! defined (__CYGWIN32__) && ! defined (__linux__)
#include <stropts.h>
#endif

extern char *ptsname (int);

static void
die (const char *s, int status)
{
  perror (s);
  exit (status);
}

static void
do_once ()
{
  int om;
  const char *slave;
  struct stat sb;
  pid_t child;
  char b;
  int c;
  int status;

#ifndef __linux__

  om = open ("/dev/ptmx", O_RDWR);
  if (om < 0)
    die ("/dev/ptmx", 1);

  if (grantpt (om) < 0)
    die ("grantpt", 2);

  if (unlockpt (om) < 0)
    die ("unlockpt", 3);

  slave = ptsname (om);
  if (slave == NULL)
    die ("ptsname", 4);

#else /* __linux__ */

  int i;
  char ab[20];

  for (i = 0; i < 16; i++)
    {
      struct stat st;

      sprintf (ab, "/dev/ptyp%x", i);
      if (stat (ab, &st) < 0)
	die ("pty stat", 30);
      om = open (ab, O_RDWR);
      if (om >= 0)
	{
	  printf ("Using %s\n", ab);
	  sprintf (ab, "/dev/ttyp%x", i);
	  slave = ab;
	  break;
	}
    }

#endif /* __linux__ */

  if (stat (slave, &sb) < 0)
    die ("stat", 31);

  child = fork ();
  if (child < 0)
    die ("fork", 5);

  if (child == 0)
    {
      int os;

      if (close (0) < 0 || close (1) < 0 || close (2) < 0 || close (om) < 0)
	die ("close", 6);

      if (setsid () < 0)
	die ("setsid", 13);

      os = open (slave, O_RDWR);
      if (os < 0)
	die (slave, 7);

      if (os != 0)
	die ("unexpected os", 8);

#if ! defined (__CYGWIN32__) && ! defined (__linux__)
      if (ioctl (os, I_PUSH, "ptem") < 0)
	die ("ptem", 90);
      if (ioctl (os, I_PUSH, "ldterm") < 0)
	die ("ldterm", 91);
#if 0
      if (ioctl (os, I_PUSH, "ttcompat") < 0)
	die ("ttcompat", 92);
#endif
#endif

#ifdef TIOCSCTTY
      if (ioctl (os, TIOCSCTTY, NULL) < 0)
	die ("TIOCSCTTY", 12);
#endif

      if (dup2 (os, 1) < 0
	  || dup2 (os, 2) < 0)
	die ("dup2", 10);

      printf ("About to execlp\n");
      fflush (stdout);

      execlp ("stty", "stty", "-a", NULL);
      die ("execlp", 11);
    }

  printf ("child pid is %d\n", (int) child);
  fflush (stdout);

  while ((c = read (om, &b, 1)) == 1)
    putchar (b);
  fflush (stdout);

  if (c < 0)
    {
#ifdef __linux__
      if (errno != EIO)
#endif
	die ("read", 20);
    }

  if (waitpid (child, &status, 0) < 0)
    die ("waitpid", 21);

  if (WIFEXITED (status))
    printf ("child exited with status %d\n", WEXITSTATUS (status));
  else if (WIFSIGNALED (status))
    printf ("child died with signal %d%s\n", WTERMSIG (status),
	    (status & 0200) != 0 ? " (core dumped)" : "");
  else
    printf ("unrecognized status %d\n", status);
}

int
main ()
{
  do_once ();
#if 0
  printf ("\n");
  do_once ();
#endif
  exit (0);
}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019