|
|
1.1 root 1: /* prote.c
2: The 'e' 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 prote_rcsid[] = "$Id: prote.c,v 1.1 93/07/30 07:53:17 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 my implementation of the 't'
40: protocol, which is fairly similar. The main difference between the
41: protocols seems to be that 't' breaks the file into packets and
42: transmits the size of the packet with each packet, whereas 'e'
43: sends the size of the entire file and then sends all the data in a
44: single enormous packet.
45:
46: The 'e' protocol does no error checking whatsoever and thus
47: requires an end-to-end verified eight bit communication line, such
48: as is provided by TCP. Using it with a modem is inadvisable, since
49: errors can occur between the modem and the computer. */
50:
51: /* The buffer size we use. */
52: #define CEBUFSIZE (CRECBUFLEN / 2)
53:
54: /* The size of the initial file size message. */
55: #define CEFRAMELEN (20)
56:
57: /* A pointer to the buffer we will use. */
58: static char *zEbuf;
59:
60: /* True if we are receiving a file. */
61: static boolean fEfile;
62:
63: /* The number of bytes we have left to send or receive. */
64: static long cEbytes;
65:
66: /* The timeout we use. */
67: static int cEtimeout = 120;
68:
69: struct uuconf_cmdtab asEproto_params[] =
70: {
71: { "timeout", UUCONF_CMDTABTYPE_INT, (pointer) &cEtimeout, NULL },
72: { NULL, 0, NULL, NULL }
73: };
74:
75: /* Local function. */
76:
77: static boolean feprocess_data P((struct sdaemon *qdaemon, boolean *pfexit,
78: size_t *pcneed));
79:
80: /* Start the protocol. */
81:
82: boolean
83: festart (qdaemon, pzlog)
84: struct sdaemon *qdaemon;
85: char **pzlog;
86: {
87: *pzlog = NULL;
88: if (! fconn_set (qdaemon->qconn, PARITYSETTING_NONE,
89: STRIPSETTING_EIGHTBITS, XONXOFF_OFF))
90: return FALSE;
91: zEbuf = (char *) xmalloc (CEBUFSIZE);
92: fEfile = FALSE;
93: usysdep_sleep (2);
94: return TRUE;
95: }
96:
97: /* Stop the protocol. */
98:
99: /*ARGSUSED*/
100: boolean
101: feshutdown (qdaemon)
102: struct sdaemon *qdaemon;
103: {
104: xfree ((pointer) zEbuf);
105: zEbuf = NULL;
106: cEtimeout = 120;
107: return TRUE;
108: }
109:
110: /* Send a command string. We send everything up to and including the
111: null byte. */
112:
113: /*ARGSUSED*/
114: boolean
115: fesendcmd (qdaemon, z, ilocal, iremote)
116: struct sdaemon *qdaemon;
117: const char *z;
118: int ilocal;
119: int iremote;
120: {
121: DEBUG_MESSAGE1 (DEBUG_UUCP_PROTO, "fesendcmd: Sending command \"%s\"", z);
122:
123: return fsend_data (qdaemon->qconn, z, strlen (z) + 1, TRUE);
124: }
125:
126: /* Get space to be filled with data. We provide a buffer which has
127: 20 bytes at the start available to hold the length. */
128:
129: /*ARGSUSED*/
130: char *
131: zegetspace (qdaemon, pclen)
132: struct sdaemon *qdaemon;
133: size_t *pclen;
134: {
135: *pclen = CEBUFSIZE;
136: return zEbuf;
137: }
138:
139: /* Send out some data. We are allowed to modify the 20 bytes
140: preceding the buffer. This allows us to send the entire block with
141: header bytes in a single call. */
142:
143: /*ARGSIGNORED*/
144: boolean
145: fesenddata (qdaemon, zdata, cdata, ilocal, iremote, ipos)
146: struct sdaemon *qdaemon;
147: char *zdata;
148: size_t cdata;
149: int ilocal;
150: int iremote;
151: long ipos;
152: {
153: #if DEBUG > 0
154: /* Keep track of the number of bytes we send out to make sure it all
155: adds up. */
156: cEbytes -= cdata;
157: if (cEbytes < 0)
158: {
159: ulog (LOG_ERROR, "Protocol 'e' internal error");
160: return FALSE;
161: }
162: #endif
163:
164: /* We pass FALSE to fsend_data since we don't expect the other side
165: to be sending us anything just now. */
166: return fsend_data (qdaemon->qconn, zdata, cdata, FALSE);
167: }
168:
169: /* Process data and return the amount we need in *pfneed. */
170:
171: static boolean
172: feprocess_data (qdaemon, pfexit, pcneed)
173: struct sdaemon *qdaemon;
174: boolean *pfexit;
175: size_t *pcneed;
176: {
177: int cinbuf, cfirst, clen;
178:
179: *pfexit = FALSE;
180:
181: cinbuf = iPrecend - iPrecstart;
182: if (cinbuf < 0)
183: cinbuf += CRECBUFLEN;
184:
185: if (! fEfile)
186: {
187: /* We are not receiving a file. Commands continue up to a null
188: byte. */
189: while (cinbuf > 0)
190: {
191: char *pnull;
192:
193: cfirst = CRECBUFLEN - iPrecstart;
194: if (cfirst > cinbuf)
195: cfirst = cinbuf;
196:
197: pnull = memchr (abPrecbuf + iPrecstart, '\0', (size_t) cfirst);
198: if (pnull != NULL)
199: cfirst = pnull - (abPrecbuf + iPrecstart) + 1;
200:
201: DEBUG_MESSAGE1 (DEBUG_PROTO,
202: "feprocess_data: Got %d command bytes",
203: cfirst);
204:
205: if (! fgot_data (qdaemon, abPrecbuf + iPrecstart,
206: (size_t) cfirst, (const char *) NULL, (size_t) 0,
207: -1, -1, (long) -1, TRUE, pfexit))
208: return FALSE;
209:
210: iPrecstart = (iPrecstart + cfirst) % CRECBUFLEN;
211:
212: if (*pfexit)
213: return TRUE;
214:
215: cinbuf = iPrecend - iPrecstart;
216: if (cinbuf < 0)
217: cinbuf += CRECBUFLEN;
218: }
219:
220: if (pcneed != NULL)
221: *pcneed = 1;
222:
223: return TRUE;
224: }
225:
226: /* Here we are receiving a file. We want cEbytes in total. If we
227: don't have cEbytes yet, we have to get it first. */
228:
229: if (cEbytes == -1)
230: {
231: char ab[CEFRAMELEN + 1];
232:
233: if (cinbuf < CEFRAMELEN)
234: {
235: if (pcneed != NULL)
236: *pcneed = CEFRAMELEN - cinbuf;
237: return TRUE;
238: }
239:
240: cfirst = CRECBUFLEN - iPrecstart;
241: if (cfirst >= CEFRAMELEN)
242: memcpy (ab, abPrecbuf + iPrecstart, (size_t) CEFRAMELEN);
243: else
244: {
245: memcpy (ab, abPrecbuf + iPrecstart, (size_t) cfirst);
246: memcpy (ab + cfirst, abPrecbuf, (size_t) CEFRAMELEN - cfirst);
247: }
248:
249: ab[CEFRAMELEN] = '\0';
250: cEbytes = strtol (ab, (char **) NULL, 10);
251:
252: iPrecstart = (iPrecstart + CEFRAMELEN) % CRECBUFLEN;
253:
254: cinbuf = iPrecend - iPrecstart;
255: if (cinbuf < 0)
256: cinbuf += CRECBUFLEN;
257: }
258:
259: /* Here we can read real data for the file. */
260:
261: while (cinbuf > 0)
262: {
263: clen = cinbuf;
264: if ((long) clen > cEbytes)
265: clen = (int) cEbytes;
266:
267: cfirst = CRECBUFLEN - iPrecstart;
268: if (cfirst > clen)
269: cfirst = clen;
270:
271: DEBUG_MESSAGE1 (DEBUG_PROTO,
272: "feprocess_data: Got %d data bytes",
273: clen);
274:
275: if (! fgot_data (qdaemon, abPrecbuf + iPrecstart,
276: (size_t) cfirst, abPrecbuf, (size_t) (clen - cfirst),
277: -1, -1, (long) -1, TRUE, pfexit))
278: return FALSE;
279:
280: iPrecstart = (iPrecstart + clen) % CRECBUFLEN;
281: cEbytes -= clen;
282:
283: if (cEbytes == 0)
284: {
285: if (! fgot_data (qdaemon, abPrecbuf, (size_t) 0,
286: (const char *) NULL, (size_t) 0,
287: -1, -1, (long) -1, TRUE, pfexit))
288: return FALSE;
289: if (*pfexit)
290: return TRUE;
291: }
292:
293: cinbuf -= clen;
294: }
295:
296: if (pcneed != NULL)
297: {
298: if (cEbytes > CRECBUFLEN / 2)
299: *pcneed = CRECBUFLEN / 2;
300: else
301: *pcneed = (int) cEbytes;
302: }
303:
304: return TRUE;
305: }
306:
307: /* Wait for data to come in and process it until we've reached the end
308: of a command or a file. */
309:
310: boolean
311: fewait (qdaemon)
312: struct sdaemon *qdaemon;
313: {
314: while (TRUE)
315: {
316: boolean fexit;
317: size_t cneed, crec;
318:
319: if (! feprocess_data (qdaemon, &fexit, &cneed))
320: return FALSE;
321: if (fexit)
322: return TRUE;
323:
324: if (! freceive_data (qdaemon->qconn, cneed, &crec, cEtimeout, TRUE))
325: return FALSE;
326:
327: if (crec == 0)
328: {
329: ulog (LOG_ERROR, "Timed out waiting for data");
330: return FALSE;
331: }
332: }
333: }
334:
335: /* File level routine, to handle transferring the amount of data and
336: to set fEfile correctly. */
337:
338: boolean
339: fefile (qdaemon, qtrans, fstart, fsend, cbytes, pfhandled)
340: struct sdaemon *qdaemon;
341: struct stransfer *qtrans;
342: boolean fstart;
343: boolean fsend;
344: long cbytes;
345: boolean *pfhandled;
346: {
347: *pfhandled = FALSE;
348:
349: if (fstart)
350: {
351: if (fsend)
352: {
353: char ab[CEFRAMELEN];
354:
355: DEBUG_MESSAGE1 (DEBUG_PROTO,
356: "Protocol 'e' starting to send %ld bytes",
357: cbytes);
358:
359: bzero (ab, (size_t) CEFRAMELEN);
360: sprintf (ab, "%ld", cbytes);
361: if (! fsend_data (qdaemon->qconn, ab, (size_t) CEFRAMELEN, TRUE))
362: return FALSE;
363: cEbytes = cbytes;
364: }
365: else
366: {
367: cEbytes = -1;
368: fEfile = TRUE;
369: }
370: }
371: else
372: {
373: if (! fsend)
374: fEfile = FALSE;
375: #if DEBUG > 0
376: if (cEbytes != 0)
377: {
378: ulog (LOG_ERROR,
379: "Protocol 'e' internal error: %ld bytes left over",
380: cEbytes);
381: return FALSE;
382: }
383: #endif
384: }
385:
386: return TRUE;
387: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.