2 * Copyright (C) 2000 Manoj Kasichainula <manoj@io.com>
3 * Copyright (C) 2001,2005 Brendan Cully <brendan@kublai.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include "mutt_socket.h"
26 #include "mutt_tunnel.h"
28 #include <netinet/in.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
35 /* -- data types -- */
43 /* forward declarations */
44 static int tunnel_socket_open (CONNECTION*);
45 static int tunnel_socket_close (CONNECTION*);
46 static int tunnel_socket_read (CONNECTION* conn, char* buf, size_t len);
47 static int tunnel_socket_write (CONNECTION* conn, const char* buf, size_t len);
48 static int tunnel_socket_poll (CONNECTION* conn);
50 /* -- public functions -- */
51 int mutt_tunnel_socket_setup (CONNECTION *conn)
53 conn->conn_open = tunnel_socket_open;
54 conn->conn_close = tunnel_socket_close;
55 conn->conn_read = tunnel_socket_read;
56 conn->conn_write = tunnel_socket_write;
57 conn->conn_poll = tunnel_socket_poll;
62 static int tunnel_socket_open (CONNECTION *conn)
69 tunnel = (TUNNEL_DATA*) safe_malloc (sizeof (TUNNEL_DATA));
70 conn->sockdata = tunnel;
72 mutt_message (_("Connecting with \"%s\"..."), Tunnel);
74 if ((rc = pipe (pin)) == -1)
79 if ((rc = pipe (pout)) == -1)
85 mutt_block_signals_system ();
86 if ((pid = fork ()) == 0)
88 mutt_unblock_signals_system (0);
89 if (dup2 (pout[0], STDIN_FILENO) < 0 || dup2 (pin[1], STDOUT_FILENO) < 0)
95 close (STDERR_FILENO);
97 /* Don't let the subprocess think it can use the controlling tty */
100 execl (EXECSHELL, "sh", "-c", Tunnel, NULL);
103 mutt_unblock_signals_system (1);
111 mutt_perror ("fork");
114 if (close (pin[1]) < 0 || close (pout[0]) < 0)
115 mutt_perror ("close");
117 fcntl (pin[0], F_SETFD, FD_CLOEXEC);
118 fcntl (pout[1], F_SETFD, FD_CLOEXEC);
120 tunnel->readfd = pin[0];
121 tunnel->writefd = pout[1];
124 conn->fd = 42; /* stupid hack */
129 static int tunnel_socket_close (CONNECTION* conn)
131 TUNNEL_DATA* tunnel = (TUNNEL_DATA*) conn->sockdata;
134 close (tunnel->readfd);
135 close (tunnel->writefd);
136 waitpid (tunnel->pid, &status, 0);
137 if (!WIFEXITED(status) || WEXITSTATUS(status))
139 mutt_error(_("Tunnel to %s returned error %d (%s)"), conn->account.host,
141 NONULL(mutt_strsysexit(WEXITSTATUS(status))));
144 FREE (&conn->sockdata);
149 static int tunnel_socket_read (CONNECTION* conn, char* buf, size_t len)
151 TUNNEL_DATA* tunnel = (TUNNEL_DATA*) conn->sockdata;
154 rc = read (tunnel->readfd, buf, len);
157 mutt_error (_("Tunnel error talking to %s: %s"), conn->account.host,
165 static int tunnel_socket_write (CONNECTION* conn, const char* buf, size_t len)
167 TUNNEL_DATA* tunnel = (TUNNEL_DATA*) conn->sockdata;
170 rc = write (tunnel->writefd, buf, len);
173 mutt_error (_("Tunnel error talking to %s: %s"), conn->account.host,
181 static int tunnel_socket_poll (CONNECTION* conn)
183 TUNNEL_DATA* tunnel = (TUNNEL_DATA*) conn->sockdata;
188 conn->fd = tunnel->readfd;
189 rc = raw_socket_poll (conn);