|
|
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.