|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T s ┃
Length: 9224 (0x2408) Types: TextFile Names: »send.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/xmodem/send.c«
/** send a file **/ /* * Operation of this routine depends on on MDM7BAT and YMDMBAT flags. * * If "name" is NULL; close out the BATCH send. */ #include "xmodem.h" sfile(name) char *name; { char *sectdisp(); time_t time(); char *strcpy(); char *unix_cpm(); extern unsigned short crctab[1<<B]; /* CRC-16 constant values, see getput.c */ register int bufctr, /* array index for data buffer */ sectnum; /* packet number for packet header */ register unsigned short checksum; /* checksum/crc */ char blockbuf[BBUFSIZ+6]; /* holds packet as it is constructed */ struct stat filestatbuf; /* file status info */ int fd, /* file descriptor for file being transmitted */ errors, /* cumulative count of errors */ attempts, /* number of attempts made to transmit a packet */ nlflag, /* flag that we have to send a LF in next packet */ sendfin, /* flag that we are sending the last packet */ closeout, /* flag that we are closing out batch send */ tmode, /* TRUE for text mode; FALSE for binary mode */ bbufcnt, /* array index for packet */ firstchar, /* first character in protocol transaction */ bufsize, /* packet size (128 or 1024) */ sendresp, /* response char to sent block received from remote*/ extrachar; /* count of extra LF characters added */ long sentsect; /* count of 128 byte sectors actually sent */ long expsect; /* count of 128 byte sectors expected to be sent */ time_t start; /* starting time of transfer */ char c; nbchr = 0; /* clear buffered read char count */ CRCMODE = FALSE; /* Receiver determines use of crc or checksum */ closeout = FALSE; /* Check on NULL file name */ if (strcmp(name,"") == 0) { if (BATCH) closeout = TRUE; else { sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); error("NULL file name in send", TRUE); } } if (!closeout) /* Are we closing down batch? */ { /* no; let's send a file */ if ((fd = open(name, 0)) < 0) { sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); error("Can't open file for send", TRUE); } stat(name, &filestatbuf); /* get file status bytes */ expsect = (filestatbuf.st_size/128) + 1; if (LOGFLAG) { fprintf(LOGFP, "----\nXMODEM Send Function\n"); fprintf(LOGFP, "File Name: %s\n", name); fprintf(LOGFP,"Estimated File Size %ldK, %ld Records, %ld Bytes\n", (filestatbuf.st_size/1024)+1, expsect, filestatbuf.st_size); projtime(expsect, LOGFP); } } else { logit("----\nXMODEM Send Function\n"); logit("Closing down Batch Transmission\n"); } tmode = (XMITTYPE == 't') ? TRUE : FALSE; /* set text mode */ bufsize = LONGPACK ? 1024 : 128; /* set sector size */ if (LONGPACK && !closeout) logit("1K packet mode chosen\n"); sendfin = nlflag = FALSE; attempts = 0; /* wait for and read startup character */ do { while (((firstchar=readbyte(30)) != NAK) && (firstchar != CRCCHR) && (firstchar != CAN)) if (++attempts > NAKMAX) error("Remote System Not Responding", TRUE); if ((firstchar & 0x7f) == CAN) if (readbyte(3) == CAN) error("Send cancelled at user's request",TRUE); if (firstchar == CRCCHR) { CRCMODE = TRUE; if (!closeout) logit("CRC mode requested\n"); } } while (firstchar != NAK && firstchar != CRCCHR); if (closeout && MDM7BAT) /* close out MODEM7 batch */ { sendbyte(ACK); sendbyte (EOT); readbyte(2); /* flush junk */ return; } if (MDM7BAT) /* send MODEM7 file name and resync for data packets */ { if (send_name(unix_cpm(name)) == -1) /* should do better job here!! */ error("MODEM7-batch filename transfer botch", TRUE); firstchar = readbyte(5); if (firstchar != CRCCHR && firstchar != NAK) /* Should do some better error handling!!! */ error("MODEM7 protocol botch, NAK/C expected", TRUE); CRCMODE = FALSE; if (firstchar == CRCCHR) { CRCMODE = TRUE; logit("CRC mode requested for MODEM7 batch transfer\n"); } } sectnum = 1; if (YMDMBAT) /* Fudge for YMODEM transfer (to send name packet) */ { sectnum = 0; bufsize = 128; } attempts = errors = sentsect = extrachar = 0; start = time((time_t *) 0); do /* outer packet building/sending loop; loop till whole file is sent */ { if (closeout && YMDMBAT && sectnum == 1) /* close out YMODEM */ return; if (YMDMBAT && sectnum == 1) /* get set to send YMODEM data packets */ { bufsize = LONGPACK ? 1024 : 128; do { while (((firstchar=readbyte(3)) != CRCCHR) && (firstchar != CAN)) if (++attempts > NAKMAX) error("YMODEM protocol botch, C expected", TRUE); if ((firstchar&0x7f) == CAN) if (readbyte(3) == CAN) error("Send cancelled at User's request", TRUE); } while (firstchar != CRCCHR); attempts = 0; } if (extrachar >= 128) /* update expected sector count */ { extrachar = 0; expsect++; } if ((bufsize == 1024) && (errors > KSWMAX)) { logit("Reducing packet size to 128 due to excessive errors\n"); bufsize = 128; } if ((bufsize == 1024) && ((expsect - sentsect) < 8)) { logit("Reducing packet size to 128 for tail end of file\n"); bufsize = 128; } if (sectnum > 0) /* data packet */ { for (bufctr=0; bufctr < bufsize;) { if (nlflag) { buff[bufctr++] = LF; /* leftover newline */ nlflag = FALSE; } if (getbyte(fd, &c) == EOF) { sendfin = TRUE; /* this is the last sector */ if (!bufctr) /* if EOF on sector boundary */ break; /* avoid sending extra sector */ buff[bufctr++] = CTRLZ; /* Control-Z for CP/M EOF (even do it for binary file) */ continue; } if (tmode && c == LF) /* text mode & Unix newline? */ { extrachar++; buff[bufctr++] = CR; /* insert carriage return */ if (bufctr < bufsize) buff[bufctr++] = LF; /* insert LF */ else nlflag = TRUE; /* insert on next sector */ } else buff[bufctr++] = c; /* copy the char without change */ } if (!bufctr) /* if EOF on sector boundary */ break; /* avoid sending empty sector */ } else /* YMODEM filename packet */ { for (bufctr=0; bufctr<bufsize; bufctr++) buff[bufctr]=0; if (!closeout) { cpmify(name); strcpy((char *)buff, name); buff[bufsize-2] = (expsect & 0xff); buff[bufsize-1] = ((expsect >> 8) & 0xff); } } bbufcnt = 0; /* start building block to be sent */ blockbuf[bbufcnt++] = (bufsize == 1024) ? STX : SOH; /* start of packet char */ blockbuf[bbufcnt++] = sectnum; /* current sector # */ blockbuf[bbufcnt++] = ~sectnum; /* and its complement */ checksum = 0; /* initialize checksum */ for (bufctr=0; bufctr < bufsize; bufctr++) { blockbuf[bbufcnt++] = buff[bufctr]; if (CRCMODE) checksum = (checksum<<B) ^ crctab[(checksum>>(W-B)) ^ buff[bufctr]]; else checksum = ((checksum+buff[bufctr]) & 0xff); } if (CRCMODE) /* put in CRC */ { checksum &= 0xffff; blockbuf[bbufcnt++] = ((checksum >> 8) & 0xff); blockbuf[bbufcnt++] = (checksum & 0xff); } else /* put in checksum */ blockbuf[bbufcnt++] = checksum; attempts = 0; do /* inner packet loop */ { writebuf(blockbuf, bbufcnt); /* write the block */ if (DEBUG) fprintf (LOGFP, "DEBUG: %d byte Packet %02xh (%02xh) sent, checksum %02xh %02xh\n", bbufcnt, blockbuf[1]&0xff, blockbuf[2]&0xff, blockbuf[bufsize+3]&0xff, blockbuf[bufsize+4]&0xff); attempts++; sendresp = readbyte(10); /* get response from remote */ if (sendresp != ACK) { errors++; if ((sendresp & 0x7f) == CAN) if ((readbyte(3) & 0x7f) == CAN) error("Send cancelled at user's request\n",TRUE); if (sendresp == TIMEOUT) { logitarg("Timeout on sector %s\n",sectdisp(sentsect,bufsize,1)); } else { logitarg("Non-ACK on sector %s\n",sectdisp(sentsect,bufsize,1)); } } } while((sendresp != ACK) && (attempts < RETRYMAX) && (errors < ERRORMAX)); /* close of inner loop */ sectnum++; /* increment to next sector number */ sentsect += (bufsize == 128) ? 1 : 8; } while (!sendfin && (attempts < RETRYMAX) && ( errors < ERRORMAX)); /* end of outer loop */ if (attempts >= RETRYMAX) { sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); error("Remote System Not Responding", TRUE); } if (attempts > ERRORMAX) { sendbyte(CAN); sendbyte(CAN); sendbyte(CAN); error ("Too many errors in transmission", TRUE); } attempts = 0; sendbyte(EOT); /* send 1st EOT to close down transfer */ while ((readbyte(15) != ACK) && (attempts++ < RETRYMAX)) /* wait for ACK of EOT */ { logit("EOT not ACKed\n"); sendbyte(EOT); } if (attempts >= RETRYMAX) error("Remote System Not Responding on Completion", TRUE); close(fd); logit("Send Complete\n"); prtime(sentsect, time((time_t *) 0) - start); }