|
|
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); **/
}