DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T x

⟦1e6cf87aa⟧ TextFile

    Length: 8604 (0x219c)
    Types: TextFile
    Names: »xfer.c«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦f91e15335⟧ »EurOpenD3/news/nntp/nntplink2.0.0.tar.Z« 
        └─⟦2c70c5e6b⟧ 
            └─⟦this⟧ »xfer.c« 

TextFile

#include "global.h"

/*
 ** Perform one transfer operation:
 **	Give IHAVE command
 **	Wait for reply, and send article if they ask for it
 **	Wait for transfer confirmation, and requeue the article
 **		if they drop it.
 **	Watch all network I/O for errors, return FALSE if
 **		the connection fails and we have to cleanup.
 **	Return TRUE means it was successful, or at least that it
 **		doesn't have to be requeued.
 **	Return FALSE means it needs to be requeued.  This implies the
 **		connection is closed and reopened.
 */
sendarticle(host, fp, mesgid)
     char	*host;
     FILE	*fp;
     char	*mesgid;
{
  register int	code;
  char	buf[BUFSIZ];
  char	*e_xfer = "%s xfer %s: %s";
  
  switch(code = ihave(fp, mesgid)) {
  case CONT_XFER:
    /*
     ** They want it. Give it to 'em.
     */
    if (!sendfile(fp)) {
      sprintf(buf, e_xfer, host, Article, errmsg(errno));
      log(L_NOTICE, buf);
      Stats.failed++;
      return(FALSE);
    }
    /*
     ** Did the article transfer OK?
     ** Stay tuned to this same socket to find out!
     */
    if ((code = readreply(buf, sizeof(buf))) != OK_XFERED) {
      Stats.failed++;
      if (code < 0) {
	if (errno > 0) {
	  sprintf(buf, e_xfer, host, Article, errmsg(errno));
	  log(L_NOTICE, buf);
	} else {
	  char errbuf[BUFSIZ];
	  
	  sprintf(errbuf, e_xfer, host, Article, buf);
	  log(L_NOTICE, errbuf);
	}
      }
      if (code == ERR_XFERRJCT) {
	/* 
	 * it failed, but they don't want it retransfered.
	 * we fake success so that it is not requeued.
	 */
	return(TRUE);
      }
      return(FALSE);
    }
    break;
  case ERR_GOTIT:
    /* they don't want it */
    break;
  case ERR_XFERFAIL:
    /* they can't do it right now, but maybe later */
    return(FALSE);
    /*NOTREACHED*/
    break;
    
  case ERR_GOODBYE:
    /* Load ave too high */
    goodbye(DONT_WAIT);
    connected = 0;
    return(FALSE);
    /*NOTREACHED*/
    break;
    
  default:
    if (code < 0) {
      if (errno > 0) {
	sprintf(buf, e_xfer, host, Article, errmsg(errno));
	log(L_NOTICE, buf);
      } else {
	char nbuf[100];
	sprintf(nbuf, "ihave, code=%d errno=%d", code, errno);
	sprintf(buf, e_xfer, host, Article, nbuf);
	log(L_NOTICE, buf);
      }
    } else {
      sprintf(buf, "%s improper response to IHAVE: %d while offering %s", host, code, Article);
      log(L_WARNING, buf);
    }
    return(FALSE);
  }
  return(TRUE);
}

/*
 ** Given a hostname to connect to, and a file of filenames (which contain
 ** netnews articles), send those articles to the named host using NNTP.
 **
 **
 ** Return code:
 **	TRUE	- if at least one article was offered without
 **		  an error.  We don't care whether it was rejected
 **		  or not, or whether an error ocurred on any later
 **		  article.  The object is measure the health of
 **		  the server so that we know when to backoff on
 **		  the retry frequency.  If the server can negotiate
 **		  at least one article, it's healthy and we don't
 **		  backoff.
 **		  Note that any error causes the connection to be closed.
 **
 **	FALSE	- if an error ocurred before an article could be
 **		  offered.  e.g., if the first sendarticle() fails.
 **		  This implies the server is not healthy and that we 
 **		  close/reopen the connection using exponential backoff.
 **
 */
sendnews(host, transport, file)
     char	*host, *file;
     int	transport;
{
  register FILE	*fp;
  register int progress; 	/* the number of successful sendarticle()s */
#ifdef	FTRUNCATE
  char	*mode = "r+";		/* so we can use ftruncate() */
#else
  char	*mode = "r";
#endif	FTRUNCATE
  char	mesgid[255];
  
  dprintf(stderr,"%s: Entering sendnews\n", Pname);
#ifdef VERIFYQFILE
  if (!In_Log_File)
    vrfy(file); 
#endif
  if ((Qfp = fopen(file, In_Log_File ? "r" : mode)) == (FILE *)NULL) {
    char	buf[BUFSIZ];
    
    sprintf(buf, E_fopen, file, In_Log_File ? "r" : mode, errmsg(errno));
    log(L_WARNING, buf);
    In_Log_File = FALSE;
    return(FALSE);
  }
  
  /*
   ** interlock with other copies of this process. (if not using log file)
   ** non-blocking.
   */
  if ( In_Log_File ) {
    if (!skip_to_pos(file))
      return(FALSE);
  } else if (!lockfd(fileno(Qfp), file, DONT_BLOCK)) {
    FCLOSE(Qfp);
    return(FALSE);
  }
  
  /*
   ** start an exchange with the remote server
   */
  
  /* we have work to do now; if we logged our stats during the last pause,
     we must reset our timers here to include only active time */
  if (resetstats) {
    resetstats = FALSE;
    dprintf(stderr,"resetting timers\n");
    Tbegin = Tend;	
    ouser = user;
    osys = sys;
    Stats.offered = Stats.accepted = Stats.rejected = Stats.failed = 0L;
  }
  
  /* open a connection if not already open */
  if (!connected) 
    {
      if (hello(host, transport) == FAIL) {
	FCLOSE(Qfp);
	In_Log_File=FALSE;
	sleep(Sleep_Time);
	return(FALSE);
      } else
	connected = 1;
    }
  
  
  /*
   ** We're sending a batch queue:
   **	open article
   **	get message-ID
   **	send "IHAVE <message-ID>" to remote
   **	read their reply
   **	send article if appropriate
   **	iterate to end of queue file
   */
/*  catchsig(interrupted);*/

  dprintf(stderr,"starting to send\n");
  
  progress = 0;
  while((fp = getfp(Qfp, Article, sizeof(Article),
		    mesgid, host)) != (FILE *)NULL) {
    if (!sendarticle(host, fp, mesgid)) {
      FCLOSE(fp);
      if (!In_Log_File)
	requeue(Article, mesgid);
      cleanup();
      goodbye(DONT_WAIT);
      connected = 0;
      In_Log_File = FALSE;
      return progress? TRUE:FALSE;
    }
    FCLOSE(fp);
    progress++;
  }

  cleanup();

  In_Log_File = FALSE;

  return(TRUE);
}

skip_to_pos(file)
char *file;
{
  char temp[MAXFNAME];
  FILE *Linkfp;
#ifdef	FTRUNCATE
  char	*mode = "r+";		/* so we can use ftruncate() */
#else
  char	*mode = "r";
#endif	FTRUNCATE
  char  buf[BUFSIZ];

  dprintf(stderr, "Entering skip_to_pos...");

  sprintf(temp, "%s.link", orig_Qfile);

  if ((Linkfp = fopen(temp, "r")) == (FILE *)NULL)
    return(TRUE);
  
  (void) fgets(old_logline, MAXLOGLENGTH, Linkfp);

  (void) fgets(logline, MAXLOGLENGTH, Qfp);

  while ((fgets(logline, MAXLOGLENGTH, Qfp) != NULL) && 
	 (strncmp(logline, old_logline, strlen(logline) - 1) != 0))
    ;


  /* If we've reached the end of the file and the lines don't match then
   * we want to start at the beginning (old_logline is probably from a
   * different log file)
   */

  if (feof(Qfp) && (strncmp(logline, old_logline, strlen(logline) -1) != 0))
    {
      FCLOSE(Qfp);
      if ((Qfp = fopen(file, In_Log_File ? "r" : mode)) == (FILE *)NULL) {
	sprintf(buf, E_fopen, file, In_Log_File ? "r" : mode, errmsg(errno));
	log(L_WARNING, buf);
	FCLOSE(Linkfp);
	In_Log_File = FALSE;
	return(FALSE);
      }
    }

  dprintf(stderr, "done\n");

  FCLOSE(Linkfp);
  return(TRUE);
}


/** strnindex:  return index of t in s (starting at n), -1 if none
 ** as found in "The C Programming Language", 2nd Ed, K & R
 ** and slightly modified  :-)
 **/

int strnindex(s, t, n)
char s[], t[];
int n;
{
  int i, j, k;

  for (i = n;  s[i] != '\0'; i++) {
    for (j=i, k=0; t[k]!='\0' && s[j]==t[k]; j++, k++)
      ;
    if (k > 0 && t[k] == '\0')
      return i;
  }
  return -1;
}

/** my very own fgets that doesn't stop at EOF
 ** We sleep Sleep_Time until a line has started to be written, then
 ** we keep banging away until we get the rest of the article
 **/
char *
my_fgets(s, n, iop)
char *s;
int n;
FILE *iop;
{
  register int c;
  register char *cs;
  register int count = 0;

  cs = s;

  dprintf(stderr, "Waiting for log entry: ", Sleep_Time);

  while ((c = getc(iop)) == EOF) {
    clearerr(iop);

    count++;
    if (connected && CheckIdleTimeout && count*Sleep_Time > IdleTimeOut) {
      dprintf(stderr,
	      "%s: reached idle time-out, closing link temporarily.\n",
	      Pname); fflush(stderr);
      goodbye(WAIT);
      connected = 0;
      Stats.since_close = 0L;
    }
    if (CheckExitTimeout && count*Sleep_Time > ExitTimeOut) {
      dprintf(stderr, 
	      "%s: reached exit time-out. %s Exiting.\n",
	      Pname,
	      Report_Stats ? " Logging stats and" : ""); fflush(stderr);
      if (Report_Stats)
	logstats();
      cleanup();
      goodbye(DONT_WAIT);
      exit(0);
    }
    sleep(Sleep_Time);
    dprintf(stderr,".");
  }

  dprintf(stderr, "got it!\n");

  while (((*cs++ = c) != '\n') && (--n > 0))
    while ((c = getc(iop)) == EOF)
      clearerr(iop);

  cs--;				/* replace "<blah>/n" with "<blah> /n" */
  *cs++ = ' ';			/* so that the last sysname has an extra */
  *cs++ = '\n';			/* space after it (used in matching) */
  *cs = '\0';

  return s;
}