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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
27 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #ifdef HAVE_ARPA_INET_H
32 #include <arpa/inet.h>
37 #include <rpc/pmap_prot.h>
38 #ifdef HAVE_RPC_PMAP_CLNT_H
39 #include <rpc/pmap_clnt.h>
45 #include "../src/dialog.h" /* for message () */
49 #include "mcfs.h" /* for mcserver_port definition */
51 #define CHECK_SIG_PIPE(sock) if (got_sigpipe) \
52 { tcp_invalidate_socket (sock); return got_sigpipe = 0; }
54 extern void tcp_invalidate_socket (int);
55 extern void vfs_die (char *);
60 /* Reads a block on dest for len bytes from sock */
61 /* Returns a boolean indicating the success status */
62 int socket_read_block (int sock
, char *dest
, int len
)
66 for (nread
= 0; nread
< len
;){
67 n
= read (sock
, dest
+nread
, len
-nread
);
69 tcp_invalidate_socket (sock
);
77 int socket_write_block (int sock
, char *buffer
, int len
)
81 for (left
= len
; left
> 0;){
82 status
= write (sock
, buffer
, left
);
83 CHECK_SIG_PIPE (sock
);
92 int send_string (int sock
, char *string
)
94 return socket_write_block (sock
, string
, strlen (string
));
97 int rpc_send (int sock
, ...)
99 long int tmp
, len
, cmd
;
106 cmd
= va_arg (ap
, int);
113 tmp
= htonl (va_arg (ap
, int));
114 write (sock
, &tmp
, sizeof (tmp
));
115 CHECK_SIG_PIPE (sock
);
119 text
= va_arg (ap
, char *);
122 write (sock
, &tmp
, sizeof (tmp
));
123 CHECK_SIG_PIPE (sock
);
124 write (sock
, text
, len
);
125 CHECK_SIG_PIPE (sock
);
129 len
= va_arg (ap
, int);
130 text
= va_arg (ap
, char *);
132 write (sock
, text
, len
);
133 CHECK_SIG_PIPE (sock
);
137 vfs_die ("Unknown rpc message\n");
142 typedef struct sock_callback_t
{
145 struct sock_callback_t
*link
;
148 sock_callback_t
*sock_callbacks
= 0;
150 static void check_hooks (int sock
)
152 sock_callback_t
*callback
, *prev
;
154 for (prev
=callback
= sock_callbacks
; callback
; callback
= callback
->link
){
155 if (callback
->sock
!= sock
){
160 (callback
->cback
)(sock
);
161 if (callback
== sock_callbacks
){
162 sock_callbacks
= callback
->link
;
164 prev
->link
= callback
->link
;
171 int rpc_get (int sock
, ...)
174 char *text
, **str_dest
;
183 cmd
= va_arg (ap
, int);
190 if (socket_read_block (sock
, (char *) &tmp
, sizeof (tmp
)) == 0){
194 dest
= va_arg (ap
, int *);
198 /* returns an allocated string */
199 case RPC_LIMITED_STRING
:
201 if (socket_read_block (sock
, (char *)&tmp
, sizeof (tmp
)) == 0){
206 if (cmd
== RPC_LIMITED_STRING
)
213 text
= g_new0 (char, len
+1);
214 if (socket_read_block (sock
, text
, len
) == 0){
219 str_dest
= va_arg (ap
, char **);
225 len
= va_arg (ap
, int);
226 text
= va_arg (ap
, char *);
227 if (socket_read_block (sock
, text
, len
) == 0){
234 vfs_die ("Unknown rpc message\n");
239 void rpc_add_get_callback (int sock
, void (*cback
)(int))
241 sock_callback_t
*new;
243 new = g_new (sock_callback_t
, 1);
246 new->link
= sock_callbacks
;
247 sock_callbacks
= new;
249 #endif /* WITH_MCFS */
251 static void sig_pipe (int unused
)
261 sa
.sa_handler
= sig_pipe
;
263 sigemptyset (&sa
.sa_mask
);
264 sigaction (SIGPIPE
, &sa
, NULL
);
268 int get_remote_port (struct sockaddr_in
*sin
, int *version
)
270 #ifdef HAVE_PMAP_GETMAPS
275 port
= mcserver_port
;
276 for (pl
= pmap_getmaps (sin
); pl
; pl
= pl
->pml_next
)
277 if (pl
->pml_map
.pm_prog
== RPC_PROGNUM
&&
278 pl
->pml_map
.pm_prot
== IPPROTO_TCP
&&
279 pl
->pml_map
.pm_vers
>= *version
) {
280 *version
= pl
->pml_map
.pm_vers
;
281 port
= pl
->pml_map
.pm_port
;
285 #ifdef HAVE_PMAP_GETPORT
287 for (*version
= RPC_PROGVER
; *version
>= 1; (*version
)--)
288 if (port
= pmap_getport (sin
, RPC_PROGNUM
, *version
, IPPROTO_TCP
))
290 #endif /* HAVE_PMAP_GETPORT */
291 #endif /* HAVE_PMAP_GETMAPS */
293 return mcserver_port
;
295 #endif /* WITH_MCFS */