| /* Serial interface for local domain connections on Un*x like systems. | 
 |  | 
 |    Copyright (C) 1992-2022 Free Software Foundation, Inc. | 
 |  | 
 |    This file is part of GDB. | 
 |  | 
 |    This program is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3 of the License, or | 
 |    (at your option) any later version. | 
 |  | 
 |    This program 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 General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #include "defs.h" | 
 | #include "serial.h" | 
 | #include "ser-base.h" | 
 |  | 
 | #include <sys/socket.h> | 
 | #include <sys/un.h> | 
 |  | 
 | #ifndef UNIX_PATH_MAX | 
 | #define UNIX_PATH_MAX sizeof(((struct sockaddr_un *) NULL)->sun_path) | 
 | #endif | 
 |  | 
 | /* Open an AF_UNIX socket.  */ | 
 |  | 
 | static int | 
 | uds_open (struct serial *scb, const char *name) | 
 | { | 
 |   struct sockaddr_un addr; | 
 |  | 
 |   if (strlen (name) > UNIX_PATH_MAX - 1) | 
 |     { | 
 |       warning | 
 | 	(_("The socket name is too long.  It may be no longer than %s bytes."), | 
 | 	 pulongest (UNIX_PATH_MAX - 1L)); | 
 |       return -1; | 
 |     } | 
 |  | 
 |   memset (&addr, 0, sizeof addr); | 
 |   addr.sun_family = AF_UNIX; | 
 |   strncpy (addr.sun_path, name, UNIX_PATH_MAX - 1); | 
 |  | 
 |   int sock = socket (AF_UNIX, SOCK_STREAM, 0); | 
 |  | 
 |   if (connect (sock, (struct sockaddr *) &addr, | 
 | 	       sizeof (struct sockaddr_un)) < 0) | 
 |     { | 
 |       close (sock); | 
 |       scb->fd = -1; | 
 |       return -1; | 
 |     } | 
 |  | 
 |   scb->fd = sock; | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | static void | 
 | uds_close (struct serial *scb) | 
 | { | 
 |   if (scb->fd == -1) | 
 |     return; | 
 |  | 
 |   close (scb->fd); | 
 |   scb->fd = -1; | 
 | } | 
 |  | 
 | static int | 
 | uds_read_prim (struct serial *scb, size_t count) | 
 | { | 
 |   return recv (scb->fd, scb->buf, count, 0); | 
 | } | 
 |  | 
 | static int | 
 | uds_write_prim (struct serial *scb, const void *buf, size_t count) | 
 | { | 
 |   return send (scb->fd, buf, count, 0); | 
 | } | 
 |  | 
 | /* The local socket ops.  */ | 
 |  | 
 | static const struct serial_ops uds_ops = | 
 | { | 
 |   "local", | 
 |   uds_open, | 
 |   uds_close, | 
 |   NULL, | 
 |   ser_base_readchar, | 
 |   ser_base_write, | 
 |   ser_base_flush_output, | 
 |   ser_base_flush_input, | 
 |   ser_base_send_break, | 
 |   ser_base_raw, | 
 |   ser_base_get_tty_state, | 
 |   ser_base_copy_tty_state, | 
 |   ser_base_set_tty_state, | 
 |   ser_base_print_tty_state, | 
 |   ser_base_setbaudrate, | 
 |   ser_base_setstopbits, | 
 |   ser_base_setparity, | 
 |   ser_base_drain_output, | 
 |   ser_base_async, | 
 |   uds_read_prim, | 
 |   uds_write_prim | 
 | }; | 
 |  | 
 | void _initialize_ser_socket (); | 
 | void | 
 | _initialize_ser_socket () | 
 | { | 
 |   serial_add_interface (&uds_ops); | 
 | } |