allocate_pty() tries all the different known easy ways of opening
a pty. In case of failure, we resort to the old BSD-style pty
grovelling code in allocate_pty_the_old_fashioned_way(). */
+#ifndef FORCE_ALLOCATE_PTY_THE_OLD_FASHIONED_WAY
int master_fd = -1;
const char *slave_name = NULL;
const char *clone = NULL;
lose:
if (master_fd >= 0)
close (master_fd);
+#endif /* ndef FORCE_ALLOCATE_PTY_THE_OLD_FASHIONED_WAY */
return allocate_pty_the_old_fashioned_way ();
}
#endif
set_descriptor_non_blocking (inchannel);
+ set_descriptor_non_blocking (outchannel);
/* Record this as an active process, with its channels.
As a result, child_setup will close Emacs's side of the pipes. */
int xforkin = forkin;
int xforkout = forkout;
+ /* Checking for quit in the child is bad because that will
+ cause I/O, and that, in turn, can confuse the X connection. */
+ begin_dont_check_for_quit();
+
/* Disconnect the current controlling terminal, pursuant to
making the pty be the controlling terminal of the process.
Also put us in our own process group. */
Bufbyte chunkbuf[512];
Bytecount chunklen;
- while (1)
+ do
{
- ssize_t writeret;
+ Lstream_data_count writeret;
chunklen = Lstream_read (lstream, chunkbuf, 512);
- if (chunklen <= 0)
- break; /* perhaps should abort() if < 0?
- This should never happen. */
old_sigpipe =
(SIGTYPE (*) (int)) signal (SIGPIPE, send_process_trap);
- /* Lstream_write() will never successfully write less than
- the amount sent in. In the worst case, it just buffers
- the unwritten data. */
- writeret = Lstream_write (XLSTREAM (DATA_OUTSTREAM(p)), chunkbuf,
- chunklen);
- signal (SIGPIPE, old_sigpipe);
- if (writeret < 0)
- /* This is a real error. Blocking errors are handled
- specially inside of the filedesc stream. */
- report_file_error ("writing to process", list1 (proc));
+ if (chunklen > 0)
+ {
+ int save_errno;
+
+ /* Lstream_write() will never successfully write less than
+ the amount sent in. In the worst case, it just buffers
+ the unwritten data. */
+ writeret = Lstream_write (XLSTREAM (DATA_OUTSTREAM(p)), chunkbuf,
+ chunklen);
+ save_errno = errno;
+ signal (SIGPIPE, old_sigpipe);
+ errno = save_errno;
+ if (writeret < 0)
+ /* This is a real error. Blocking errors are handled
+ specially inside of the filedesc stream. */
+ report_file_error ("writing to process", list1 (proc));
+ }
+ else
+ {
+ /* Need to make sure that everything up to and including the
+ last chunk is flushed, even when the pipe is currently
+ blocked. */
+ Lstream_flush (XLSTREAM (DATA_OUTSTREAM(p)));
+ signal (SIGPIPE, old_sigpipe);
+ }
while (Lstream_was_blocked_p (XLSTREAM (p->pipe_outstream)))
{
/* Buffer is full. Wait, accepting input;
Lstream_flush (XLSTREAM (p->pipe_outstream));
signal (SIGPIPE, old_sigpipe);
}
+ /* Perhaps should abort() if < 0? This should never happen. */
}
+ while (chunklen > 0);
}
else
{ /* We got here from a longjmp() from the SIGPIPE handler */
/* #### There is controversy over whether this might cause fd leakage */
/* my tests say no. -slb */
XLSTREAM (p->pipe_outstream)->flags &= ~LSTREAM_FL_IS_OPEN;
+#ifdef FILE_CODING
+ XLSTREAM (p->coding_outstream)->flags &= ~LSTREAM_FL_IS_OPEN;
+#endif
p->status_symbol = Qexit;
p->exit_code = 256; /* #### SIGPIPE ??? */
p->core_dumped = 0;
try_to_initialize_subtty (struct unix_process_data *upd)
{
if (upd->pty_flag
- && (upd->subtty = -1 || ! isatty (upd->subtty))
+ && (upd->subtty == -1 || ! isatty (upd->subtty))
&& STRINGP (upd->tty_name))
- upd->subtty = open (XSTRING_DATA (upd->tty_name), O_RDWR, 0);
+ upd->subtty = open ((char *) XSTRING_DATA (upd->tty_name), O_RDWR, 0);
}
/* Send signal number SIGNO to PROCESS.
ioctl TIOCGPGRP it is supposed to obsolete. Sometimes we have to
use TIOCGPGRP on the master end, sometimes the slave end
(probably an AIX bug). So we better get a fd for the slave if we
- haven't got it yet. On some systems none of these work, so then
- we just fall back to the non-current_group behavior and kill the
- process group of the child. */
+ haven't got it yet.
+
+ Anal operating systems like SGI Irix and Compaq Tru64 adhere
+ strictly to the letter of the law, so our hack doesn't work.
+ The following fragment from an Irix header file is suggestive:
+
+ #ifdef __notdef__
+ // this is not currently supported
+ #define TIOCSIGNAL (tIOC|31) // pty: send signal to slave
+ #endif
+
+ On those systems where none of our tricks work, we just fall back
+ to the non-current_group behavior and kill the process group of
+ the child.
+ */
if (current_group)
{
try_to_initialize_subtty (d);
/* Finally send the signal. */
if (EMACS_KILLPG (pgid, signo) == -1)
- error ("kill (%ld, %ld) failed: %s",
- (long) pgid, (long) signo, strerror (errno));
+ {
+ /* It's not an error if our victim is already dead.
+ And we can't rely on the result of killing a zombie, since
+ XPG 4.2 requires that killing a zombie fail with ESRCH,
+ while FIPS 151-2 requires that it succeeds! */
+#ifdef ESRCH
+ if (errno != ESRCH)
+#endif
+ error ("kill (%ld, %ld) failed: %s",
+ (long) pgid, (long) signo, strerror (errno));
+ }
}
/* Send signal SIGCODE to any process in the system given its PID.
xzero (hints);
hints.ai_flags = AI_CANONNAME;
+#ifdef IPV6_CANONICALIZE
hints.ai_family = AF_UNSPEC;
+#else
+ hints.ai_family = PF_INET;
+#endif
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
LISP_STRING_TO_EXTERNAL (host, ext_host, Qnative);
volatile int xerrno = 0;
volatile int failed_connect = 0;
char *ext_host;
+ char portbuf[sizeof(long)*3 + 2];
/*
* Caution: service can either be a string or int.
* Convert to a C string for later use by getaddrinfo.
*/
if (INTP (service))
{
- char portbuf[128];
snprintf (portbuf, sizeof (portbuf), "%ld", (long) XINT (service));
portstring = portbuf;
port = htons ((unsigned short) XINT (service));
failed_connect = 1;
close (s);
+ s = -1;
speed_up_interrupts ();
memset (&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = theport;
- sa.sin_addr.s_addr = htonl (inet_addr ((char *) XSTRING_DATA (dest)));
+ sa.sin_addr.s_addr = inet_addr ((char *) XSTRING_DATA (dest));
/* Socket configuration for reading ------------------------ */
}
/* join multicast group */
- imr.imr_multiaddr.s_addr = htonl (inet_addr ((char *) XSTRING_DATA (dest)));
+ imr.imr_multiaddr.s_addr = inet_addr ((char *) XSTRING_DATA (dest));
imr.imr_interface.s_addr = htonl (INADDR_ANY);
if (setsockopt (rs, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&imr, sizeof (struct ip_mreq)) < 0)