#include "defs.h"
#if NEED_TERMIOS
#include <sys/termios.h>
#endif
typedef struct Feed {
struct Feed *fe_Next;
char *fe_Label;
int fe_Fd;
char *fe_Buf;
int fe_BufIdx;
int fe_BufMax;
int fe_Failed;
} Feed;
Feed *FeBase;
MemPool *ParProcMemPool;
char *MySpoolHome;
int fwCallBack(const char *hlabel, const char *msgid, const char *path, const char *offsize, int plfo, int headOnly, const char *artType, const char *cSize);
void writeFeedOut(const char *label, const char *file, const char *msgid, const char *offSize, int rt, int headOnly, const char *cSize);
void flushFeeds(int justClose);
void flushFeedOut(Feed *fe);
void
Usage(void)
{
fprintf(stderr, "Requeue articles for a feed or all feeds from DUMP lines (usually written\n");
fprintf(stderr, "from diloadfromspool) on stdin.\n\n");
fprintf(stderr, "Usage: drequeue [-a] [-C file] [-d[n]] [-f file] [-s] [-V] [label]\n");
fprintf(stderr, " where:\n");
fprintf(stderr, "\t-a\t- requeue for all labels in dnewsfeeds\n");
fprintf(stderr, "\t-C file\t- specify diablo.config to use\n");
fprintf(stderr, "\t-d[n]\t- set debug [with optional level]\n");
fprintf(stderr, "\t-f file\t- specify the dnewsfeeds filename\n");
fprintf(stderr, "\t-s\t- print each line to stdout and to labels\n");
fprintf(stderr, "\t-V\t- print version and exit\n");
fprintf(stderr, "\tlabel\t- only requeue entries for specified dnewsfeeds label\n");
exit(1);
}
int
main(int ac, char **av)
{
char buf[8192];
char *s1;
char *hlabel = NULL;
int i;
int sendStdout = 0;
int doAll = 0;
LoadDiabloConfig(ac, av);
/*
* Extract the spool home pattern into a real path and place
* in MySpoolHome
*/
{
int l = strlen(PatExpand(SpoolHomePat)) + 1;
MySpoolHome = malloc(l);
snprintf(MySpoolHome, l, PatExpand(SpoolHomePat));
}
for (i = 1; i < ac; ++i) {
char *ptr = av[i];
if (*ptr != '-') {
hlabel = ptr;
} else {
ptr++;
switch(*ptr) {
case 'a':
doAll = 1;
break;
case 'C':
break;
case 'd':
DebugOpt = atoi(*ptr ? ptr : av[++i]);
break;
case 'f':
DNewsfeedsPat = *ptr ? ptr : av[++i];
break;
case 's':
sendStdout = 1;
break;
case 'V':
PrintVersion();
break;
default:
Usage();
}
}
}
if (hlabel == NULL && doAll == 0)
Usage();
if (hlabel != NULL)
printf("Requeueing for label: %s\n", hlabel);
LoadNewsFeed(0, 1, hlabel);
while (!feof(stdin)) {
fgets(buf, sizeof(buf), stdin);
s1 = strtok(buf, " \t\n");
if (s1 == NULL)
continue;
if (strncmp(s1, "SOUT", 4) == 0) {
char *path = strtok(NULL, "\t\n");
char *offsize = strtok(NULL, "\t\n");
const char *msgid = MsgId(strtok(NULL, "\t\n"), NULL);
char *nglist = strtok(NULL, "\t\n");
char *dist = strtok(NULL, "\t\n");
char *npath = strtok(NULL, "\t\n");
char *headOnly = strtok(NULL, "\t\n");
const char *artType = strtok(NULL, "\t\n");
const char *cSize = strtok(NULL, "\t\n");
if (path && offsize && msgid && nglist) {
int spamArt = 0;
if (npath == NULL) npath = "1";
if (headOnly == NULL) headOnly = "0";
if (artType == NULL) artType = "000000";
if (cSize != NULL && strcmp(cSize, "0") == 0) cSize = NULL;
if (sendStdout)
printf(
"SOUTLINE: %s %s %s %s %s HO=%s AT=%s %s\n",
path,
offsize,
msgid,
nglist,
npath,
headOnly,
artType,
cSize != NULL ? cSize : ""
);
FeedWrite(0, fwCallBack, msgid, path, offsize, nglist, npath, dist, headOnly, artType, spamArt, cSize);
}
}
}
flushFeeds(0);
exit(0);
}
int
fwCallBack(const char *hlabel, const char *msgid, const char *path, const char *offsize, int plfo, int headOnly, const char *artType, const char *cSize)
{
writeFeedOut(hlabel, path, msgid, offsize, ((plfo > 0) ? 1 : 0), headOnly, cSize);
return(0);
}
void
writeFeedOut(const char *label, const char *file, const char *msgid, const char *offSize, int rt, int headOnly, const char *cSize)
{
Feed *fe;
/*
* locate feed
*/
for (fe = FeBase; fe; fe = fe->fe_Next) {
if (strcmp(label, fe->fe_Label) == 0)
break;
}
/*
* allocate feed if not found
*/
if (fe == NULL) {
fe = zalloc(&ParProcMemPool, sizeof(Feed) + strlen(label) + 1);
fe->fe_Label = (char *)(fe + 1);
strcpy(fe->fe_Label, label);
fe->fe_Fd = xopen(O_APPEND|O_RDWR|O_CREAT, 0644, "%s/%s", PatExpand(DQueueHomePat), label);
if (fe->fe_Fd >= 0) {
int bsize;
fe->fe_Buf = pagealloc(&bsize, 1);
fe->fe_BufMax = bsize;
fe->fe_BufIdx = 0;
fe->fe_Failed = 0;
}
fe->fe_Next = FeBase;
FeBase = fe;
}
/*
* write to buffered feed, flushing buffers if there is not enough
* room. If the line is too long, something has gone wrong and we
* throw it away.
*
* note that we cannot fill the buffer to 100%, because the trailing
* nul (which we do not write) will overrun it. I temporarily add 4 to
* l instead of 3 to include the trailing nul in the calculations, but
* subtract it off after the actual copy operation.
*/
if (fe->fe_Fd >= 0) {
int l = strlen(file) + strlen(msgid) + strlen(offSize) + (3 + 32 + 1);
/*
* line would be too long?
*/
if (l < fe->fe_BufMax) {
/*
* line fits in buffer with trailing nul ?
*/
if (l >= fe->fe_BufMax - fe->fe_BufIdx)
flushFeedOut(fe);
sprintf(fe->fe_Buf + fe->fe_BufIdx, "%s %s %s%s%s%s\n",
file, msgid, offSize,
(headOnly ? " H" : ""),
(cSize != NULL ? " C" : ""),
(cSize != NULL ? cSize : "")
);
fe->fe_BufIdx += strlen(fe->fe_Buf + fe->fe_BufIdx);
if (rt)
flushFeedOut(fe);
}
}
}
void
flushFeeds(int justClose)
{
Feed *fe;
while ((fe = FeBase) != NULL) {
if (justClose == 0)
flushFeedOut(fe);
if (fe->fe_Buf)
pagefree(fe->fe_Buf, 1);
if (fe->fe_Fd >= 0)
close(fe->fe_Fd);
fe->fe_Fd = -1;
fe->fe_Buf = NULL;
FeBase = fe->fe_Next;
zfree(&ParProcMemPool, fe, sizeof(Feed) + strlen(fe->fe_Label) + 1);
}
}
void
flushFeedOut(Feed *fe)
{
if (fe->fe_BufIdx && fe->fe_Buf && fe->fe_Fd >= 0) {
/*
* flush buffer. If the write fails, we undo it to ensure
* that we do not get garbaged feed files.
*/
int n = write(fe->fe_Fd, fe->fe_Buf, fe->fe_BufIdx);
if (n >= 0 && n != fe->fe_BufIdx) {
ftruncate(fe->fe_Fd, lseek(fe->fe_Fd, 0L, 1) - n);
}
if (n != fe->fe_BufIdx && fe->fe_Failed == 0) {
fe->fe_Failed = 1;
logit(LOG_INFO, "failure writing to feed %s", fe->fe_Label);
}
}
fe->fe_BufIdx = 0;
}
syntax highlighted by Code2HTML, v. 0.9.1