1 /* Server for the Midnight Commander Virtual File System.
2 Routines for the tcp connection, includes the primitive rpc routines.
4 Copyright (C) 1995, 1996 Miguel de Icaza
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License
8 as published by the Free Software Foundation; either version 2 of
9 the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
27 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
35 #include <rpc/pmap_prot.h>
36 #ifdef HAVE_RPC_PMAP_CLNT_H
37 #include <rpc/pmap_clnt.h>
47 #include "../src/dialog.h" /* for message () */
51 #include "mcfs.h" /* for mcserver_port definition */
53 #define CHECK_SIG_PIPE(sock) if (got_sigpipe) \
54 { tcp_invalidate_socket (sock); return got_sigpipe = 0; }
56 extern void tcp_invalidate_socket (int);
57 extern void vfs_die (char *);
61 /* Reads a block on dest for len bytes from sock */
62 /* Returns a boolean indicating the success status */
63 int socket_read_block (int sock
, char *dest
, int len
)
67 for (nread
= 0; nread
< len
;){
68 n
= read (sock
, dest
+nread
, len
-nread
);
70 tcp_invalidate_socket (sock
);
78 int socket_write_block (int sock
, char *buffer
, int len
)
82 for (left
= len
; left
> 0;){
83 status
= write (sock
, buffer
, left
);
84 CHECK_SIG_PIPE (sock
);
93 int send_string (int sock
, char *string
)
95 return socket_write_block (sock
, string
, strlen (string
));
98 int rpc_send (int sock
, ...)
100 long int tmp
, len
, cmd
;
107 cmd
= va_arg (ap
, int);
114 tmp
= htonl (va_arg (ap
, int));
115 write (sock
, &tmp
, sizeof (tmp
));
116 CHECK_SIG_PIPE (sock
);
120 text
= va_arg (ap
, char *);
123 write (sock
, &tmp
, sizeof (tmp
));
124 CHECK_SIG_PIPE (sock
);
125 write (sock
, text
, len
);
126 CHECK_SIG_PIPE (sock
);
130 len
= va_arg (ap
, int);
131 text
= va_arg (ap
, char *);
133 write (sock
, text
, len
);
134 CHECK_SIG_PIPE (sock
);
138 vfs_die ("Unknown rpc message\n");
143 typedef struct sock_callback_t
{
146 struct sock_callback_t
*link
;
149 sock_callback_t
*sock_callbacks
= 0;
151 static void check_hooks (int sock
)
153 sock_callback_t
*callback
, *prev
;
155 for (prev
=callback
= sock_callbacks
; callback
; callback
= callback
->link
){
156 if (callback
->sock
!= sock
){
161 (callback
->cback
)(sock
);
162 if (callback
== sock_callbacks
){
163 sock_callbacks
= callback
->link
;
165 prev
->link
= callback
->link
;
172 int rpc_get (int sock
, ...)
175 char *text
, **str_dest
;
184 cmd
= va_arg (ap
, int);
191 if (socket_read_block (sock
, (char *) &tmp
, sizeof (tmp
)) == 0)
193 dest
= va_arg (ap
, int *);
197 /* returns an allocated string */
198 case RPC_LIMITED_STRING
:
200 if (socket_read_block (sock
, (char *)&tmp
, sizeof (tmp
)) == 0)
203 if (cmd
== RPC_LIMITED_STRING
)
210 text
= g_new0 (char, len
+1);
211 if (socket_read_block (sock
, text
, len
) == 0)
213 str_dest
= va_arg (ap
, char **);
219 len
= va_arg (ap
, int);
220 text
= va_arg (ap
, char *);
221 if (socket_read_block (sock
, text
, len
) == 0)
226 vfs_die ("Unknown rpc message\n");
231 void rpc_add_get_callback (int sock
, void (*cback
)(int))
233 sock_callback_t
*new;
235 new = g_new (sock_callback_t
, 1);
238 new->link
= sock_callbacks
;
239 sock_callbacks
= new;
242 #if defined(IS_AIX) || defined(linux) || defined(SCO_FLAVOR) \
243 || defined(__QNX__) || defined(__FreeBSD__) || defined(__bsdi__)
244 static void sig_pipe (int unused
)
246 static void sig_pipe (void)
257 sa
.sa_handler
= sig_pipe
;
259 sigemptyset (&sa
.sa_mask
);
260 sigaction (SIGPIPE
, &sa
, NULL
);
263 int get_remote_port (struct sockaddr_in
*sin
, int *version
)
265 #ifdef HAVE_PMAP_GETMAPS
270 port
= mcserver_port
;
271 for (pl
= pmap_getmaps (sin
); pl
; pl
= pl
->pml_next
)
272 if (pl
->pml_map
.pm_prog
== RPC_PROGNUM
&&
273 pl
->pml_map
.pm_prot
== IPPROTO_TCP
&&
274 pl
->pml_map
.pm_vers
>= *version
) {
275 *version
= pl
->pml_map
.pm_vers
;
276 port
= pl
->pml_map
.pm_port
;
280 #ifdef HAVE_PMAP_GETPORT
282 for (*version
= RPC_PROGVER
; *version
>= 1; (*version
)--)
283 if (port
= pmap_getport (sin
, RPC_PROGNUM
, *version
, IPPROTO_TCP
))
285 #endif /* HAVE_PMAP_GETPORT */
286 #endif /* HAVE_PMAP_GETMAPS */
288 return mcserver_port
;