<commit_before>/*  $Id$

    Part of SWI-Prolog

    Author:        <NAME>
    E-mail:        <EMAIL>
    WWW:           http://www.swi-prolog.org
    Copyright (C): 1985-2006, University of Amsterdam

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifdef __linux__
#define _XOPEN_SOURCE 600
#endif

/* #define O_DEBUG 1 */
#include "pl-incl.h"
#if defined(HAVE_GRANTPT) && defined(O_PLMT)

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Open an alternative  xterm-console.  Used   to  support  multi-threading
user-interaction. Currently only implemented using the Unix-98 /dev/ptmx
style of pseudo terminals (Solaris 2.x,  Linux   2.2  and many more). As
multi-threading asks for a modern Unix   version  anyhow, this should be
ok.

In principle, asking for  HAVE_GRANTPT  should   do,  but  I  don't want
portability problems for users of   the  single-threaded version.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#ifdef HAVE_SYS_STROPTS_H
#include <sys/stropts.h>	/* needed for ioctl(fd, I_PUSH, "..") */
#endif
#include <termios.h>
#include <signal.h>

typedef struct
{ int fd;				/* associated file */
  int pid;				/* PID of xterm */
  int count;
} xterm;


static ssize_t
Xterm_read(void *handle, char *buffer, size_t count)
{ GET_LD
  xterm *xt = handle;
  int size;

  if ( LD->prompt.next && ttymode != TTY_RAW )
    PL_write_prompt(TRUE);
  else
    Sflush(Suser_output);

  size = read(xt->fd, buffer, count);

  if ( size == 0 )			/* end-of-file */
  { LD->prompt.next = TRUE;
  } else if ( size > 0 && buffer[size-1] == '\n' )
    LD->prompt.next = TRUE;


  return size;
}


static ssize_t
Xterm_write(void *handle, char *buffer, size_t count)
{ xterm *xt = handle;

  return write(xt->fd, buffer, count);
}


/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Normally we kill the xterm if all   file-descriptors  are closed. If the
thread  cannot  be  killed  however,   dieIO()    will   kill  only  the
file-descriptors that are not in use and may   fail to kill all of them.<commit_msg>FIXED: Make streams to xterm process handle EINTR correctly.<commit_after>/*  $Id$

    Part of SWI-Prolog

    Author:        <NAME>
    E-mail:        <EMAIL>
    WWW:           http://www.swi-prolog.org
    Copyright (C): 1985-2006, University of Amsterdam

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifdef __linux__
#define _XOPEN_SOURCE 600
#endif

/* #define O_DEBUG 1 */
#include "pl-incl.h"
#if defined(HAVE_GRANTPT) && defined(O_PLMT)

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Open an alternative  xterm-console.  Used   to  support  multi-threading
user-interaction. Currently only implemented using the Unix-98 /dev/ptmx
style of pseudo terminals (Solaris 2.x,  Linux   2.2  and many more). As
multi-threading asks for a modern Unix   version  anyhow, this should be
ok.

In principle, asking for  HAVE_GRANTPT  should   do,  but  I  don't want
portability problems for users of   the  single-threaded version.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#ifdef HAVE_SYS_STROPTS_H
#include <sys/stropts.h>	/* needed for ioctl(fd, I_PUSH, "..") */
#endif
#include <termios.h>
#include <signal.h>

typedef struct
{ int fd;				/* associated file */
  int pid;				/* PID of xterm */
  int count;
} xterm;


static ssize_t
Xterm_read(void *handle, char *buffer, size_t count)
{ GET_LD
  xterm *xt = handle;
  ssize_t size;

  if ( LD->prompt.next && ttymode != TTY_RAW )
    PL_write_prompt(TRUE);
  else
    Sflush(Suser_output);

  do
  { size = read(xt->fd, buffer, count);

    if ( size < 0 && errno == EINTR )
    { if ( PL_handle_signals() < 0 )
      { errno = EPLEXCEPTION;
	break;
      }

      continue;
    }
  } while(0);

  if ( size == 0 )			/* end-of-file */
  { LD->prompt.next = TRUE;
  } else if ( size > 0 && buffer[size-1] == '\n' )
    LD->prompt.next = TRUE;

  return size;
}


static ssize_t
Xterm_write(void *handle, char *buffer, size_t count)
{ xterm *xt = handle;
  ssize_t size;

  do
  { size = write(xt->fd, buffer, count);

    if ( size < 0 && errno == EINTR )
    { if ( PL_handle_signals() < 0 )
      { errno = EPLEXCEPTION;
	break;
      }

      continue;
    }
  } while(0);

  return size;
}


/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Normally we kill the xterm if all   file-descriptors  are closed. If the
thread  cannot  be  killed  however,   dieIO()    will   kill  only  the
file-descriptors that are not in use and may   fail to kill all of them.
{'fraction_non_alphanumeric': 0.1266087516087516, 'fraction_numerical': 0.011583011583011582, 'mean_word_length': 2.284204965662969, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2076379', 'n_tokens_mistral': 2240, 'n_tokens_neox': 2106, 'n_words': 711}