/*
* DSPOOLOUT.C
*
* Flush the outbound queue files and start up dnewslinks as appropriate
*
* (c)Copyright 1997, Matthew Dillon, All Rights Reserved. Refer to
* the COPYRIGHT file in the base directory of this distribution
* for specific rights granted.
*/
#include "defs.h"
#define TYPE_NORMAL 1
#define TYPE_XREPLIC 2
#define SF_NOSTREAM 0x0001
#define SF_REALTIME 0x0002
#define SF_NOBATCH 0x0004
#define SF_HEADFEED 0x0008
#define SF_NOCHECK 0x0010
#define SF_GENLINES 0x0020
#define SF_PRESBYTES 0x0040
#define SF_ARTSTAT 0x0080
#define SF_NOTIFY 0x0100
#define MAXLOGARTS 80 /* maximal length of the logarts string */
int MaxRun = 2;
int MinFlushSecs = 0; /* minimum time between flshs if queue not caught up */
typedef struct DNode {
struct DNode *no_Next;
char *no_SpoolFile;
} DNode;
DNode *Base;
void processDnewsfeeds(const char *qFile);
void processDspoolout(const char *fname, char *qFile);
int spool_file(char *spoolFile, int pass, NewslinkInfo *li, int flags);
DNode *FindNode(char *name);
void AddNode(char *name);
int VerboseOpt;
int ForReal = 1;
int Quiet;
int ForceRealTime = 0;
int TxBufSize = 0;
int RxBufSize = 0;
int QoS = 0;
char *OutboundIpStr = "-nop";
int
main(int ac, char **av)
{
char *qFile = NULL;
const char *cFile = NULL;
int oldFormat = 0;
OpenLog("dspoolout", (DebugOpt > 0 ? LOG_PERROR: 0) | LOG_NDELAY | LOG_PID);
LoadDiabloConfig(ac, av);
cFile = DNewsfeedsPat;
/*
* Maintain compatability with old format
*/
{
struct stat sb;
if (stat(PatLibExpand(DNNTPSpoolCtlPat), &sb) == 0) {
cFile = DNNTPSpoolCtlPat;
oldFormat = 1;
}
}
/*
* Shift into the out.going directory
*/
if (chdir(PatExpand(DQueueHomePat)) != 0) {
fprintf(stderr, "unable to chdir to %s\n", PatExpand(DQueueHomePat));
exit(1);
}
{
int i;
for (i = 1; i < ac; ++i) {
char *ptr = av[i];
if (*ptr == '-') {
ptr += 2;
switch(ptr[-1]) {
case 'B':
if (*ptr == 0)
ptr = av[++i];
OutboundIpStr = malloc(strlen(ptr) + 8);
sprintf(OutboundIpStr, "-B%s", ptr);
break;
case 'C':
if (*ptr == 0)
++i;
break;
case 'd':
DebugOpt = 1;
if (*ptr)
DebugOpt = strtol(ptr, NULL, 0);
break;
case 'f':
cFile = (*ptr) ? ptr : av[++i];
break;
case 'm':
MaxRun = strtol((*ptr ? ptr : av[++i]), NULL, 0);
break;
case 'n':
ForReal = 0;
break;
case 'p':
oldFormat = 1;
break;
case 'q':
Quiet = 1;
break;
case 'R':
RxBufSize = strtol((*ptr ? ptr : av[++i]), NULL, 0);
break;
case 'Q':
QoS = strtol((*ptr ? ptr : av[++i]), NULL, 0);
break;
case 'r':
ForceRealTime = 1;
break;
case 's':
MinFlushSecs = strtol((*ptr ? ptr : av[++i]), NULL, 0) * 60;
break;
case 'T':
TxBufSize = strtol((*ptr ? ptr : av[++i]), NULL, 0);
break;
case 'V':
PrintVersion();
break;
case 'v':
VerboseOpt = 1;
break;
default:
break;
}
} else {
qFile = ptr;
}
}
}
if (DebugOpt && qFile != NULL)
printf("Processing label: %s\n", qFile);
if (oldFormat || strstr(PatLibExpand(cFile), "dspoolout") != NULL) {
processDspoolout(PatLibExpand(cFile), qFile);
} else {
DNewsfeedsPat = cFile;
processDnewsfeeds(qFile);
}
return(0);
}
void
processDnewsfeeds(const char *qFile)
{
int sfCount = 200;
int *sfAry = malloc(sfCount * sizeof(int));
int pass;
int hour;
{
struct tm *tp;
time_t t;
t=time(0);
tp=localtime(&t);
hour=tp->tm_hour;
}
if (DebugOpt > 1)
printf("Using dnewsfeeds for feed config\n");
LoadNewsFeed(0, 1, NULL);
/*
* Get list of spoolfile names and NNTP hosts, one pair per line,
* blank lines and lines beginning with '#' excepted.
*/
for (pass = 1; pass <= 2; ++pass) {
LabelList *ll;
NewslinkInfo *li;
int count = 0;
for (ll = FeedLinkLabelList(); ll != NULL && ll->label != NULL;
ll = ll->next) {
int flags = 0;
li = FeedLinkInfo(ll->label);
if (li == NULL)
continue;
if (qFile != NULL && strcmp(ll->label, qFile) != 0)
continue;
if (li->li_Hours != NULL) {
int found = 0;
int hourbegin;
int hourend;
char *hourinterval;
char *minus;
if ((hourinterval=strtok(li->li_Hours,",")) != NULL) {
while (hourinterval != NULL) {
hourbegin=strtol(hourinterval,NULL,0);
if ((minus=strstr(hourinterval,"-")) != NULL)
hourend=strtol(minus+1,NULL,0);
else
hourend=hourbegin;
if (hourbegin <= hourend) {
if (hour >= hourbegin && hour <= hourend)
found=1;
} else {
if (hour >= hourbegin || hour <= hourend)
found=1;
}
hourinterval=strtok(NULL,",");
}
}
if (found == 0)
continue;
}
flags = flags | (li->li_NoStream ? SF_NOSTREAM : 0);
flags = flags | (li->li_RealTime ? SF_REALTIME : 0);
flags = flags | (li->li_Notify ? SF_NOTIFY : 0);
flags = flags | (li->li_HeadFeed ? SF_HEADFEED : 0);
flags = flags | (li->li_Check ? 0 : SF_NOCHECK);
flags = flags | (li->li_GenLines ? SF_GENLINES : 0);
flags = flags | (li->li_PreserveBytes ? SF_PRESBYTES : 0);
flags = flags | (li->li_ArticleStat ? SF_ARTSTAT : 0);
if (flags & SF_NOTIFY && !(flags & SF_REALTIME))
flags &= ~SF_NOTIFY;
/*
* run spool file, with flags modifier from pass 1. Pass1
* may clear the SF_REALTIME flag.
*/
if (count >= sfCount) {
sfCount += 200;
sfAry = realloc(sfAry, sfCount * sizeof(int));
memset(sfAry+count, 0, (sfCount - count) * sizeof(int));
}
if (pass == 2) {
flags = (flags & ~SF_REALTIME) |
(sfAry[count] & SF_REALTIME);
}
flags = spool_file(ll->label, pass, li, flags);
if (pass == 1)
sfAry[count] = flags;
++count;
}
if (pass == 1) {
char sysline[256];
snprintf(sysline, sizeof(sysline), "%s/dbin/dicmd flush", NewsHome);
if (ForReal)
system(sysline);
}
}
}
void
processDspoolout(const char *fname, char *qFile)
{
int sfCount = 200;
int *sfAry = malloc(sfCount * sizeof(int));
int pass;
int hour;
FILE *fi;
char buf[256];
{
struct tm *tp;
time_t t;
t=time(0);
tp=localtime(&t);
hour=tp->tm_hour;
}
if (*fname != '/') {
char *p = malloc(strlen(fname) + strlen(NewsHome) + 3);
sprintf(p, "%s/%s", NewsHome, fname);
fname = p;
}
printf("Using legacy dnntpspool.ctl format from %s\n", fname);
/*
* Get list of spoolfile names and NNTP hosts, one pair per line,
* blank lines and lines beginning with '#' excepted.
*/
for (pass = 1; pass <= 2; ++pass) {
if ((fi = fopen(fname, "r")) != NULL) {
int count = 0;
while (fgets(buf, sizeof(buf), fi) != NULL) {
char *spoolFile;
char *hostName;
if (buf[0] == '\n' || buf[0] == '#')
continue;
if ((spoolFile = strtok(buf, " \t\n")) != NULL &&
(hostName = strtok(NULL, " \t\n")) != NULL &&
(qFile == NULL || strcmp(spoolFile, qFile) == 0)
) {
int maxq = -1;
int port = -1;
int maxr = MaxRun;
int type = TYPE_NORMAL;
int delay = 0;
int flags = 0;
int qskip = 0;
int compress = 0;
int txbufsiz = TxBufSize;
int rxbufsiz = RxBufSize;
int qos = QoS;
int maxstream = 0;
char *obip = NULL;
char *hours = NULL;
char *logarts = NULL;
{
char *maxqStr;
while ((maxqStr = strtok(NULL, " \t\n")) != NULL) {
if (strtol(maxqStr, NULL, 0) > 0) {
maxq = strtol(maxqStr, NULL, 0);
} else if (strcmp(maxqStr, "xreplic") == 0) {
type = TYPE_XREPLIC;
} else if (strcmp(maxqStr, "nostream") == 0) {
flags |= SF_NOSTREAM;
} else if (strcmp(maxqStr, "headfeed") == 0) {
flags |= SF_HEADFEED;
} else if (strcmp(maxqStr, "preservebytes") == 0) {
flags |= SF_PRESBYTES;
} else if (strcmp(maxqStr, "ignorebytes") == 0) {
flags |= SF_PRESBYTES;
} else if (strcmp(maxqStr, "nocheck") == 0) {
flags |= SF_NOCHECK;
} else if (strcmp(maxqStr, "realtime") == 0) {
flags |= SF_REALTIME;
} else if (strcmp(maxqStr, "nobatch") == 0) {
flags |= SF_NOBATCH;
} else if (strcmp(maxqStr, "genlines") == 0) {
flags |= SF_GENLINES;
} else if (strcmp(maxqStr, "notify") == 0) {
flags |= SF_NOTIFY;
} else if (strcmp(maxqStr, "compress") == 0) {
compress = 1;
} else if (strcmp(maxqStr, "logarts") == 0) {
logarts = "all";
} else if (strncmp(maxqStr, "logarts=", 8) == 0) {
/* we should check for validity of the parameter here */
logarts = maxqStr + 8;
} else if (strncmp(maxqStr, "bind=", 5) == 0) {
obip = maxqStr + 5;
} else if (strncmp(maxqStr, "hours=", 6) == 0) {
hours = maxqStr + 6;
} else if (maxqStr[0] == 'q') {
qskip = strtol(maxqStr + 1, NULL, 0);
} else if (maxqStr[0] == 'n') {
maxr = strtol(maxqStr + 1, NULL, 0);
} else if (maxqStr[0] == 'p') {
port = strtol(maxqStr + 1, NULL, 0);
} else if (maxqStr[0] == 'd') {
delay = strtol(maxqStr + 1, NULL, 0);
} else if (maxqStr[0] == 'T') {
txbufsiz = strtol(maxqStr + 1, NULL, 0);
} else if (maxqStr[0] == 'R') {
rxbufsiz = strtol(maxqStr + 1, NULL, 0);
} else if (maxqStr[0] == 'Q') {
qos = strtol(maxqStr + 1, NULL, 0);
} else if (maxqStr[0] == 'M') {
maxstream = strtol(maxqStr + 1, NULL, 0);
} else {
if (pass == 1)
fprintf(stderr, "bad keyword in control file: %s\n", maxqStr);
}
}
}
if (hours != NULL) {
int found = 0;
int hourbegin;
int hourend;
char *hourinterval;
char *minus;
if ((hourinterval=strtok(hours,",")) != NULL) {
while (hourinterval != NULL) {
hourbegin=strtol(hourinterval,NULL,0);
if ((minus=strstr(hourinterval,"-")) != NULL)
hourend=strtol(minus+1,NULL,0);
else
hourend=hourbegin;
if (hourbegin <= hourend) {
if (hour >= hourbegin && hour <= hourend)
found=1;
} else {
if (hour >= hourbegin || hour <= hourend)
found=1;
}
hourinterval=strtok(NULL,",");
}
}
if (found == 0)
continue;
}
/*
* run spool file, with flags modifier from pass 1. Pass1
* may clear the SF_REALTIME flag.
*/
if (count >= sfCount) {
sfCount += 200;
sfAry = realloc(sfAry, sfCount * sizeof(int));
memset(sfAry+count, 0, (sfCount - count) * sizeof(int));
}
if (pass == 2) {
flags = (flags & ~SF_REALTIME) |
(sfAry[count] & SF_REALTIME);
}
{
NewslinkInfo li;
li.li_HostName = hostName;
li.li_MaxQueueFile = maxq;
li.li_MaxParallel = maxr;
li.li_Port = port;
li.li_StartDelay = delay;
li.li_TransmitBuf = txbufsiz;
li.li_ReceiveBuf = rxbufsiz;
li.li_QoS = qos;
li.li_LogArts = logarts;
li.li_BindAddress = obip;
li.li_MaxStream = 0;
li.li_Compress = compress;
li.li_QueueSkip = qskip;
flags = spool_file(spoolFile, pass, &li, flags);
/*
flags = spool_file(
spoolFile,
hostName,
maxq,
maxr,
qskip,
port,
delay,
type,
flags,
obip,
txbufsiz,
rxbufsiz,
logarts,
pass,
maxstream
);
*/
}
if (pass == 1)
sfAry[count] = flags;
++count;
}
}
fclose(fi);
} else if (pass == 1) {
fprintf(stderr, "Unable to open %s\n", fname);
}
if (pass == 1) {
char sysline[256];
snprintf(sysline, sizeof(sysline), "%s/dbin/dicmd flush", NewsHome);
system(sysline);
}
}
}
/*
* SPOOL_FILE() - pass 1 - rename spool files
*
* pass 2 - start dnewslink processes
*/
int
spool_file(char *spoolFile, int pass, NewslinkInfo *li, int flags)
{
char seqFile[256];
char newFile[256];
char obIpBuf[256];
char *outboundIpStr = OutboundIpStr;
int begSeq = 0;
int endSeq = 0;
long newTime = 0;
char portBuf[32];
char logartsStr[MAXLOGARTS+2];
int fd;
struct stat st;
char txBufSizeStr[32];
char rxBufSizeStr[32];
char QoSStr[32];
char maxStreamStr[32];
char compressStr[32];
char delayStr[32];
if (VerboseOpt)
printf("spool_file(%s, %d, %s, %d)\n",
spoolFile, pass, li->li_HostName, flags);
/*
* Initialize rx/txBufSizeStr
*/
sprintf(txBufSizeStr, "-nop");
sprintf(rxBufSizeStr, "-nop");
sprintf(QoSStr, "-nop");
sprintf(maxStreamStr, "-nop");
sprintf(compressStr, "-nop");
sprintf(delayStr, "-nop");
if (li->li_TransmitBuf > 0 && li->li_TransmitBuf < 16 * 1024 * 1024)
sprintf(txBufSizeStr, "-T%d", li->li_TransmitBuf);
if (li->li_ReceiveBuf > 0 && li->li_ReceiveBuf < 16 * 1024 * 1024)
sprintf(rxBufSizeStr, "-R%d", li->li_ReceiveBuf);
if (li->li_QoS > 0 && li->li_QoS <= 0xff )
sprintf(QoSStr, "-Q%d", li->li_QoS);
if (li->li_MaxStream > 0)
sprintf(maxStreamStr, "-M%d", li->li_MaxStream);
if (li->li_Compress > 0)
sprintf(compressStr, "-Z%d", li->li_Compress);
if (li->li_DelayFeed > 0)
sprintf(delayStr, "-W%d", li->li_DelayFeed);
/*
* Outbound article logging.
*/
sprintf(logartsStr, "-nop");
if (li->li_LogArts && *li->li_LogArts) {
strcpy(logartsStr, "-A");
StrnCpyNull(logartsStr+2, li->li_LogArts, MAXLOGARTS);
}
/*
* Override outbound IP
*/
if (li->li_BindAddress != NULL &&
strlen(li->li_BindAddress) < sizeof(obIpBuf) - 8) {
sprintf(obIpBuf, "-B%s", li->li_BindAddress);
outboundIpStr = obIpBuf;
}
if (li->li_Port <= 0)
li->li_Port = 119;
sprintf(portBuf, "%d", li->li_Port);
sprintf(seqFile, ".%s.seq", spoolFile);
/*
* Get beginning and ending sequence numbers
*/
fd = open(seqFile, O_RDWR|O_CREAT, 0600);
if (fd >= 0) {
char buf[64];
xflock(fd, XLOCK_EX); /* lock and leave locked */
memset(buf, 0, sizeof(buf));
read(fd, buf, sizeof(buf) - 1);
sscanf(buf, "%d %d %lx", &begSeq, &endSeq, &newTime);
}
/*
* Discard beginning sequence numbers that are now deleted, or
* delete queue files that are too old.
*/
while (begSeq < endSeq) {
sprintf(newFile, "%s.S%05d", spoolFile, begSeq);
if (li->li_MaxQueueFile > 0 && begSeq < endSeq - li->li_MaxQueueFile)
remove(newFile);
if (stat(newFile, &st) == 0)
break;
++begSeq;
}
/*
* If primary spool file exists, shift to primary
* queue
*/
if (pass == 1) {
{
int tries = 100;
int32 dt;
struct stat st;
while (tries > 0) {
sprintf(newFile, "%s.S%05d", spoolFile, endSeq);
if (stat(newFile, &st) < 0)
break;
--tries;
++endSeq;
}
/*
* Only create a new spool file if:
*
* (1) endSeq == begSeq + 1, or
* (2) current time larger then newTime + MinFlushSecs
* (3) there is time weirdness
*/
dt = time(NULL) - ((int32)newTime + MinFlushSecs);
if (VerboseOpt)
printf("PASS %d: dt=%d tries=%d begSeq=%d endSeq=%d\n",
pass, dt, tries, begSeq, endSeq);
if (endSeq <= begSeq + 4 || dt > 0 || dt < -MinFlushSecs) {
/*
* If a dnewslink has a lock on the unsequenced spool file,
* clear the SF_REALTIME flag... a realtime dnewslink is
* already running so there is no sense trying to start
* another one.
*/
if (flags & SF_REALTIME) {
int tfd;
if ((tfd = open(spoolFile, O_RDWR)) >= 0) {
if (xflock(tfd, XLOCK_EX|XLOCK_NB) < 0) {
if (VerboseOpt)
printf("%s: realtime already\n", spoolFile);
flags &= ~SF_REALTIME;
}
close(tfd);
}
}
if (stat(spoolFile, &st) == 0 && st.st_size > 0 &&
rename(spoolFile, newFile) == 0) {
++endSeq;
if (!Quiet)
printf("dspoolout: add %s\n", newFile);
} else {
if (VerboseOpt && !Quiet)
printf("dspoolout: nofile %s\n", newFile);
if (endSeq == begSeq)
AddNode(spoolFile);
}
if (flags & SF_REALTIME) {
int fd = xopen(O_RDWR|O_CREAT, 0644, spoolFile);
if (fd != -1) {
close(fd);
}
}
newTime = time(NULL);
} else {
AddNode(spoolFile);
if (VerboseOpt && !Quiet)
printf("dspoolout: wait %s\n", spoolFile);
}
}
/*
* Update sequence number file
*/
if (fd >= 0) {
char buf[64];
sprintf(buf, "%5d %5d %08lx\n", begSeq, endSeq, newTime);
lseek(fd, 0L, 0);
write(fd, buf, strlen(buf));
ftruncate(fd, lseek(fd, 0L, 1));
}
}
if (fd >= 0) {
xflock(fd, XLOCK_UN);
close(fd);
}
/*
* Run up to N newslink's/innxmit's, usually set at 2.
*
* Note that we spool out the queue as a FIFO. This is important as
* it reduces article jumble.
*/
if (pass == 2 && FindNode(spoolFile) == NULL) {
int tries = li->li_MaxParallel;
int look;
/*
* Start up to MaxParallel dnewslinks. If the nobatch
* flag is set, do not start any.
*/
if (flags & SF_NOBATCH)
tries = 0;
for (look = 0; look < 32 && tries &&
begSeq + look < endSeq - li->li_QueueSkip; ++look) {
int use = begSeq + look;
int fd;
char numBuf[32];
{
int left = endSeq - use - li->li_QueueSkip;
if (left > 32)
left = 32;
if (left < 3 && li->li_QueueSkip == 0)
left = 3;
else if (left < 1)
left = 1;
sprintf(numBuf, "%d", left);
if (VerboseOpt)
printf("PASS %d: look=%d tries=%d begSeq=%d endSeq=%d use=%d left=%d\n",
pass, look, tries, begSeq, endSeq, use, left);
}
sprintf(newFile, "%s.S%05d", spoolFile, use);
if ((fd = open(newFile, O_RDWR)) >= 0) {
if (xflock(fd, XLOCK_EX|XLOCK_NB) == 0) {
char seqName[64];
char templateFile[256];
xflock(fd, XLOCK_UN);
if (!Quiet)
printf("dspoolout: run %s.S%05d\n", spoolFile, use);
sprintf(templateFile, "%s.S%%05d", spoolFile);
sprintf(seqName, "%d", use);
if (VerboseOpt)
printf("%s %s%s %s%s %s%s %s%s %s%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
"dnewslink",
"-h", li->li_HostName,
"-b", templateFile,
"-S", seqName,
"-N", numBuf,
"-P", portBuf,
"-D",
((flags & SF_NOSTREAM) ? "-i" : "-nop"),
((flags & SF_HEADFEED) ?
((flags & SF_PRESBYTES) ? "-HB" : "-H") :
"-nop"),
((flags & SF_NOCHECK) ? "-I" : "-nop"),
((flags & SF_GENLINES) ? "-L" : "-nop"),
((flags & SF_ARTSTAT) ? "-x" : "-nop"),
compressStr,
logartsStr,
outboundIpStr,
txBufSizeStr,
rxBufSizeStr,
QoSStr,
delayStr,
maxStreamStr
);
if (ForReal && fork() == 0) {
char binPath[128];
if (li->li_StartDelay > 0) {
if (xflock(fd, XLOCK_EX|XLOCK_NB) == 0) {
sleep(li->li_StartDelay);
xflock(fd, XLOCK_UN);
} else {
if (DebugOpt)
printf(" qfile already locked for delay\n");
exit(0);
}
}
if (li->li_Priority > 0)
nice(li->li_Priority);
snprintf(binPath, sizeof(binPath), "%s/dbin/dnewslink", NewsHome);
execl(binPath, "dnewslink",
"-h", li->li_HostName,
"-b", templateFile,
"-S", seqName,
"-N", numBuf,
"-P", portBuf,
"-D",
((flags & SF_NOSTREAM) ? "-i" : "-nop"),
((flags & SF_HEADFEED) ?
((flags & SF_PRESBYTES) ? "-HB" : "-H") :
"-nop"),
((flags & SF_NOCHECK) ? "-I" : "-nop"),
((flags & SF_GENLINES) ? "-L" : "-nop"),
((flags & SF_ARTSTAT) ? "-x" : "-nop"),
compressStr,
logartsStr,
outboundIpStr,
txBufSizeStr,
rxBufSizeStr,
QoSStr,
delayStr,
maxStreamStr,
NULL
);
exit(0);
}
}
--tries; /* even if lock fails */
close(fd);
}
}
/*
* Deal with the realtime dnewslink, but only if:
* The realtime flag is set
* We have not gotten behind
* We did not detect another realtime process
*/
if (VerboseOpt)
printf("%s: flags %02x nseq %d\n", spoolFile, flags & SF_REALTIME, endSeq-begSeq);
if ((flags & SF_REALTIME) &&
(ForceRealTime || (endSeq - begSeq <= 2))) {
int fd;
if ((fd = open(spoolFile, O_RDWR|O_CREAT, 0600)) >= 0) {
if (xflock(fd, XLOCK_EX|XLOCK_NB) == 0) {
xflock(fd, XLOCK_UN);
if (!Quiet)
printf("dspoolout: run realtime %s\n", spoolFile);
if (VerboseOpt)
printf("%s %s%s %s%s %s%s %s%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
"dnewslink",
"-h", li->li_HostName,
"-b", spoolFile,
"-P", portBuf,
"-N", "100", /* 1000 spool cycles */
((li->li_StartDelay < 0) ? "-r-1" : "-r"),
((flags & SF_NOTIFY) ? "-o" : "-nop"),
((flags & SF_NOTIFY) ? spoolFile : "-nop"),
((flags & SF_NOSTREAM) ? "-i" : "-nop"),
((flags & SF_HEADFEED) ?
((flags & SF_PRESBYTES) ? "-HB" : "-H") :
"-nop"),
(((flags & SF_NOCHECK)||(li->li_Check==2)) ? "-I" : "-nop"),
((flags & SF_GENLINES) ? "-L" : "-nop"),
((flags & SF_ARTSTAT) ? "-x" : "-nop"),
compressStr,
logartsStr,
outboundIpStr,
txBufSizeStr,
rxBufSizeStr,
delayStr,
maxStreamStr
);
if (ForReal && fork() == 0) {
char binPath[128];
if (li->li_StartDelay > 0)
sleep(li->li_StartDelay);
if (li->li_Priority > 0)
nice(li->li_Priority);
snprintf(binPath, sizeof(binPath), "%s/dbin/dnewslink", NewsHome);
/*
* realtime option is '-r'. If a delay of -1
* is specified, we pass -r-1 to dnewslink which
* reduces the tail latency from 1 second to 1ms.
*/
execl(binPath, "dnewslink",
"-h", li->li_HostName,
"-b", spoolFile,
"-P", portBuf,
"-N", "100", /* 1000 spool cycles */
((li->li_StartDelay < 0) ? "-r-1" : "-r"),
((flags & SF_NOTIFY) ? "-o" : "-nop"),
((flags & SF_NOTIFY) ? spoolFile : "-nop"),
((flags & SF_NOSTREAM) ? "-i" : "-nop"),
((flags & SF_HEADFEED) ?
((flags & SF_PRESBYTES) ? "-HB" : "-H") :
"-nop"),
(((flags & SF_NOCHECK)||(li->li_Check==2)) ? "-I" : "-nop"),
((flags & SF_GENLINES) ? "-L" : "-nop"),
((flags & SF_ARTSTAT) ? "-x" : "-nop"),
compressStr,
logartsStr,
outboundIpStr,
txBufSizeStr,
rxBufSizeStr,
delayStr,
maxStreamStr,
NULL
);
exit(0);
}
}
close(fd);
}
}
}
return(flags);
}
DNode *
FindNode(char *name)
{
DNode *node;
for (node = Base; node; node = node->no_Next) {
if (strcmp(name, node->no_SpoolFile) == 0)
break;
}
return(node);
}
void
AddNode(char *name)
{
DNode *node = malloc(sizeof(Node) + strlen(name) + 1);
if (!node) {
fprintf(stderr, "unable to malloc in AddNode\n");
exit(1);
}
node->no_Next = Base;
node->no_SpoolFile = (char *)(node + 1);
Base = node;
strcpy(node->no_SpoolFile, name);
}
syntax highlighted by Code2HTML, v. 0.9.1