This commit was manufactured by cvs2svn to create tag 'FreeBSD-release/1.0'.
[unix-history] / gnu / libexec / uucp / uucico / prott.c
CommitLineData
78ed81a3 1/* prott.c
2 The 't' protocol.
3
4 Copyright (C) 1991, 1992 Ian Lance Taylor
5
6 This file is part of the Taylor UUCP package.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 The author of the program may be contacted at ian@airs.com or
23 c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
24 */
25
26#include "uucp.h"
27
28#if USE_RCS_ID
29const char prott_rcsid[] = "$Id: prott.c,v 1.1 1993/08/04 19:36:24 jtc Exp $";
30#endif
31
32#include "uudefs.h"
33#include "uuconf.h"
34#include "conn.h"
35#include "trans.h"
36#include "system.h"
37#include "prot.h"
38\f
39/* This implementation is based on code written by Rick Adams.
40
41 This code implements the 't' protocol, which does no error checking
42 whatsoever and thus requires an end-to-end verified eight bit
43 communication line, such as is provided by TCP. Using it with a
44 modem is unadvisable, since errors can occur between the modem and
45 the computer. */
46\f
47/* The buffer size we use. */
48#define CTBUFSIZE (1024)
49
50/* The offset in the buffer to the data. */
51#define CTFRAMELEN (4)
52
53/* Commands are sent in multiples of this size. */
54#define CTPACKSIZE (512)
55
56/* A pointer to the buffer we will use. */
57static char *zTbuf;
58
59/* True if we are receiving a file. */
60static boolean fTfile;
61
62/* The timeout we use. */
63static int cTtimeout = 120;
64
65struct uuconf_cmdtab asTproto_params[] =
66{
67 { "timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cTtimeout, NULL },
68 { NULL, 0, NULL, NULL }
69};
70
71/* Local function. */
72
73static boolean ftprocess_data P((struct sdaemon *qdaemon, boolean *pfexit,
74 size_t *pcneed));
75\f
76/* Start the protocol. */
77
78boolean
79ftstart (qdaemon, pzlog)
80 struct sdaemon *qdaemon;
81 char **pzlog;
82{
83 *pzlog = NULL;
84 if (! fconn_set (qdaemon->qconn, PARITYSETTING_NONE,
85 STRIPSETTING_EIGHTBITS, XONXOFF_OFF))
86 return FALSE;
87 zTbuf = (char *) xmalloc (CTBUFSIZE + CTFRAMELEN);
88 /* The first two bytes of the buffer are always zero. */
89 zTbuf[0] = 0;
90 zTbuf[1] = 0;
91 fTfile = FALSE;
92 usysdep_sleep (2);
93 return TRUE;
94}
95\f
96/* Stop the protocol. */
97
98/*ARGSUSED*/
99boolean
100ftshutdown (qdaemon)
101 struct sdaemon *qdaemon;
102{
103 xfree ((pointer) zTbuf);
104 zTbuf = NULL;
105 cTtimeout = 120;
106 return TRUE;
107}
108\f
109/* Send a command string. We send everything up to and including the
110 null byte. The number of bytes we send must be a multiple of
111 TPACKSIZE. */
112
113/*ARGSUSED*/
114boolean
115ftsendcmd (qdaemon, z, ilocal, iremote)
116 struct sdaemon *qdaemon;
117 const char *z;
118 int ilocal;
119 int iremote;
120{
121 size_t clen, csend;
122 char *zalc;
123 boolean fret;
124
125 DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO, "ftsendcmd: Sending command \"%s\"", z);
126
127 clen = strlen (z);
128
129 /* We need to send the smallest multiple of CTPACKSIZE which is
130 greater than clen (not equal to clen, since we need room for the
131 null byte). */
132 csend = ((clen / CTPACKSIZE) + 1) * CTPACKSIZE;
133
134 zalc = zbufalc (csend);
135 memcpy (zalc, z, clen);
136 bzero (zalc + clen, csend - clen);
137
138 fret = fsend_data (qdaemon->qconn, zalc, csend, TRUE);
139 ubuffree (zalc);
140 return fret;
141}
142\f
143/* Get space to be filled with data. We provide a buffer which has
144 four bytes at the start available to hold the length. */
145
146/*ARGSIGNORED*/
147char *
148ztgetspace (qdaemon, pclen)
149 struct sdaemon *qdaemon;
150 size_t *pclen;
151{
152 *pclen = CTBUFSIZE;
153 return zTbuf + CTFRAMELEN;
154}
155
156/* Send out some data. We are allowed to modify the four bytes
157 preceding the buffer. This allows us to send the entire block with
158 header bytes in a single call. */
159
160/*ARGSIGNORED*/
161boolean
162ftsenddata (qdaemon, zdata, cdata, ilocal, iremote, ipos)
163 struct sdaemon *qdaemon;
164 char *zdata;
165 size_t cdata;
166 int ilocal;
167 int iremote;
168 long ipos;
169{
170 /* Here we do htonl by hand, since it doesn't exist everywhere. We
171 know that the amount of data cannot be greater than CTBUFSIZE, so
172 the first two bytes of this value will always be 0. They were
173 set to 0 in ftstart so we don't touch them here. This is useful
174 because we cannot portably right shift by 24 or 16, since we
175 might be dealing with sixteen bit integers. */
176 zdata[-2] = (char) ((cdata >> 8) & 0xff);
177 zdata[-1] = (char) (cdata & 0xff);
178
179 /* We pass FALSE to fsend_data since we don't expect the other side
180 to be sending us anything just now. */
181 return fsend_data (qdaemon->qconn, zdata - CTFRAMELEN, cdata + CTFRAMELEN,
182 FALSE);
183}
184\f
185/* Process data and return the amount we need in *pfneed. */
186
187static boolean
188ftprocess_data (qdaemon, pfexit, pcneed)
189 struct sdaemon *qdaemon;
190 boolean *pfexit;
191 size_t *pcneed;
192{
193 int cinbuf, cfirst, clen;
194
195 *pfexit = FALSE;
196
197 cinbuf = iPrecend - iPrecstart;
198 if (cinbuf < 0)
199 cinbuf += CRECBUFLEN;
200
201 if (! fTfile)
202 {
203 /* We are not receiving a file. Commands are read in chunks of
204 CTPACKSIZE. */
205 while (cinbuf >= CTPACKSIZE)
206 {
207 cfirst = CRECBUFLEN - iPrecstart;
208 if (cfirst > CTPACKSIZE)
209 cfirst = CTPACKSIZE;
210
211 DEBUG_MESSAGE1 (DEBUG_PROTO,
212 "ftprocess_data: Got %d command bytes",
213 cfirst);
214
215 if (! fgot_data (qdaemon, abPrecbuf + iPrecstart,
216 (size_t) cfirst, abPrecbuf,
217 (size_t) CTPACKSIZE - cfirst,
218 -1, -1, (long) -1, TRUE, pfexit))
219 return FALSE;
220
221 iPrecstart = (iPrecstart + CTPACKSIZE) % CRECBUFLEN;
222
223 if (*pfexit)
224 return TRUE;
225
226 cinbuf -= CTPACKSIZE;
227 }
228
229 if (pcneed != NULL)
230 *pcneed = CTPACKSIZE - cinbuf;
231
232 return TRUE;
233 }
234
235 /* Here we are receiving a file. The data comes in blocks. The
236 first four bytes contain the length, followed by that amount of
237 data. */
238
239 while (cinbuf >= CTFRAMELEN)
240 {
241 /* The length is stored in network byte order, MSB first. */
242
243 clen = (((((((abPrecbuf[iPrecstart] & 0xff) << 8)
244 + (abPrecbuf[(iPrecstart + 1) % CRECBUFLEN] & 0xff)) << 8)
245 + (abPrecbuf[(iPrecstart + 2) % CRECBUFLEN] & 0xff)) << 8)
246 + (abPrecbuf[(iPrecstart + 3) % CRECBUFLEN] & 0xff));
247
248 if (cinbuf < clen + CTFRAMELEN)
249 {
250 if (pcneed != NULL)
251 *pcneed = clen + CTFRAMELEN - cinbuf;
252 return TRUE;
253 }
254
255 iPrecstart = (iPrecstart + CTFRAMELEN) % CRECBUFLEN;
256
257 cfirst = CRECBUFLEN - iPrecstart;
258 if (cfirst > clen)
259 cfirst = clen;
260
261 DEBUG_MESSAGE1 (DEBUG_PROTO,
262 "ftprocess_data: Got %d data bytes",
263 clen);
264
265 if (! fgot_data (qdaemon, abPrecbuf + iPrecstart,
266 (size_t) cfirst, abPrecbuf, (size_t) (clen - cfirst),
267 -1, -1, (long) -1, TRUE, pfexit))
268 return FALSE;
269
270 iPrecstart = (iPrecstart + clen) % CRECBUFLEN;
271
272 if (*pfexit)
273 return TRUE;
274
275 cinbuf -= clen + CTFRAMELEN;
276 }
277
278 if (pcneed != NULL)
279 *pcneed = CTFRAMELEN - cinbuf;
280
281 return TRUE;
282}
283\f
284/* Wait for data to come in and process it until we've reached the end
285 of a command or a file. */
286
287boolean
288ftwait (qdaemon)
289 struct sdaemon *qdaemon;
290{
291 while (TRUE)
292 {
293 boolean fexit;
294 size_t cneed, crec;
295
296 if (! ftprocess_data (qdaemon, &fexit, &cneed))
297 return FALSE;
298 if (fexit)
299 return TRUE;
300
301 if (! freceive_data (qdaemon->qconn, cneed, &crec, cTtimeout, TRUE))
302 return FALSE;
303
304 if (crec == 0)
305 {
306 ulog (LOG_ERROR, "Timed out waiting for data");
307 return FALSE;
308 }
309 }
310}
311\f
312/* File level routine, to set fTfile correctly. */
313
314/*ARGSUSED*/
315boolean
316ftfile (qdaemon, qtrans, fstart, fsend, cbytes, pfhandled)
317 struct sdaemon *qdaemon;
318 struct stransfer *qtrans;
319 boolean fstart;
320 boolean fsend;
321 long cbytes;
322 boolean *pfhandled;
323{
324 *pfhandled = FALSE;
325
326 if (! fsend)
327 fTfile = fstart;
328
329 return TRUE;
330}