|
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 - metrics - downloadIndex: T q
Length: 7935 (0x1eff) Types: TextFile Names: »queue.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦f91e15335⟧ »EurOpenD3/news/nntp/nntplink2.0.0.tar.Z« └─⟦2c70c5e6b⟧ └─⟦this⟧ »queue.c«
#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); **/ }