198944Sobrien/* Serial interface for a pipe to a separate program
298944Sobrien   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
398944Sobrien
498944Sobrien   Contributed by Cygnus Solutions.
598944Sobrien
698944Sobrien   This file is part of GDB.
798944Sobrien
898944Sobrien   This program is free software; you can redistribute it and/or modify
998944Sobrien   it under the terms of the GNU General Public License as published by
1098944Sobrien   the Free Software Foundation; either version 2 of the License, or
1198944Sobrien   (at your option) any later version.
1298944Sobrien
1398944Sobrien   This program is distributed in the hope that it will be useful,
1498944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1598944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1698944Sobrien   GNU General Public License for more details.
1798944Sobrien
1898944Sobrien   You should have received a copy of the GNU General Public License
1998944Sobrien   along with this program; if not, write to the Free Software
2098944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2198944Sobrien   Boston, MA 02111-1307, USA.  */
2298944Sobrien
2398944Sobrien#include "defs.h"
2498944Sobrien#include "serial.h"
2598944Sobrien#include "ser-unix.h"
2698944Sobrien
2798944Sobrien#include "gdb_vfork.h"
2898944Sobrien
2998944Sobrien#include <sys/types.h>
3098944Sobrien#include <sys/socket.h>
3198944Sobrien#include <sys/time.h>
3298944Sobrien#include <fcntl.h>
3398944Sobrien#include "gdb_string.h"
3498944Sobrien
3598944Sobrien#include <signal.h>
3698944Sobrien
3798944Sobrienstatic int pipe_open (struct serial *scb, const char *name);
3898944Sobrienstatic void pipe_close (struct serial *scb);
3998944Sobrien
4098944Sobrienextern void _initialize_ser_pipe (void);
4198944Sobrien
4298944Sobrienstruct pipe_state
4398944Sobrien  {
4498944Sobrien    int pid;
4598944Sobrien  };
4698944Sobrien
4798944Sobrien/* Open up a raw pipe */
4898944Sobrien
4998944Sobrienstatic int
5098944Sobrienpipe_open (struct serial *scb, const char *name)
5198944Sobrien{
5298944Sobrien#if !HAVE_SOCKETPAIR
5398944Sobrien  return -1;
5498944Sobrien#else
5598944Sobrien  struct pipe_state *state;
5698944Sobrien  /* This chunk: */
5798944Sobrien  /* Copyright (c) 1988, 1993
5898944Sobrien   *      The Regents of the University of California.  All rights reserved.
5998944Sobrien   *
6098944Sobrien   * This code is derived from software written by Ken Arnold and
6198944Sobrien   * published in UNIX Review, Vol. 6, No. 8.
6298944Sobrien   */
6398944Sobrien  int pdes[2];
6498944Sobrien  int pid;
6598944Sobrien  if (socketpair (AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
6698944Sobrien    return -1;
6798944Sobrien
6898944Sobrien  /* Create the child process to run the command in.  Note that the
6998944Sobrien     apparent call to vfork() below *might* actually be a call to
7098944Sobrien     fork() due to the fact that autoconf will ``#define vfork fork''
7198944Sobrien     on certain platforms.  */
7298944Sobrien  pid = vfork ();
7398944Sobrien
7498944Sobrien  /* Error. */
7598944Sobrien  if (pid == -1)
7698944Sobrien    {
7798944Sobrien      close (pdes[0]);
7898944Sobrien      close (pdes[1]);
7998944Sobrien      return -1;
8098944Sobrien    }
8198944Sobrien
8298944Sobrien  /* Child. */
8398944Sobrien  if (pid == 0)
8498944Sobrien    {
8598944Sobrien      /* re-wire pdes[1] to stdin/stdout */
8698944Sobrien      close (pdes[0]);
8798944Sobrien      if (pdes[1] != STDOUT_FILENO)
8898944Sobrien	{
8998944Sobrien	  dup2 (pdes[1], STDOUT_FILENO);
9098944Sobrien	  close (pdes[1]);
9198944Sobrien	}
9298944Sobrien      dup2 (STDOUT_FILENO, STDIN_FILENO);
9398944Sobrien#if 0
9498944Sobrien      /* close any stray FD's - FIXME - how? */
9598944Sobrien      /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams
9698944Sobrien         from previous popen() calls that remain open in the
9798944Sobrien         parent process are closed in the new child process. */
9898944Sobrien      for (old = pidlist; old; old = old->next)
9998944Sobrien	close (fileno (old->fp));	/* don't allow a flush */
10098944Sobrien#endif
101130803Smarcel      execl ("/bin/sh", "sh", "-c", name, (char *) 0);
10298944Sobrien      _exit (127);
10398944Sobrien    }
10498944Sobrien
10598944Sobrien  /* Parent. */
10698944Sobrien  close (pdes[1]);
10798944Sobrien  /* :end chunk */
10898944Sobrien  state = XMALLOC (struct pipe_state);
10998944Sobrien  state->pid = pid;
11098944Sobrien  scb->fd = pdes[0];
11198944Sobrien  scb->state = state;
11298944Sobrien
11398944Sobrien  /* If we don't do this, GDB simply exits when the remote side dies.  */
11498944Sobrien  signal (SIGPIPE, SIG_IGN);
11598944Sobrien  return 0;
11698944Sobrien#endif
11798944Sobrien}
11898944Sobrien
11998944Sobrienstatic void
12098944Sobrienpipe_close (struct serial *scb)
12198944Sobrien{
12298944Sobrien  struct pipe_state *state = scb->state;
12398944Sobrien  if (state != NULL)
12498944Sobrien    {
12598944Sobrien      int pid = state->pid;
12698944Sobrien      close (scb->fd);
12798944Sobrien      scb->fd = -1;
12898944Sobrien      xfree (state);
12998944Sobrien      scb->state = NULL;
13098944Sobrien      kill (pid, SIGTERM);
13198944Sobrien      /* Might be useful to check that the child does die. */
13298944Sobrien    }
13398944Sobrien}
13498944Sobrien
13598944Sobrienstatic struct serial_ops pipe_ops;
13698944Sobrien
13798944Sobrienvoid
13898944Sobrien_initialize_ser_pipe (void)
13998944Sobrien{
14098944Sobrien  struct serial_ops *ops = XMALLOC (struct serial_ops);
141130803Smarcel  memset (ops, 0, sizeof (struct serial_ops));
14298944Sobrien  ops->name = "pipe";
14398944Sobrien  ops->next = 0;
14498944Sobrien  ops->open = pipe_open;
14598944Sobrien  ops->close = pipe_close;
14698944Sobrien  ops->readchar = ser_unix_readchar;
14798944Sobrien  ops->write = ser_unix_write;
14898944Sobrien  ops->flush_output = ser_unix_nop_flush_output;
14998944Sobrien  ops->flush_input = ser_unix_flush_input;
15098944Sobrien  ops->send_break = ser_unix_nop_send_break;
15198944Sobrien  ops->go_raw = ser_unix_nop_raw;
15298944Sobrien  ops->get_tty_state = ser_unix_nop_get_tty_state;
15398944Sobrien  ops->set_tty_state = ser_unix_nop_set_tty_state;
15498944Sobrien  ops->print_tty_state = ser_unix_nop_print_tty_state;
15598944Sobrien  ops->noflush_set_tty_state = ser_unix_nop_noflush_set_tty_state;
15698944Sobrien  ops->setbaudrate = ser_unix_nop_setbaudrate;
15798944Sobrien  ops->setstopbits = ser_unix_nop_setstopbits;
15898944Sobrien  ops->drain_output = ser_unix_nop_drain_output;
15998944Sobrien  ops->async = ser_unix_async;
16098944Sobrien  serial_add_interface (ops);
16198944Sobrien}
162