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