Blame src/ascii-xfr.c

Packit 15a96c
/*
Packit 15a96c
 * ascii-xfr	Ascii file transfer.
Packit 15a96c
 *
Packit 15a96c
 * Usage:	ascii-xfr -s|-r [-ednv] [-c character delay] [-l line delay]
Packit 15a96c
 *
Packit 15a96c
 * 08.03.98 added a patch from Bo Branten <bosse@ing.umu.se>
Packit 15a96c
 *
Packit 15a96c
 *  You should have received a copy of the GNU General Public License along
Packit 15a96c
 *  with this program; if not, write to the Free Software Foundation, Inc.,
Packit 15a96c
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit 15a96c
 *
Packit 15a96c
 */
Packit 15a96c
Packit 15a96c
#ifdef HAVE_CONFIG_H
Packit 15a96c
#include <config.h>
Packit 15a96c
#endif
Packit 15a96c
Packit 15a96c
#include <errno.h>
Packit 15a96c
#include <stdio.h>
Packit 15a96c
#include <stdlib.h>
Packit 15a96c
#include <string.h>
Packit 15a96c
#include <time.h>
Packit 15a96c
#include <unistd.h>
Packit 15a96c
#include <sys/time.h>
Packit 15a96c
#include <sys/types.h>
Packit 15a96c
Packit 15a96c
#ifdef HAVE_TERMIOS_H
Packit 15a96c
#include <termios.h>
Packit 15a96c
#endif
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 *	Externals.
Packit 15a96c
 */
Packit 15a96c
extern int optind;
Packit 15a96c
extern char *optarg;
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 *	Global variables.
Packit 15a96c
 */
Packit 15a96c
int cdelay = 0;
Packit 15a96c
int ldelay = 0;
Packit 15a96c
int dotrans = 1;
Packit 15a96c
int eofchar = 26;
Packit 15a96c
int useeof = 0;
Packit 15a96c
int verbose = 0;
Packit 15a96c
time_t start, last;
Packit 15a96c
unsigned long bdone = 0;
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 *	Millisecond delay.
Packit 15a96c
 */
Packit 15a96c
void ms_delay(int ms)
Packit 15a96c
{
Packit 15a96c
#ifdef HAVE_USLEEP
Packit 15a96c
  usleep(1000 * ms);
Packit 15a96c
#endif
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 *	Output a line and delay if needed.
Packit 15a96c
 */
Packit 15a96c
static void lineout(char const *line, int len)
Packit 15a96c
{
Packit 15a96c
  int ret;
Packit 15a96c
Packit 15a96c
  if (!cdelay) {
Packit 15a96c
    do {
Packit 15a96c
      ret = write(STDOUT_FILENO, line, len);
Packit 15a96c
      if (ret < 0) {
Packit 15a96c
	fprintf(stderr, "Error while writing (errno = %d)\n", errno);
Packit 15a96c
	return;
Packit 15a96c
      }
Packit 15a96c
      len -= ret;
Packit 15a96c
      line += ret;
Packit 15a96c
    } while (len);
Packit 15a96c
Packit 15a96c
  } else {
Packit 15a96c
    while (*line) {
Packit 15a96c
      ret = write(STDOUT_FILENO, line, 1);
Packit 15a96c
      if (ret < 0) {
Packit 15a96c
	fprintf(stderr, "Error while writing (errno = %d)\n", errno);
Packit 15a96c
	return;
Packit 15a96c
      }
Packit 15a96c
      if (ret == 1)
Packit 15a96c
	line++;
Packit 15a96c
      ms_delay(cdelay);
Packit 15a96c
    }
Packit 15a96c
  }
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 *	Show the up/download statistics.
Packit 15a96c
 */
Packit 15a96c
void stats(int force)
Packit 15a96c
{
Packit 15a96c
  time_t now;
Packit 15a96c
  time_t dif;
Packit 15a96c
Packit 15a96c
  if (!verbose)
Packit 15a96c
    return;
Packit 15a96c
Packit 15a96c
  time(&now;;
Packit 15a96c
  dif = now - start;
Packit 15a96c
Packit 15a96c
  if (!force && dif < 2)
Packit 15a96c
    return;
Packit 15a96c
  if (dif < 1)
Packit 15a96c
    dif = 1;
Packit 15a96c
  last = now;
Packit 15a96c
Packit 15a96c
  fprintf(stderr, "\r%.1f Kbytes transferred at %d CPS",
Packit 15a96c
          (float)bdone / 1024, (int)(bdone / dif));
Packit 15a96c
  fflush(stderr);
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
void check_answer(void)
Packit 15a96c
{ /* a patch from Bo Branten <bosse@ing.umu.se> */
Packit 15a96c
  char line[1024];
Packit 15a96c
  int  n;
Packit 15a96c
  fd_set rfds;
Packit 15a96c
  struct timeval tv;
Packit 15a96c
Packit 15a96c
  FD_ZERO (&rfds);
Packit 15a96c
  FD_SET (STDIN_FILENO, &rfds);
Packit 15a96c
  tv.tv_sec = 0;
Packit 15a96c
  tv.tv_usec = 0;
Packit 15a96c
  while (select (STDIN_FILENO + 1, &rfds, NULL, NULL, &tv) > 0) {
Packit 15a96c
    n = read (STDIN_FILENO, line, sizeof(line));
Packit 15a96c
    if (write(STDERR_FILENO, line, n) == -1)
Packit 15a96c
      break;
Packit 15a96c
    FD_ZERO(&rfds);
Packit 15a96c
    FD_SET(STDIN_FILENO, &rfds);
Packit 15a96c
    tv.tv_sec = 0;
Packit 15a96c
    tv.tv_usec = 0;
Packit 15a96c
  }
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 *	Send a file in ASCII mode.
Packit 15a96c
 */
Packit 15a96c
int asend(char *file)
Packit 15a96c
{
Packit 15a96c
  FILE *fp;
Packit 15a96c
  char line[1024];
Packit 15a96c
  char *s;
Packit 15a96c
  int first = 1;
Packit 15a96c
  long cur, len;
Packit 15a96c
Packit 15a96c
  if ((fp = fopen(file, "r")) == NULL) {
Packit 15a96c
    perror(file);
Packit 15a96c
    return -1;
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  cur = 0;
Packit 15a96c
Packit 15a96c
  while (fgets(line, sizeof(line) - 2, fp) != NULL) {
Packit 15a96c
    long c = ftell(fp);
Packit 15a96c
    len = c - cur;
Packit 15a96c
    cur = c;
Packit 15a96c
    if (dotrans && (s = strrchr(line, '\n')) != NULL) {
Packit 15a96c
      /* s now points to \n */
Packit 15a96c
      /* if there's a \r before, go there */
Packit 15a96c
      if (s > line && *(s - 1) == '\r')
Packit 15a96c
        {
Packit 15a96c
          s--;
Packit 15a96c
	  len--;
Packit 15a96c
	}
Packit 15a96c
      /* end of line */
Packit 15a96c
      *s++ = '\r';
Packit 15a96c
      *s++ = '\n';
Packit 15a96c
      /* terminate string */
Packit 15a96c
      *s = 0;
Packit 15a96c
      len++;
Packit 15a96c
    }
Packit 15a96c
    lineout(line, len);
Packit 15a96c
    bdone += len;
Packit 15a96c
    if (ldelay)
Packit 15a96c
      ms_delay(ldelay);
Packit 15a96c
    stats(first);
Packit 15a96c
    first = 0;
Packit 15a96c
    check_answer();
Packit 15a96c
  }
Packit 15a96c
  if (useeof) 
Packit 15a96c
    putchar(eofchar);
Packit 15a96c
  fflush(stdout);
Packit 15a96c
  if (isatty (STDOUT_FILENO))
Packit 15a96c
    tcdrain (STDOUT_FILENO);
Packit 15a96c
  fclose(fp);
Packit 15a96c
Packit 15a96c
  return 0;
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
/*
Packit 15a96c
 *	Receive a file in ASCII mode.
Packit 15a96c
 */
Packit 15a96c
int arecv(char *file)
Packit 15a96c
{
Packit 15a96c
  FILE *fp;
Packit 15a96c
  char line[1024];
Packit 15a96c
  char *s;
Packit 15a96c
  int n;
Packit 15a96c
  int first = 1;
Packit 15a96c
Packit 15a96c
  if ((fp = fopen(file, "w")) == NULL) {
Packit 15a96c
    perror(file);
Packit 15a96c
    return -1;
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  while ((n = read(STDIN_FILENO, line, sizeof(line))) > 0) {
rpm-build bace13
    for (s = line; s - line < n; s++) {
Packit 15a96c
      if (*s == eofchar)
Packit 15a96c
        break;
Packit 15a96c
      if (dotrans && *s == '\r')
Packit 15a96c
        continue;
Packit 15a96c
      bdone++;
Packit 15a96c
      fputc(*s, fp);
Packit 15a96c
    }
Packit 15a96c
    stats(first);
Packit 15a96c
    first = 0;
rpm-build bace13
    if (s - line < n && *s == eofchar)
Packit 15a96c
      break;
Packit 15a96c
  }
Packit 15a96c
  fclose(fp);
Packit 15a96c
Packit 15a96c
  return 0;
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
void usage(void)
Packit 15a96c
{
Packit 15a96c
  fprintf(stderr, "\
Packit 15a96c
Usage: ascii-xfr -s|-r [-dvn] [-l linedelay] [-c character delay] filename\n\
Packit 15a96c
       -s:  send\n\
Packit 15a96c
       -r:  receive\n\
Packit 15a96c
       -e:  send the End Of File character (default is not to)\n\
Packit 15a96c
       -d:  set End Of File character to Control-D (instead of Control-Z)\n\
Packit 15a96c
       -v:  verbose (statistics on stderr output)\n\
Packit 15a96c
       -n:  do not translate CRLF <--> LF\n\
Packit 15a96c
       Delays are in milliseconds.\n");
Packit 15a96c
  exit(1);
Packit 15a96c
}
Packit 15a96c
Packit 15a96c
int main(int argc, char **argv)
Packit 15a96c
{
Packit 15a96c
  int c;
Packit 15a96c
  int what = 0;
Packit 15a96c
  char *file;
Packit 15a96c
  int ret;
Packit 15a96c
Packit 15a96c
  while ((c = getopt(argc, argv, "srdevnl:c:")) != EOF) {
Packit 15a96c
    switch (c) {
Packit 15a96c
      case 's':
Packit 15a96c
      case 'r':
Packit 15a96c
        what = c;
Packit 15a96c
        break;
Packit 15a96c
      case 'd':
Packit 15a96c
        eofchar = 4; /* Unix, CTRL-D */
Packit 15a96c
        break;
Packit 15a96c
      case 'e':
Packit 15a96c
        useeof = 1;
Packit 15a96c
        break;
Packit 15a96c
      case 'v':
Packit 15a96c
        verbose++;
Packit 15a96c
        break;
Packit 15a96c
      case 'n':
Packit 15a96c
        dotrans = 0;
Packit 15a96c
        break;
Packit 15a96c
      case 'l':
Packit 15a96c
        ldelay = atoi(optarg);
Packit 15a96c
        break;
Packit 15a96c
      case 'c':
Packit 15a96c
        cdelay = atoi(optarg);
Packit 15a96c
        break;
Packit 15a96c
      default:
Packit 15a96c
        usage();
Packit 15a96c
        break;
Packit 15a96c
    }
Packit 15a96c
  }
Packit 15a96c
  if (optind != argc - 1 || what == 0)
Packit 15a96c
    usage();
Packit 15a96c
  file = argv[optind];
Packit 15a96c
Packit 15a96c
  time(&start;;
Packit 15a96c
  last = start;
Packit 15a96c
Packit 15a96c
  if (what == 's') {
Packit 15a96c
    fprintf(stderr, "ASCII upload of \"%s\"\n", file);
Packit 15a96c
    if (cdelay || ldelay)
Packit 15a96c
      fprintf(stderr, "Line delay: %d ms, character delay %d ms\n",
Packit 15a96c
              ldelay, cdelay);
Packit 15a96c
    fprintf(stderr, "\n");
Packit 15a96c
    fflush(stderr);
Packit 15a96c
    ret = asend(file);
Packit 15a96c
  } else {
Packit 15a96c
    fprintf(stderr, "ASCII download of \"%s\"\n\n", file);
Packit 15a96c
    fflush(stderr);
Packit 15a96c
    ret = arecv(file);
Packit 15a96c
  }
Packit 15a96c
  if (verbose) {
Packit 15a96c
    stats(1);
Packit 15a96c
    fprintf(stderr, "... Done.\n");
Packit 15a96c
    fflush(stdout);
Packit 15a96c
  }
Packit 15a96c
Packit 15a96c
  return ret < 0 ? 1 : 0;
Packit 15a96c
}
Packit 15a96c