|
|
1.1 root 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 [email protected] 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
29: const char prott_rcsid[] = "$Id: prott.c,v 1.1 93/07/30 07:53:37 bin Exp Locker: bin $";
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:
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:
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. */
57: static char *zTbuf;
58:
59: /* True if we are receiving a file. */
60: static boolean fTfile;
61:
62: /* The timeout we use. */
63: static int cTtimeout = 120;
64:
65: struct uuconf_cmdtab asTproto_params[] =
66: {
67: { "timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cTtimeout, NULL },
68: { NULL, 0, NULL, NULL }
69: };
70:
71: /* Local function. */
72:
73: static boolean ftprocess_data P((struct sdaemon *qdaemon, boolean *pfexit,
74: size_t *pcneed));
75:
76: /* Start the protocol. */
77:
78: boolean
79: ftstart (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:
96: /* Stop the protocol. */
97:
98: /*ARGSUSED*/
99: boolean
100: ftshutdown (qdaemon)
101: struct sdaemon *qdaemon;
102: {
103: xfree ((pointer) zTbuf);
104: zTbuf = NULL;
105: cTtimeout = 120;
106: return TRUE;
107: }
108:
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*/
114: boolean
115: ftsendcmd (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:
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*/
147: char *
148: ztgetspace (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*/
161: boolean
162: ftsenddata (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:
185: /* Process data and return the amount we need in *pfneed. */
186:
187: static boolean
188: ftprocess_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:
284: /* Wait for data to come in and process it until we've reached the end
285: of a command or a file. */
286:
287: boolean
288: ftwait (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:
312: /* File level routine, to set fTfile correctly. */
313:
314: /*ARGSUSED*/
315: boolean
316: ftfile (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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.