ser-pipe.c revision 98944
174462Salfred/* Serial interface for a pipe to a separate program
274462Salfred   Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
3261046Smav
4261046Smav   Contributed by Cygnus Solutions.
5261046Smav
6261046Smav   This file is part of GDB.
7261046Smav
8261046Smav   This program is free software; you can redistribute it and/or modify
9261046Smav   it under the terms of the GNU General Public License as published by
10261046Smav   the Free Software Foundation; either version 2 of the License, or
11261046Smav   (at your option) any later version.
12261046Smav
13261046Smav   This program is distributed in the hope that it will be useful,
14261046Smav   but WITHOUT ANY WARRANTY; without even the implied warranty of
15261046Smav   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16261046Smav   GNU General Public License for more details.
1774462Salfred
18261046Smav   You should have received a copy of the GNU General Public License
19261046Smav   along with this program; if not, write to the Free Software
20261046Smav   Foundation, Inc., 59 Temple Place - Suite 330,
21261046Smav   Boston, MA 02111-1307, USA.  */
22261046Smav
23261046Smav#include "defs.h"
24261046Smav#include "serial.h"
25261046Smav#include "ser-unix.h"
26261046Smav
27261046Smav#include "gdb_vfork.h"
28261046Smav
2974462Salfred#include <sys/types.h>
3074462Salfred#include <sys/socket.h>
3174462Salfred#include <sys/time.h>
3274462Salfred#include <fcntl.h>
3374462Salfred#include "gdb_string.h"
3474462Salfred
3574462Salfred#include <signal.h>
3674462Salfred
3774462Salfredstatic int pipe_open (struct serial *scb, const char *name);
3874462Salfredstatic void pipe_close (struct serial *scb);
3974462Salfred
40136581Sobrienextern void _initialize_ser_pipe (void);
4174462Salfred
4274462Salfredstruct pipe_state
4392990Sobrien  {
4492990Sobrien    int pid;
4574462Salfred  };
4674462Salfred
4774462Salfred/* Open up a raw pipe */
4874462Salfred
4974462Salfredstatic int
5074462Salfredpipe_open (struct serial *scb, const char *name)
5174462Salfred{
5274462Salfred#if !HAVE_SOCKETPAIR
5374462Salfred  return -1;
5474462Salfred#else
5574462Salfred  struct pipe_state *state;
5675094Siedowse  /* This chunk: */
5774462Salfred  /* Copyright (c) 1988, 1993
5874462Salfred   *      The Regents of the University of California.  All rights reserved.
5974462Salfred   *
6074462Salfred   * This code is derived from software written by Ken Arnold and
6174462Salfred   * published in UNIX Review, Vol. 6, No. 8.
6274462Salfred   */
6374462Salfred  int pdes[2];
6474462Salfred  int pid;
6574462Salfred  if (socketpair (AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
6674462Salfred    return -1;
6774462Salfred
6874462Salfred  /* Create the child process to run the command in.  Note that the
6974462Salfred     apparent call to vfork() below *might* actually be a call to
7074462Salfred     fork() due to the fact that autoconf will ``#define vfork fork''
7174462Salfred     on certain platforms.  */
7274462Salfred  pid = vfork ();
7374462Salfred
7474462Salfred  /* Error. */
7574462Salfred  if (pid == -1)
76156090Sdeischen    {
7774462Salfred      close (pdes[0]);
7892941Sobrien      close (pdes[1]);
7992941Sobrien      return -1;
8092905Sobrien    }
8192905Sobrien
8274462Salfred  /* Child. */
8374462Salfred  if (pid == 0)
8474462Salfred    {
8574462Salfred      /* re-wire pdes[1] to stdin/stdout */
8674462Salfred      close (pdes[0]);
8774462Salfred      if (pdes[1] != STDOUT_FILENO)
8874462Salfred	{
8974462Salfred	  dup2 (pdes[1], STDOUT_FILENO);
9074462Salfred	  close (pdes[1]);
91309489Sngie	}
92309489Sngie      dup2 (STDOUT_FILENO, STDIN_FILENO);
9374462Salfred#if 0
9474462Salfred      /* close any stray FD's - FIXME - how? */
9574462Salfred      /* POSIX.2 B.3.2.2 "popen() shall ensure that any streams
9674462Salfred         from previous popen() calls that remain open in the
9774462Salfred         parent process are closed in the new child process. */
9874462Salfred      for (old = pidlist; old; old = old->next)
9974462Salfred	close (fileno (old->fp));	/* don't allow a flush */
10074462Salfred#endif
10174462Salfred      execl ("/bin/sh", "sh", "-c", name, NULL);
10274462Salfred      _exit (127);
10374462Salfred    }
10474462Salfred
10574462Salfred  /* Parent. */
10674462Salfred  close (pdes[1]);
10774462Salfred  /* :end chunk */
10874462Salfred  state = XMALLOC (struct pipe_state);
10974462Salfred  state->pid = pid;
11074462Salfred  scb->fd = pdes[0];
11174462Salfred  scb->state = state;
11274462Salfred
11374462Salfred  /* If we don't do this, GDB simply exits when the remote side dies.  */
11474462Salfred  signal (SIGPIPE, SIG_IGN);
11574462Salfred  return 0;
11674462Salfred#endif
11774462Salfred}
11874462Salfred
11974462Salfredstatic void
12074462Salfredpipe_close (struct serial *scb)
12174462Salfred{
12274462Salfred  struct pipe_state *state = scb->state;
12374462Salfred  if (state != NULL)
12474462Salfred    {
12574462Salfred      int pid = state->pid;
12674462Salfred      close (scb->fd);
12774462Salfred      scb->fd = -1;
12874462Salfred      xfree (state);
12974462Salfred      scb->state = NULL;
13074462Salfred      kill (pid, SIGTERM);
13174462Salfred      /* Might be useful to check that the child does die. */
13274462Salfred    }
13374462Salfred}
13474462Salfred
13574462Salfredstatic struct serial_ops pipe_ops;
13674462Salfred
13774462Salfredvoid
13874462Salfred_initialize_ser_pipe (void)
13974462Salfred{
14074462Salfred  struct serial_ops *ops = XMALLOC (struct serial_ops);
14174462Salfred  memset (ops, sizeof (struct serial_ops), 0);
14274462Salfred  ops->name = "pipe";
14374462Salfred  ops->next = 0;
14474462Salfred  ops->open = pipe_open;
14574462Salfred  ops->close = pipe_close;
14674462Salfred  ops->readchar = ser_unix_readchar;
14774462Salfred  ops->write = ser_unix_write;
14874462Salfred  ops->flush_output = ser_unix_nop_flush_output;
14974462Salfred  ops->flush_input = ser_unix_flush_input;
15074462Salfred  ops->send_break = ser_unix_nop_send_break;
15174462Salfred  ops->go_raw = ser_unix_nop_raw;
15274462Salfred  ops->get_tty_state = ser_unix_nop_get_tty_state;
15374462Salfred  ops->set_tty_state = ser_unix_nop_set_tty_state;
15474462Salfred  ops->print_tty_state = ser_unix_nop_print_tty_state;
15574462Salfred  ops->noflush_set_tty_state = ser_unix_nop_noflush_set_tty_state;
15674462Salfred  ops->setbaudrate = ser_unix_nop_setbaudrate;
15774462Salfred  ops->setstopbits = ser_unix_nop_setstopbits;
15874462Salfred  ops->drain_output = ser_unix_nop_drain_output;
15974462Salfred  ops->async = ser_unix_async;
16074462Salfred  serial_add_interface (ops);
161309489Sngie}
162309489Sngie