Ticket #1395 (Copying to fish is broken)
[midnight-commander.git] / vfs / mcfsutil.c
blob959d4b5e8bb0527ccafca5be85d3153dd8e25e46
1 /* Low-level protocol for MCFS.
3 Copyright (C) 1995, 1996 Miguel de Icaza
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License
7 as published by the Free Software Foundation; either version 2 of
8 the License, or (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 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 /**
20 * \file
21 * \brief Source: Low-level protocol for MCFS
22 * \author Miguel de Icaza
23 * \date 1995, 1996
26 #include <config.h>
28 #ifdef ENABLE_VFS_MCFS
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33 #include <signal.h>
34 #include <pwd.h>
35 #include <sys/types.h>
36 #include <netdb.h>
37 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #ifdef HAVE_ARPA_INET_H
40 #include <arpa/inet.h>
41 #endif
43 #ifdef HAVE_PMAP_SET
44 #include <rpc/rpc.h>
45 #include <rpc/pmap_prot.h>
46 #ifdef HAVE_RPC_PMAP_CLNT_H
47 #include <rpc/pmap_clnt.h>
48 #endif
49 #endif
51 #include <errno.h>
53 #include "../src/global.h"
54 #include "../src/tty.h" /* enable/disable interrupt key */
55 #include "../src/wtools.h" /* message() */
56 #include "../src/main.h" /* print_vfs_message */
57 #include "utilvfs.h"
58 #include "mcfsutil.h"
59 #include "tcputil.h"
60 #include "mcfs.h" /* tcp_invalidate_socket() */
62 #define CHECK_SIG_PIPE(sock) if (got_sigpipe) \
63 { tcp_invalidate_socket (sock); return got_sigpipe = 0; }
65 /* Reads a block on dest for len bytes from sock */
66 /* Returns a boolean indicating the success status */
67 int
68 socket_read_block (int sock, char *dest, int len)
70 int nread, n;
72 for (nread = 0; nread < len;) {
73 n = read (sock, dest + nread, len - nread);
74 if (n <= 0) {
75 tcp_invalidate_socket (sock);
76 return 0;
78 nread += n;
80 return 1;
83 int
84 socket_write_block (int sock, const char *buffer, int len)
86 int left, status;
88 for (left = len; left > 0;) {
89 status = write (sock, buffer, left);
90 CHECK_SIG_PIPE (sock);
91 if (status < 0)
92 return 0;
93 left -= status;
94 buffer += status;
96 return 1;
99 int
100 rpc_send (int sock, ...)
102 long int tmp, len, cmd;
103 char *text;
104 va_list ap;
106 va_start (ap, sock);
108 for (;;) {
109 cmd = va_arg (ap, int);
110 switch (cmd) {
111 case RPC_END:
112 va_end (ap);
113 return 1;
115 case RPC_INT:
116 tmp = htonl (va_arg (ap, int));
117 write (sock, &tmp, sizeof (tmp));
118 CHECK_SIG_PIPE (sock);
119 break;
121 case RPC_STRING:
122 text = va_arg (ap, char *);
123 len = strlen (text);
124 tmp = htonl (len);
125 write (sock, &tmp, sizeof (tmp));
126 CHECK_SIG_PIPE (sock);
127 write (sock, text, len);
128 CHECK_SIG_PIPE (sock);
129 break;
131 case RPC_BLOCK:
132 len = va_arg (ap, int);
133 text = va_arg (ap, char *);
134 tmp = htonl (len);
135 write (sock, text, len);
136 CHECK_SIG_PIPE (sock);
137 break;
139 default:
140 vfs_die ("Unknown rpc message\n");
146 rpc_get (int sock, ...)
148 long int tmp, len;
149 char *text, **str_dest;
150 int *dest, cmd;
151 va_list ap;
153 va_start (ap, sock);
155 for (;;) {
156 cmd = va_arg (ap, int);
157 switch (cmd) {
158 case RPC_END:
159 va_end (ap);
160 return 1;
162 case RPC_INT:
163 if (socket_read_block (sock, (char *) &tmp, sizeof (tmp)) == 0) {
164 va_end (ap);
165 return 0;
167 dest = va_arg (ap, int *);
168 *dest = ntohl (tmp);
169 break;
171 /* returns an allocated string */
172 case RPC_LIMITED_STRING:
173 case RPC_STRING:
174 if (socket_read_block (sock, (char *) &tmp, sizeof (tmp)) == 0) {
175 va_end (ap);
176 return 0;
178 len = ntohl (tmp);
179 if (cmd == RPC_LIMITED_STRING)
180 if (len > 16 * 1024) {
181 /* silently die */
182 abort ();
184 if (len > 128 * 1024)
185 abort ();
187 /* Don't use glib functions here - this code is used by mcserv */
188 text = malloc (len + 1);
189 if (socket_read_block (sock, text, len) == 0) {
190 free (text);
191 va_end (ap);
192 return 0;
194 text[len] = '\0';
196 str_dest = va_arg (ap, char **);
197 *str_dest = text;
198 break;
200 case RPC_BLOCK:
201 len = va_arg (ap, int);
202 text = va_arg (ap, char *);
203 if (socket_read_block (sock, text, len) == 0) {
204 va_end (ap);
205 return 0;
207 break;
209 default:
210 vfs_die ("Unknown rpc message\n");
214 #else
215 void mcfsutil__unused(void)
218 CFLAGS="-ansi -pedantic -Wall -Wextra -Werror"
221 #endif /* ENABLE_VFS_MCFS */