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 q

⟦d8d918533⟧ TextFile

    Length: 7935 (0x1eff)
    Types: TextFile
    Names: »queue.c«

Derivation

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

TextFile

#include "global.h"

char *safecopy(Qfile)
char *Qfile;
{
  struct stat statb;

  if (In_Log_File)
    return(Qfile);

  sprintf(nntpfile, "%s.nntp", Qfile);
  sprintf(orig_nntpfile, "%s.nntp", orig_Qfile);

  errno = 0;
  if (stat(nntpfile, &statb) == -1)	/** NNTP file doesn't exist?   **/
    {
      dprintf(stderr, "%s does not exist; waiting for %s\n", nntpfile, Qfile);
      
      waitingfor(Qfile);
      
      dprintf(stderr, "got %s\n", Qfile);

      if ( !In_Log_File ) {
      	if ( rename(Qfile, nntpfile) == -1 )
	  {
	    fprintf(stderr, "rename(%s, %s) failed: %s",
		    Qfile, nntpfile, errmsg(errno));
	    exit(-1);
	  }
	dprintf(stderr, "renamed %s to %s\n", Qfile, nntpfile);
      }
    }
  else { /*** NNTP file exists **/
    dprintf(stderr, "%s already exists\n", nntpfile);
    if (statb.st_size) {
      dprintf(stderr, "%s not empty\n", nntpfile);
    } else {
      dprintf(stderr, "%s is empty.\n", nntpfile);
      unlink(nntpfile);
      dprintf(stderr, "%s does not exist; waiting for %s\n", nntpfile, Qfile);
      
      waitingfor(Qfile);
      
      dprintf(stderr, "got %s\n", Qfile);

      if ( !In_Log_File ) {
	if ( rename(Qfile, nntpfile) == -1 )
	  {
	    dprintf(stderr, "rename(%s, %s) failed: %s",
		    Qfile, nntpfile, errmsg(errno));
	    exit(-1);
	  }
	dprintf(stderr, "renamed %s to %s\n", Qfile, nntpfile);
      }
    }
  }
  return(nntpfile);
}

void
  waitingfor(Qfile)
char *Qfile;
{   
  struct stat statb;
  int count = 0;

  dprintf(stderr,"entering waitingfor\n");fflush(stderr);

  if (Use_Log_File) {

    strcpy(Qfile, LOG_FILE);
    strcpy(nntpfile, LOG_FILE);
    dprintf(stderr,
	    "%s: switching to log file %s\n", Pname, Qfile); fflush(stderr);
    In_Log_File = TRUE;
    return;
  } else

  /** wait until batch file exists, but close link while waiting 
   ** if we exceed prescribed time-out
   **/

    while (stat(Qfile, &statb) == -1) {
      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();
	goodbye(WAIT);
	exit(0);
      }

      sleep(Sleep_Time);
    }
}
  
  /*
   ** OK, clean up any mess and requeue failed articles
   */
cleanup()
{
  dprintf(stderr, "%s: cleanup()\n", Pname);

  if (Qfp == (FILE *)NULL || Qfile == (char *)NULL)
    return;

  if (In_Log_File) {
    requeue((char *)NULL, (char *)NULL);
    FCLOSE(Qfp);
    return;
  }

  if ((ReQueue_Fails && (FailedArticle[0] != '\0')) || !feof(Qfp)) {
    rewrite();
  } else {
    /*
     ** Nothing to clean up after, reset stuff and
     ** nuke the queue file.
     */
    if (feof(Qfp)) {
      dprintf(stderr, "%s: unlink(%s)\n", Pname, nntpfile);
	
      if (unlink(nntpfile) < 0) {
	char	buf[BUFSIZ];
	
	sprintf(buf, E_unlk, nntpfile, errmsg(errno));
	log(L_WARNING, buf);
      }
    }
    FCLOSE(Qfp);
  }
}

/*
 ** Note that if I'm not running as "news" or "usenet" (or whatever
 ** account is supposed to own netnews), the resultant file will be the
 ** wrong ownership, permissions, etc.
 */
rewrite()
{
  register FILE	*tmpfp;
  char	*mode = "w+";
  char	*template = "/tmp/nntplinkXXXXXX";
  char	buf[BUFSIZ];
  static char	*tempfile = (char *)NULL;
  
  if (In_Log_File)
    return;

  dprintf(stderr, "%s: rewrite(%s)\n", Pname, nntpfile);
  
  if (tempfile == (char *)NULL)		/* should only need this once */
    tempfile = mktemp(template);
  
  if ((tmpfp = fopen(tempfile, mode)) == (FILE *)NULL) {
    sprintf(buf, E_fopen, tempfile, mode, errmsg(errno));
    log(L_WARNING, buf);
    FCLOSE(Qfp);
    return;
  }
  
  /*
   ** Requeue the rest of the queue file first,
   ** so that failed articles (if any) go to the end
   ** of the new file.
   */
  if (!feof(Qfp)) {
    dprintf(stderr, "%s: copying the unused portion of %s to %s\n",
	    Pname, nntpfile, tempfile);
    while(fgets(buf, sizeof(buf), Qfp) != (char *)NULL)
      (void) fputs(buf, tmpfp);
  }
  
  /*
   ** Here we write out the filenames of articles which
   ** failed at the remote end.
   */
  if (FailedArticle[0] != '\0') {
    fprintf(tmpfp, "%s\n", FailedArticle);
    dprintf(stderr, "%s: wrote %s to %s\n", Pname, FailedArticle, tempfile);
  }
  else {
    dprintf(stderr, "%s: no failed articles to rewrite.\n", Pname);
  }
  
  (void) fflush(tmpfp);
  /*
   ** If writing the temp file failed (maybe /tmp is full?)
   ** back out and leave the queue file exactly as it is.
   */
  if (ferror(tmpfp)) {
    sprintf(buf, "rewrite(): copy to %s failed", tempfile);
    log(L_WARNING, buf);
    FCLOSE(tmpfp);
    FCLOSE(Qfp);
    if (unlink(tempfile) < 0) {
      sprintf(buf, E_unlk, tempfile, errmsg(errno));
      log(L_WARNING, buf);
    }
    requeue((char *)NULL,(char *)NULL);		/* reset */
    return;
  }
  
  rewind(tmpfp);
#ifdef	FTRUNCATE
  rewind(Qfp);
  if (ftruncate(fileno(Qfp), (off_t)0) < 0) {
    sprintf(buf, "ftruncate(%s, 0): %s",
	    nntpfile, errmsg(errno));
    log(L_WARNING, buf);
    FCLOSE(Qfp);
    FCLOSE(tmpfp);
    if (unlink(tempfile) < 0) {
      sprintf(buf, E_unlk, tempfile, errmsg(errno));
      log(L_WARNING, buf);
    }
    requeue((char *)NULL,(char *)NULL);		/* reset */
    return;
  }
#else
  FCLOSE(Qfp);	/* we just nuked our lock here (lockfd) */
  if ((Qfp = fopen(nntpfile, mode)) == (FILE *)NULL)
    {
      sprintf(buf, E_fopen, nntpfile, mode, errmsg(errno));
      /*
	log(L_WARNING, buf);
	*/
      FCLOSE(tmpfp);
      if (unlink(tempfile) < 0) {
	sprintf(buf, E_unlk, tempfile, errmsg(errno));
	log(L_WARNING, buf);
      }
      requeue((char *)NULL,(char *)NULL);		/* reset */
      return;
    }
  /* Try to get our lock back (but continue whether we do or not) */
  (void) lockfd(fileno(Qfp), nntpfile, DONT_BLOCK);
#endif	FTRUNCATE
  
  dprintf(stderr, "%s: copying %s back to %s\n", Pname, tempfile, nntpfile);
  
  while(fgets(buf, sizeof(buf), tmpfp) != (char *)NULL)
    (void) fputs(buf, Qfp);
  
  (void) fflush(Qfp);
  if (ferror(Qfp)) {
    sprintf(buf, "rewrite(): copy to %s failed", nntpfile);
    log(L_WARNING, buf);
  }
  FCLOSE(tmpfp);
  FCLOSE(Qfp);
  if (unlink(tempfile) < 0) {
    sprintf(buf, E_unlk, tempfile, errmsg(errno));
    log(L_WARNING, buf);
  }
  requeue((char *)NULL,(char *)NULL);		/* reset */
  dprintf(stderr, "%s: rewrite(%s): done\n", Pname, nntpfile);
  return;
}
  
/*
 ** Save the failed article back to the batch file.
 ** Calling this with a NULL pointer resets the article.
 */
void
  requeue(article, mesgid)
char *article;
char *mesgid;
{
  /*
   * A NULL parameter means clear the failed article.  This is a hack.
   * This really doesn't belong here (should be a separate function),
   * but it's easy to do that later.
   */
  if (article == (char *)NULL) {
    dprintf(stderr, "%s: requeue(): reset\n", Pname);
    FailedArticle[0] = '\0';
    return;
  }
  
  /*
   * We should never have more than one failed article.
   * Scream loudly if we do.
   */
  if (FailedArticle[0] != '\0') {
    char buf[2*MAXFNAME];
    sprintf(buf, "Two failures: %s and %s\n", FailedArticle, article);
    log(L_NOTICE, buf);
    return;
  }
  
  dprintf(stderr, "%s: requeue(%s)\n", Pname, article);

  /**
   ** SAVE the Message-Id. We worked so hard to get it, we should save
   ** it.
   **
   ** This ifdef is silly, we're the only ones who are going to see this,
   **   and we really don't care if it's a \t or a " "..
   **/

  if (cnews)
    sprintf(FailedArticle, "%s %s", article, mesgid);
  else
    sprintf(FailedArticle, "%s\t%s", article, mesgid);

  /** (void)strncpy(FailedArticle, article, sizeof FailedArticle); **/
}