inn-1.7.2/0040755000175100001440000000000006443072143010634 5ustar mdusersinn-1.7.2/syslog/0040755000175100001440000000000006443103542012152 5ustar mdusersinn-1.7.2/syslog/syslogd.80100644000175100001440000001222406443103542013725 0ustar mdusers.\" $Revision: 1.2 $ .\" Copyright (c) 1983, 1986 The Regents of the University of California. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms are permitted provided .\" that: (1) source distributions retain this entire copyright notice and .\" comment, and (2) distributions including binaries display the following .\" acknowledgement: ``This product includes software developed by the .\" University of California, Berkeley and its contributors'' in the .\" documentation or other materials provided with the distribution and in .\" all advertising materials mentioning features or use of this software. .\" Neither the name of the University nor the names of its contributors may .\" be used to endorse or promote products derived from this software without .\" specific prior written permission. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .\" @(#)syslogd.8 6.8 (Berkeley) 6/27/90 .\" .TH SYSLOGD 8 "June 27, 1990" .UC 5 .SH NAME syslogd \- log systems messages .SH SYNOPSIS .B syslogd [ .BI \-f configfile ] [ .BI \-m markinterval ] [ .B \-d ] .SH DESCRIPTION .I Syslogd reads and logs messages into a set of files described by the configuration file /etc/syslog.conf. Each message is one line. A message can contain a priority code, marked by a number in angle braces at the beginning of the line. Priorities are defined in .RI < sys/syslog.h >. .I Syslogd reads from the UNIX domain socket .IR /dev/log , from an Internet domain socket specified in .IR /etc/services , and from the special device .I /dev/klog (to read kernel messages). .PP .I Syslogd configures when it starts up and whenever it receives a hangup signal. Lines in the configuration file have a .I selector to determine the message priorities to which the line applies and an .IR action . The .I action field are separated from the selector by one or more tabs. .PP Selectors are semicolon separated lists of priority specifiers. Each priority has a .I facility describing the part of the system that generated the message, a dot, and a .I level indicating the severity of the message. Symbolic names may be used. An asterisk selects all facilities. All messages of the specified level or higher (greater severity) are selected. More than one facility may be selected using commas to separate them. For example: .PP .ti +5 *.emerg;mail,daemon.crit .PP Selects all facilities at the .I emerg level and the .I mail and .I daemon facilities at the .I crit level. .PP Known facilities and levels recognized by .I syslogd are those listed in .IR syslog (3) without the leading ``LOG_''. The additional facility ``mark'' has a message at priority LOG_INFO sent to it every 20 minutes (this may be changed with the .B \-m flag). The ``mark'' facility is not enabled by a facility field containing an asterisk. The level ``none'' may be used to disable a particular facility. For example, .PP .ti +5 *.debug;mail.none .PP Sends all messages .I except mail messages to the selected file. .PP The second part of each line describes where the message is to be logged if this line is selected. There are four forms: .IP \(bu 3n A filename (beginning with a leading slash). The file will be opened in append mode. .IP \(bu 3n A hostname preceeded by an at sign (``@''). Selected messages are forwarded to the .I syslogd on the named host. .IP \(bu 3n A comma separated list of users. Selected messages are written to those users if they are logged in. .IP \(bu 3n An asterisk. Selected messages are written to all logged-in users. .PP Blank lines and lines beginning with `#' are ignored. .PP For example, the configuration file: .PP .nf .ta 4m +\w'*.alert,auth.warning'u+3 kern,mark.debug /dev/console *.notice;mail.info /var/log/maillog *.crit /var/log/critical kern.err @ucbarpa *.emerg * *.alert eric,kridle *.alert;auth.warning ralph .fi .PP logs all kernel messages and 20 minute marks onto the system console, all notice (or higher) level messages and all mail system messages except debug messages into the file /var/log/maillog, and all critical messages into /var/log/critical; kernel messages of error severity or higher are forwarded to ucbarpa. All users will be informed of any emergency messages, the users ``eric'' and ``kridle'' will be informed of any alert messages, and the user ``ralph'' will be informed of any alert message, or any warning message (or higher) from the authorization system. .PP The flags are: .TP 0.5i .B \-f Specify an alternate configuration file. .TP .B \-m Select the number of minutes between mark messages. .TP .B \-d Turn on debugging. .PP .I Syslogd creates the file /var/run/syslog.pid, if possible, containing a single line with its process id. This can be used to kill or reconfigure .I syslogd. .PP To bring .I syslogd down, it should be sent a terminate signal (e.g. kill \`cat /var/run/syslog.pid\`). .SH FILES .ta \w'/etc/syslog.conf 'u .nf /etc/syslog.conf the configuration file /var/run/syslog.pid the process id /dev/log Name of the UNIX domain datagram log socket /dev/klog The kernel log device .fi .SH SEE ALSO logger(1), syslog(3) inn-1.7.2/syslog/syslog.conf0100644000175100001440000000143006443103542014334 0ustar mdusers## $Id: syslog.conf,v 1.7 1996/11/10 22:12:22 brister Exp $ ## Sample syslog.conf file for folks not used to the new syslog. ## ## This matches typical old-style config. Log everything to a ## file and send warnings or worse to root. *.notice;news.err /usr/spool/mqueue/syslog *.alert root ## Send critical messages to everyone who is logged in and to the console. news.crit * news.crit /dev/console ## Log news messages to separate files. ## Note that each level includes all levels above it: notice includes crit. ## =()@/news.crit>()= news.crit /var/log/news/news.crit ## =()@/news.err>()= news.err /var/log/news/news.err ## =()@/news.notice>()= news.notice /var/log/news/news.notice inn-1.7.2/syslog/syslog.h0100644000175100001440000001224106443103542013640 0ustar mdusers/* $Revision: 1.3 $ * Copyright (c) 1982, 1986, 1988 Regents of the University of California. * All rights reserved. * * Redistribution is only permitted until one year after the first shipment * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and * binary forms are permitted provided that: (1) source distributions retain * this entire copyright notice and comment, and (2) distributions including * binaries display the following acknowledgement: This product includes * software developed by the University of California, Berkeley and its * contributors'' in the documentation or other materials provided with the * distribution and in all advertising materials mentioning features or use * of this software. Neither the name of the University nor the names of * its contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)syslog.h 7.16 (Berkeley) 6/28/90 */ /* * priorities/facilities are encoded into a single 32-bit quantity, where the * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility * (0-big number). Both the priorities and the facilities map roughly * one-to-one to strings in the syslogd(8) source code. This mapping is * included in this file. * * priorities (these are ordered) */ #define LOG_EMERG 0 /* system is unusable */ #define LOG_ALERT 1 /* action must be taken immediately */ #define LOG_CRIT 2 /* critical conditions */ #define LOG_ERR 3 /* error conditions */ #define LOG_WARNING 4 /* warning conditions */ #define LOG_NOTICE 5 /* normal but significant condition */ #define LOG_INFO 6 /* informational */ #define LOG_DEBUG 7 /* debug-level messages */ #define LOG_PRIMASK 0x007 /* mask to extract priority part (internal) */ /* extract priority */ #define LOG_PRI(p) ((p) & LOG_PRIMASK) #define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri)) #ifdef SYSLOG_NAMES #define INTERNAL_NOPRI 0x10 /* the "no priority" priority */ /* mark "facility" */ #define INTERNAL_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0) typedef struct _code { char *c_name; int c_val; } CODE; CODE prioritynames[] = { "alert", LOG_ALERT, "crit", LOG_CRIT, "debug", LOG_DEBUG, "emerg", LOG_EMERG, "err", LOG_ERR, "error", LOG_ERR, /* DEPRECATED */ "info", LOG_INFO, "none", INTERNAL_NOPRI, /* INTERNAL */ "notice", LOG_NOTICE, "panic", LOG_EMERG, /* DEPRECATED */ "warn", LOG_WARNING, /* DEPRECATED */ "warning", LOG_WARNING, NULL, -1, }; #endif /* facility codes */ #define LOG_KERN (0<<3) /* kernel messages */ #define LOG_USER (1<<3) /* random user-level messages */ #define LOG_MAIL (2<<3) /* mail system */ #define LOG_DAEMON (3<<3) /* system daemons */ #define LOG_AUTH (4<<3) /* security/authorization messages */ #define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ #define LOG_LPR (6<<3) /* line printer subsystem */ #define LOG_NEWS (7<<3) /* network news subsystem */ #define LOG_UUCP (8<<3) /* UUCP subsystem */ #define LOG_CRON (15<<3) /* clock daemon */ /* other codes through 15 reserved for system use */ #define LOG_LOCAL0 (16<<3) /* reserved for local use */ #define LOG_LOCAL1 (17<<3) /* reserved for local use */ #define LOG_LOCAL2 (18<<3) /* reserved for local use */ #define LOG_LOCAL3 (19<<3) /* reserved for local use */ #define LOG_LOCAL4 (20<<3) /* reserved for local use */ #define LOG_LOCAL5 (21<<3) /* reserved for local use */ #define LOG_LOCAL6 (22<<3) /* reserved for local use */ #define LOG_LOCAL7 (23<<3) /* reserved for local use */ #define LOG_NFACILITIES 24 /* current number of facilities */ #define LOG_FACMASK 0x03f8 /* mask to extract facility part */ /* facility of pri */ #define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3) #ifdef SYSLOG_NAMES CODE facilitynames[] = { "auth", LOG_AUTH, "cron", LOG_CRON, "daemon", LOG_DAEMON, "kern", LOG_KERN, "lpr", LOG_LPR, "mail", LOG_MAIL, "mark", INTERNAL_MARK, /* INTERNAL */ "news", LOG_NEWS, "security", LOG_AUTH, /* DEPRECATED */ "syslog", LOG_SYSLOG, "user", LOG_USER, "uucp", LOG_UUCP, "local0", LOG_LOCAL0, "local1", LOG_LOCAL1, "local2", LOG_LOCAL2, "local3", LOG_LOCAL3, "local4", LOG_LOCAL4, "local5", LOG_LOCAL5, "local6", LOG_LOCAL6, "local7", LOG_LOCAL7, NULL, -1, }; #endif #ifdef KERNEL #define LOG_PRINTF -1 /* pseudo-priority to indicate use of printf */ #endif /* * arguments to setlogmask. */ #define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */ #define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */ /* * Option flags for openlog. * * LOG_ODELAY no longer does anything. * LOG_NDELAY is the inverse of what it used to be. */ #define LOG_PID 0x01 /* log the pid with each message */ #define LOG_CONS 0x02 /* log on the console if errors in sending */ #define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */ #define LOG_NDELAY 0x08 /* don't delay open */ #define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */ #define LOG_PERROR 0x20 /* log to stderr as well */ inn-1.7.2/syslog/logger.10100644000175100001440000000457606443103542013524 0ustar mdusers.\" $Revision: 1.4 $ .\" Modified by Rich $alz to be more portable to older .\" systems. .\" Copyright (c) 1983, 1990 The Regents of the University of California. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms are permitted provided .\" that: (1) source distributions retain this entire copyright notice and .\" comment, and (2) distributions including binaries display the following .\" acknowledgement: ``This product includes software developed by the .\" University of California, Berkeley and its contributors'' in the .\" documentation or other materials provided with the distribution and in .\" all advertising materials mentioning features or use of this software. .\" Neither the name of the University nor the names of its contributors may .\" be used to endorse or promote products derived from this software without .\" specific prior written permission. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .\" @(#)logger.1 6.6 (Berkeley) 7/24/90 .\" .TH LOGGER 1 "July 24, 1990" .SH NAME logger \- make entries in the system log .SH SYNOPSIS .B logger [ .B \-i ] [ .B \-s ] [ .BI \-f file ] [ .BI \-p pri ] [ .BI \-t tag ] .I message... .SH DESCRIPTION .I Logger provides a shell command interface to the .IR syslog (3) system log module. .PP Options: .TP .B \-i Log the process id of the logger process with each line. .TP .B \-s Log the message to standard error, as well as the system log. .TP .BI \-f file Log the specified file. .TP .BI \-p pri Enter the message with the specified priority. The priority may be specified numerically or as a ``facility.level'' pair. For example, ``\-p local3.info'' logs the message(s) as .IR info rmational level in the .I local3 facility. The default is ``user.notice.'' .TP .BI \-t tag Mark every line in the log with the specified .IR tag . .TP .I message Write the message to log; if not specified, and the ``\-f'' flag is not provided, standard input is logged. .PP The .I logger utility exits 0 on success, and >0 if an error occurs. .SH EXAMPLES .RS .nf logger System rebooted logger \-p local0.notice \-t HOSTIDM \-f /dev/idmc .fi .DE .SH "SEE ALSO" syslog(3), syslogd(8) .SH STANDARDS The logger function is expected to be POSIX 1003.2 compatible. inn-1.7.2/syslog/syslogd.c0100644000175100001440000007551306443103542014012 0ustar mdusers/* $Revision: 1.11 $ ** This file has been modified to get it to compile more easily ** on pre-4.4BSD (e.g., SysVr4 :-) systems. Rich $alz, June 1991. */ #include #include #include "configdata.h" #include "clibrary.h" /* change these three if you must keep running an old syslog. */ #define _PATH_LOGFILE "/dev/log" #define _PATH_LOGCONF "/etc/syslog.conf" #define _PATH_LOGPID "/etc/syslog.pid" /* #define this to enable verbose debugging of all messages. */ #undef VERBOSE_DEBUG /* #define this to line to listen on the INET port. */ #undef DO_INET_SOCKET /* #undef this to not read kernel syslog messages. */ #define _PATH_KLOG "/dev/klog" #undef _PATH_KLOG /* set this depending on what your sighandler is. */ /* =()<#define SIGHANDLER @@>()= */ #define SIGHANDLER void /* if you need various BSD functions, set this. */ #define NEED_BZERO_ETC /* Use "union wait" instead of int? */ /* =()<#define @@_USE_UNION_WAIT>()= */ #define DONT_USE_UNION_WAIT #if defined(DO_USE_UNION_WAIT) #define WAITVALUE union wait #else #define WAITVALUE int #endif /* defined(DO_USE_UNION_WAIT) */ /* * Copyright (c) 1983, 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)syslogd.c 5.42 (Berkeley) 6/29/90"; #endif /* not lint */ /* * syslogd -- log system messages * * This program implements a system log. It takes a series of lines. * Each line may have a priority, signified as "" as * the first characters of the line. If this is * not present, a default priority is used. * * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will * cause it to reread its configuration file. * * Defined Constants: * * MAXLINE -- the maximimum line length that can be handled. * DEFUPRI -- the default priority for user messages * DEFSPRI -- the default priority for kernel messages * * Author: Eric Allman * extensive changes by Ralph Campbell * more extensive changes by Eric Allman (again) */ #define MAXLINE 1024 /* maximum line length */ #define MAXSVLINE 120 /* maximum saved line length */ #define DEFUPRI (LOG_USER|LOG_NOTICE) #define DEFSPRI (LOG_KERN|LOG_CRIT) #define TIMERINTVL 30 /* interval for checking flush, mark */ #include #include #include #include #include #include #include #include #include #include #include #ifdef MSG_BSIZE #undef MSG_BSIZE #endif #define MSG_BSIZE 4096 #include #include #include #include #include #define SYSLOG_NAMES #include "syslog.h" #ifndef UT_NAMESIZE #define UT_NAMESIZE 8 #endif #ifndef _PATH_UTMP #define _PATH_UTMP "/etc/utmp" #endif #ifndef _PATH_DEV #define _PATH_DEV "/dev/" #endif #ifndef _PATH_CONSOLE #define _PATH_CONSOLE "/dev/console" #endif #ifndef sigmask #define sigmask(m) (1 << ((m)-1)) #endif char *LogName = _PATH_LOGFILE; char *ConfFile = _PATH_LOGCONF; char *PidFile = _PATH_LOGPID; char ctty[] = _PATH_CONSOLE; #define FDMASK(fd) (1 << (fd)) #define dprintf if (Debug) printf #define MAXUNAMES 20 /* maximum number of user names */ #ifdef NEED_BZERO_ETC #include void bzero(b, length) char *b; int length; { while (--length >= 0) *b++ = '\0'; } void bcopy(b1, b2, length) char *b1; char *b2; int length; { while (--length >= 0) *b2++ = *b1++; } setlinebuf(f) FILE *f; { setbuf(f, (char *)NULL); } PID_T wait3(status, flags, np) WAITVALUE *status; int flags; struct rusage *np; { return waitpid(-1, status, WNOHANG); } /* Not a general mask handler -- it know what we call, below. */ SIGHANDLER (*oldhup)(), (*oldalrm)(); int sigsetmask(omask) int omask; { if (omask & sigmask(SIGHUP)) (void) signal(SIGHUP, oldhup); if (omask & sigmask(SIGALRM)) (void) signal(SIGALRM, oldalrm); } int sigblock(mask) int mask; { if (mask & sigmask(SIGHUP)) oldhup = signal(SIGHUP, SIG_IGN); if (mask & sigmask(SIGALRM)) oldhup = signal(SIGALRM, SIG_IGN); } #endif /* * Flags to logmsg(). */ #define IGN_CONS 0x001 /* don't print on console */ #define SYNC_FILE 0x002 /* do fsync on file after printing */ #define ADDDATE 0x004 /* add a date to the message */ #define MARK 0x008 /* this message is a mark */ /* * This structure represents the files that will have log * copies printed. */ struct filed { struct filed *f_nextone; /* next in linked list */ short f_type; /* entry type, see below */ short f_file; /* file descriptor */ time_t f_time; /* time this was last written */ u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */ union { char f_uname[MAXUNAMES][UT_NAMESIZE+1]; struct { char f_hname[MAXHOSTNAMELEN+1]; struct sockaddr_in f_addr; } f_forw; /* forwarding address */ char f_fname[MAXPATHLEN]; } f_un; char f_prevline[MAXSVLINE]; /* last message logged */ char f_lasttime[16]; /* time of last occurrence */ char f_prevhost[MAXHOSTNAMELEN+1]; /* host from which recd. */ int f_prevpri; /* pri of f_prevline */ int f_prevlen; /* length of f_prevline */ int f_prevcount; /* repetition cnt of prevline */ int f_repeatcount; /* number of "repeated" msgs */ }; /* * Intervals at which we flush out "message repeated" messages, * in seconds after previous message is logged. After each flush, * we move to the next interval until we reach the largest. */ int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */ #define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1) #define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount]) #define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \ (f)->f_repeatcount = MAXREPEAT; \ } /* values for f_type */ #define F_UNUSED 0 /* unused entry */ #define F_FILE 1 /* regular file */ #define F_TTY 2 /* terminal */ #define F_CONSOLE 3 /* console terminal */ #define F_FORW 4 /* remote machine */ #define F_USERS 5 /* list of users */ #define F_WALL 6 /* everyone logged on */ char *TypeNames[7] = { "UNUSED", "FILE", "TTY", "CONSOLE", "FORW", "USERS", "WALL" }; struct filed *Files; struct filed consfile; int Debug; /* debug flag */ char LocalHostName[MAXHOSTNAMELEN+1]; /* our hostname */ char *LocalDomain; /* our local domain name */ int InetInuse = 0; /* non-zero if INET sockets are being used */ int finet; /* Internet datagram socket */ int LogPort; /* port number for INET connections */ int Initialized = 0; /* set when we have initialized ourselves */ int MarkInterval = 20 * 60; /* interval between marks in seconds */ int MarkSeq = 0; /* mark sequence number */ extern int errno; extern char *ctime(), *strchr(); extern POINTER malloc(); SIGHANDLER die(), domark(), init(), reapchild(); int main(argc, argv) int argc; char **argv; { register int i; register char *p; int funix, inetm, fklog, klogm, len; struct sockaddr_un sunx, fromunix; struct sockaddr_in sin, frominet; FILE *fp; int ch; char line[MSG_BSIZE + 1]; extern int optind; extern char *optarg; while ((ch = getopt(argc, argv, "df:m:p:")) != EOF) switch((char)ch) { case 'd': /* debug */ Debug++; break; case 'f': /* configuration file */ ConfFile = optarg; break; case 'm': /* mark interval */ MarkInterval = atoi(optarg) * 60; break; case 'p': /* path */ LogName = optarg; break; case '?': default: usage(); } if (argc -= optind) usage(); if (!Debug) daemon(0, 0); else setlinebuf(stdout); consfile.f_type = F_CONSOLE; (void) strcpy(consfile.f_un.f_fname, ctty); (void) gethostname(LocalHostName, sizeof LocalHostName); if (p = strchr(LocalHostName, '.')) { *p++ = '\0'; LocalDomain = p; } else LocalDomain = ""; (void) signal(SIGTERM, die); if (Debug) { (void) signal(SIGINT, die); (void) signal(SIGQUIT, die); } else { (void) signal(SIGINT, SIG_IGN); (void) signal(SIGQUIT, SIG_IGN); } (void) signal(SIGCHLD, reapchild); (void) signal(SIGALRM, domark); (void) alarm(TIMERINTVL); (void) unlink(LogName); bzero((char *)&sunx, sizeof(sunx)); sunx.sun_family = AF_UNIX; (void) strncpy(sunx.sun_path, LogName, sizeof sunx.sun_path); funix = socket(AF_UNIX, SOCK_DGRAM, 0); if (funix < 0 || bind(funix, (struct sockaddr *) &sunx, sizeof(sunx)) < 0 || chmod(LogName, 0666) < 0) { (void) sprintf(line, "cannot create %s", LogName); logerror(line); dprintf("cannot create %s (%d)\n", LogName, errno); die(0); } #ifdef DO_INET_SOCKET finet = socket(AF_INET, SOCK_DGRAM, 0); if (finet >= 0) { struct servent *sp; sp = getservbyname("syslog", "udp"); if (sp == NULL) { errno = 0; logerror("syslog/udp: unknown service"); die(0); } bzero((char *)&sin, sizeof(sin)); /* added uunet!rbj */ sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = LogPort = htons(sp->s_port); if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) { logerror("bind"); if (!Debug) die(0); } else { inetm = FDMASK(finet); InetInuse = 1; } } #else finet = -1; inetm = 0; #endif /* DO_INET_SOCKET */ #ifdef _PATH_KLOG if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) >= 0) klogm = FDMASK(fklog); else { dprintf("can't open %s (%d)\n", _PATH_KLOG, errno); klogm = 0; } #else fklog = -1; klogm = 0; #endif /* _PATH_KLOG */ /* tuck my process id away */ fp = fopen(PidFile, "w"); if (fp != NULL) { fprintf(fp, "%ld\n", (long) getpid()); (void) fclose(fp); } dprintf("off & running....\n"); init(); (void) signal(SIGHUP, init); for (;;) { int nfds, readfds = FDMASK(funix) | inetm | klogm; errno = 0; dprintf("readfds = %#x\n", readfds); nfds = select(20, (fd_set *) &readfds, (fd_set *) NULL, (fd_set *) NULL, (struct timeval *) NULL); if (nfds == 0) continue; if (nfds < 0) { if (errno != EINTR) logerror("select"); continue; } dprintf("got a message (%d, %#x)\n", nfds, readfds); if (readfds & klogm) { i = read(fklog, line, sizeof(line) - 1); if (i > 0) { line[i] = '\0'; printsys(line); } else if (i < 0 && errno != EINTR) { logerror("klog"); fklog = -1; klogm = 0; } } if (readfds & FDMASK(funix)) { len = sizeof fromunix; i = recvfrom(funix, line, MAXLINE, 0, (struct sockaddr *) &fromunix, &len); if (i > 0) { line[i] = '\0'; printline(LocalHostName, line); } else if (i < 0 && errno != EINTR) logerror("recvfrom unix"); } if (readfds & inetm) { len = sizeof frominet; i = recvfrom(finet, line, MAXLINE, 0, (struct sockaddr *) &frominet, &len); if (i > 0) { extern char *cvthname(); line[i] = '\0'; printline(cvthname(&frominet), line); } else if (i < 0 && errno != EINTR) logerror("recvfrom inet"); } } } usage() { (void) fprintf(stderr, "usage: syslogd [-d] [-f conffile] [-m markinterval] [-p path]\n"); exit(1); } /* * Take a raw input line, decode the message, and print the message * on the appropriate log files. */ printline(hname, msg) char *hname; char *msg; { register char *p, *q; register int c; char line[MAXLINE + 1]; int pri; /* test for special codes */ pri = DEFUPRI; p = msg; if (*p == '<') { pri = 0; while (isdigit(*++p)) pri = 10 * pri + (*p - '0'); if (*p == '>') ++p; } if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) pri = DEFUPRI; /* don't allow users to log kernel messages */ if (LOG_FAC(pri) == LOG_KERN) pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri)); q = line; while ((c = *p++ & 0177) != '\0' && q < &line[sizeof(line) - 1]) if (iscntrl(c)) if (c == '\n') *q++ = ' '; else if (c == '\t') *q++ = '\t'; else { *q++ = '^'; *q++ = c ^ 0100; } else *q++ = c; *q = '\0'; logmsg(pri, line, hname, 0); } /* * Take a raw input line from /dev/klog, split and format similar to syslog(). */ printsys(msg) char *msg; { register char *p, *q; register int c; char line[MAXLINE + 1]; int pri, flags; char *lp; (void) strcpy(line, "vmunix: "); lp = line + strlen(line); for (p = msg; *p != '\0'; ) { flags = SYNC_FILE | ADDDATE; /* fsync file after write */ pri = DEFSPRI; if (*p == '<') { pri = 0; while (isdigit(*++p)) pri = 10 * pri + (*p - '0'); if (*p == '>') ++p; } else { /* kernel printf's come out on console */ flags |= IGN_CONS; } if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) pri = DEFSPRI; q = lp; while (*p != '\0' && (c = *p++) != '\n' && q < &line[MAXLINE]) *q++ = c; *q = '\0'; logmsg(pri, line, LocalHostName, flags); } } #ifdef VERBOSE_DEBUG /* * Decode a numeric value to a symbolic name */ char * edoced(val, codetab) int val; CODE *codetab; { register CODE *c; if (val >= 0) for (c = codetab; c->c_val != -1; c++) if (c->c_val == val) return (c->c_name); return ("???"); } #endif time_t now; /* * Log a message to the appropriate log files, users, etc. based on * the priority. */ logmsg(pri, msg, from, flags) int pri; char *msg, *from; int flags; { register struct filed *f; int fac, prilev; int omask, msglen; char *timestamp; time_t time(); #ifdef VERBOSE_DEBUG if (Debug) { int pfac = (flags & MARK) ? INTERNAL_MARK : (pri & LOG_FACMASK); printf("logmsg: {%s.%s} pri %o, flags %x, from %s, msg %s\n", edoced(pfac, facilitynames), edoced(LOG_PRI(pri), prioritynames), pri, flags, from, msg); } #else dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n", pri, flags, from, msg); #endif omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM)); /* * Check to see if msg looks non-standard. */ msglen = strlen(msg); if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' || msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') flags |= ADDDATE; (void) time(&now); if (flags & ADDDATE) timestamp = ctime(&now) + 4; else { timestamp = msg; msg += 16; msglen -= 16; } /* extract facility and priority level */ if (flags & MARK) fac = LOG_NFACILITIES; else fac = LOG_FAC(pri); prilev = LOG_PRI(pri); /* log the message to the particular outputs */ if (!Initialized) { f = &consfile; f->f_file = open(ctty, O_WRONLY, 0); if (f->f_file >= 0) { fprintlog(f, flags, msg); (void) close(f->f_file); } (void) sigsetmask(omask); return; } for (f = Files; f; f = f->f_nextone) { /* skip messages that are incorrect priority */ if ((int)f->f_pmask[fac] < prilev || f->f_pmask[fac] == INTERNAL_NOPRI) continue; if (f->f_type == F_CONSOLE && (flags & IGN_CONS)) continue; /* don't output marks to recently written files */ if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2) continue; /* * suppress duplicate lines to this file */ if ((flags & MARK) == 0 && msglen == f->f_prevlen && !strcmp(msg, f->f_prevline) && !strcmp(from, f->f_prevhost)) { (void) strncpy(f->f_lasttime, timestamp, 15); f->f_prevcount++; dprintf("msg repeated %d times, %ld sec of %d\n", f->f_prevcount, now - f->f_time, repeatinterval[f->f_repeatcount]); /* * If domark would have logged this by now, * flush it now (so we don't hold isolated messages), * but back off so we'll flush less often * in the future. */ if (now > REPEATTIME(f)) { fprintlog(f, flags, (char *)NULL); BACKOFF(f); } } else { /* new line, save it */ if (f->f_prevcount) fprintlog(f, 0, (char *)NULL); f->f_repeatcount = 0; (void) strncpy(f->f_lasttime, timestamp, 15); (void) strncpy(f->f_prevhost, from, sizeof(f->f_prevhost)); if (msglen < MAXSVLINE) { f->f_prevlen = msglen; f->f_prevpri = pri; (void) strcpy(f->f_prevline, msg); fprintlog(f, flags, (char *)NULL); } else { f->f_prevline[0] = 0; f->f_prevlen = 0; fprintlog(f, flags, msg); } } } (void) sigsetmask(omask); } fprintlog(f, flags, msg) register struct filed *f; int flags; char *msg; { struct iovec iov[6]; register struct iovec *v; register int l; char line[MAXLINE + 1], repbuf[80], greetings[200]; v = iov; if (f->f_type == F_WALL) { v->iov_base = greetings; sprintf(greetings, "\r\n\7Message from syslogd@%s at %.24s ...\r\n", f->f_prevhost, ctime(&now)); v->iov_len = strlen(greetings); v++; v->iov_base = ""; v->iov_len = 0; v++; } else { v->iov_base = f->f_lasttime; v->iov_len = 15; v++; v->iov_base = " "; v->iov_len = 1; v++; } v->iov_base = f->f_prevhost; v->iov_len = strlen(v->iov_base); v++; v->iov_base = " "; v->iov_len = 1; v++; if (msg) { v->iov_base = msg; v->iov_len = strlen(msg); } else if (f->f_prevcount > 1) { v->iov_base = repbuf; sprintf(repbuf, "last message repeated %d times", f->f_prevcount); v->iov_len = strlen(repbuf); } else { v->iov_base = f->f_prevline; v->iov_len = f->f_prevlen; } v++; dprintf("Logging to %s", TypeNames[f->f_type]); f->f_time = now; switch (f->f_type) { case F_UNUSED: dprintf("\n"); break; case F_FORW: dprintf(" %s\n", f->f_un.f_forw.f_hname); sprintf(line, "<%d>%.15s %s", f->f_prevpri, iov[0].iov_base, iov[4].iov_base); l = strlen(line); if (l > MAXLINE) l = MAXLINE; if (sendto(finet, line, l, 0, &f->f_un.f_forw.f_addr, sizeof f->f_un.f_forw.f_addr) != l) { int e = errno; (void) close(f->f_file); f->f_type = F_UNUSED; errno = e; logerror("sendto"); } break; case F_CONSOLE: if (flags & IGN_CONS) { dprintf(" (ignored)\n"); break; } /* FALLTHROUGH */ case F_TTY: case F_FILE: dprintf(" %s\n", f->f_un.f_fname); if (f->f_type != F_FILE) { v->iov_base = "\r\n"; v->iov_len = 2; } else { v->iov_base = "\n"; v->iov_len = 1; } again: if (writev(f->f_file, iov, 6) < 0) { int e = errno; (void) close(f->f_file); /* * Check for errors on TTY's due to loss of tty */ if ((e == EIO || e == EBADF) && f->f_type != F_FILE) { f->f_file = open(f->f_un.f_fname, O_WRONLY|O_APPEND, 0); if (f->f_file < 0) { f->f_type = F_UNUSED; logerror(f->f_un.f_fname); } else goto again; } else { f->f_type = F_UNUSED; errno = e; logerror(f->f_un.f_fname); } } else if (flags & SYNC_FILE) (void) fsync(f->f_file); break; case F_USERS: case F_WALL: dprintf("\n"); v->iov_base = "\r\n"; v->iov_len = 2; wallmsg(f, iov); break; } f->f_prevcount = 0; } /* * WALLMSG -- Write a message to the world at large * * Write the specified message to either the entire * world, or a list of approved users. */ wallmsg(f, iov) register struct filed *f; struct iovec *iov; { static int reenter; /* avoid calling ourselves */ register FILE *uf; register int i; struct utmp ut; char *p, *ttymsg(); if (reenter++) return; if ((uf = fopen(_PATH_UTMP, "r")) == NULL) { logerror(_PATH_UTMP); reenter = 0; return; } /* NOSTRICT */ while (fread((char *) &ut, sizeof ut, 1, uf) == 1) { if (ut.ut_name[0] == '\0') continue; if (f->f_type == F_WALL) { if (p = ttymsg(iov, 6, ut.ut_line, 1)) { errno = 0; /* already in msg */ logerror(p); } continue; } /* should we send the message to this user? */ for (i = 0; i < MAXUNAMES; i++) { if (!f->f_un.f_uname[i][0]) break; if (!strncmp(f->f_un.f_uname[i], ut.ut_name, UT_NAMESIZE)) { if (p = ttymsg(iov, 6, ut.ut_line, 1)) { errno = 0; /* already in msg */ logerror(p); } break; } } } (void) fclose(uf); reenter = 0; } SIGHANDLER reapchild() { WAITVALUE status; while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) continue; } /* * Return a printable representation of a host address. */ char * cvthname(f) struct sockaddr_in *f; { struct hostent *hp; register char *p; extern char *inet_ntoa(); dprintf("cvthname(%s)\n", inet_ntoa(f->sin_addr)); if (f->sin_family != AF_INET) { dprintf("Malformed from address\n"); return ("???"); } hp = gethostbyaddr(&f->sin_addr, sizeof(struct in_addr), f->sin_family); if (hp == 0) { dprintf("Host name for your address (%s) unknown\n", inet_ntoa(f->sin_addr)); return (inet_ntoa(f->sin_addr)); } if ((p = strchr(hp->h_name, '.')) && strcmp(p + 1, LocalDomain) == 0) *p = '\0'; return (hp->h_name); } SIGHANDLER domark() { register struct filed *f; time_t time(); now = time((time_t *)NULL); MarkSeq += TIMERINTVL; if (MarkSeq >= MarkInterval) { logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE|MARK); MarkSeq = 0; } for (f = Files; f; f = f->f_nextone) { if (f->f_prevcount && now >= REPEATTIME(f)) { dprintf("flush %s: repeated %d times, %d sec.\n", TypeNames[f->f_type], f->f_prevcount, repeatinterval[f->f_repeatcount]); fprintlog(f, 0, (char *)NULL); BACKOFF(f); } } (void) alarm(TIMERINTVL); } static char * xstrerror() { extern int sys_nerr; extern char *sys_errlist[]; extern int errno; static char buff[30]; if (errno >= 0 && errno < sys_nerr) return sys_errlist[errno]; (void)sprintf(buff, "Error code %d\n", errno); return buff; } /* * Print syslogd errors some place. */ logerror(type) char *type; { char buf[100]; if (errno) (void) sprintf(buf, "syslogd: %s: %s", type, xstrerror(errno)); else (void) sprintf(buf, "syslogd: %s", type); errno = 0; dprintf("%s\n", buf); logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE); } SIGHANDLER die(sig) { register struct filed *f; char buf[100]; for (f = Files; f != NULL; f = f->f_nextone) { /* flush any pending output */ if (f->f_prevcount) fprintlog(f, 0, (char *)NULL); } if (sig) { dprintf("syslogd: exiting on signal %d\n", sig); (void) sprintf(buf, "exiting on signal %d", sig); errno = 0; logerror(buf); } (void) unlink(LogName); exit(0); } /* * INIT -- Initialize syslogd from configuration table */ SIGHANDLER init() { register int i; register FILE *cf; register struct filed *f, *next, **nextp; register char *p; char cline[BUFSIZ]; dprintf("init\n"); /* * Close all open log files. */ Initialized = 0; for (f = Files; f != NULL; f = next) { /* flush any pending output */ if (f->f_prevcount) fprintlog(f, 0, (char *)NULL); switch (f->f_type) { case F_FILE: case F_TTY: case F_CONSOLE: case F_FORW: (void) close(f->f_file); break; } next = f->f_nextone; free((char *) f); } Files = NULL; nextp = &Files; /* open the configuration file */ if ((cf = fopen(ConfFile, "r")) == NULL) { dprintf("cannot open %s\n", ConfFile); *nextp = (struct filed *)malloc(sizeof(*f)); cfline("*.ERR\t/dev/console", *nextp); (*nextp)->f_nextone = (struct filed *)malloc(sizeof(*f)); cfline("*.PANIC\t*", (*nextp)->f_nextone); Initialized = 1; return; } /* * Foreach line in the conf table, open that file. */ f = NULL; while (fgets(cline, sizeof cline, cf) != NULL) { /* * check for end-of-section, comments, strip off trailing * spaces and newline character. */ for (p = cline; isspace(*p); ++p); if (*p == NULL || *p == '#') continue; for (p = strchr(cline, '\0'); isspace(*--p);); *++p = '\0'; f = (struct filed *)malloc(sizeof(*f)); *nextp = f; nextp = &f->f_nextone; cfline(cline, f); } /* close the configuration file */ (void) fclose(cf); Initialized = 1; if (Debug) { for (f = Files; f; f = f->f_nextone) { for (i = 0; i <= LOG_NFACILITIES; i++) if (f->f_pmask[i] == INTERNAL_NOPRI) printf("X "); else printf("%d ", f->f_pmask[i]); printf("%s: ", TypeNames[f->f_type]); switch (f->f_type) { case F_FILE: case F_TTY: case F_CONSOLE: printf("%s", f->f_un.f_fname); break; case F_FORW: printf("%s", f->f_un.f_forw.f_hname); break; case F_USERS: for (i = 0; i < MAXUNAMES && *f->f_un.f_uname[i]; i++) printf("%s, ", f->f_un.f_uname[i]); break; } printf("\n"); } } logmsg(LOG_SYSLOG|LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE); dprintf("syslogd: restarted\n"); } /* * Crack a configuration file line */ cfline(line, f) char *line; register struct filed *f; { register char *p; register char *q; register int i; char *bp; int pri; struct hostent *hp; char buf[MAXLINE]; dprintf("cfline(%s)\n", line); errno = 0; /* keep strerror() stuff out of logerror messages */ /* clear out file entry */ bzero((char *) f, sizeof *f); for (i = 0; i <= LOG_NFACILITIES; i++) f->f_pmask[i] = INTERNAL_NOPRI; /* scan through the list of selectors */ for (p = line; *p && *p != '\t';) { /* find the end of this facility name list */ for (q = p; *q && *q != '\t' && *q++ != '.'; ) continue; /* collect priority name */ for (bp = buf; *q && !strchr("\t,;", *q); ) *bp++ = *q++; *bp = '\0'; /* skip cruft */ while (strchr(", ;", *q)) q++; /* decode priority name */ pri = decode(buf, prioritynames); if (pri < 0) { char xbuf[200]; (void) sprintf(xbuf, "unknown priority name \"%s\"", buf); logerror(xbuf); return; } /* scan facilities */ while (*p && !strchr("\t.;", *p)) { for (bp = buf; *p && !strchr("\t,;.", *p); ) *bp++ = *p++; *bp = '\0'; if (*buf == '*') for (i = 0; i < LOG_NFACILITIES; i++) f->f_pmask[i] = pri; else { i = decode(buf, facilitynames); if (i < 0) { char xbuf[200]; (void) sprintf(xbuf, "unknown facility name \"%s\"", buf); logerror(xbuf); return; } f->f_pmask[i >> 3] = pri; } while (*p == ',' || *p == ' ') p++; } p = q; } /* skip to action part */ while (*p == '\t') p++; switch (*p) { case '@': if (!InetInuse) break; (void) strcpy(f->f_un.f_forw.f_hname, ++p); hp = gethostbyname(p); if (hp == NULL) { logerror("hostname lookup error"); break; } bzero((char *) &f->f_un.f_forw.f_addr, sizeof f->f_un.f_forw.f_addr); f->f_un.f_forw.f_addr.sin_family = AF_INET; f->f_un.f_forw.f_addr.sin_port = LogPort; bcopy(hp->h_addr, (char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_length); f->f_type = F_FORW; break; case '/': (void) strcpy(f->f_un.f_fname, p); if ((f->f_file = open(p, O_WRONLY|O_APPEND, 0)) < 0) { f->f_file = F_UNUSED; logerror(p); break; } if (isatty(f->f_file)) f->f_type = F_TTY; else f->f_type = F_FILE; if (strcmp(p, ctty) == 0) f->f_type = F_CONSOLE; break; case '*': f->f_type = F_WALL; break; default: for (i = 0; i < MAXUNAMES && *p; i++) { for (q = p; *q && *q != ','; ) q++; (void) strncpy(f->f_un.f_uname[i], p, UT_NAMESIZE); if ((q - p) > UT_NAMESIZE) f->f_un.f_uname[i][UT_NAMESIZE] = '\0'; else f->f_un.f_uname[i][q - p] = '\0'; while (*q == ',' || *q == ' ') q++; p = q; } f->f_type = F_USERS; break; } } /* * Decode a symbolic name to a numeric value */ decode(name, codetab) char *name; CODE *codetab; { register CODE *c; register char *p; char buf[40]; if (isdigit(*name)) return (atoi(name)); (void) strcpy(buf, name); for (p = buf; *p; p++) if (isupper(*p)) *p = tolower(*p); for (c = codetab; c->c_name; c++) if (!strcmp(buf, c->c_name)) return (c->c_val); return (-1); } daemon(nochdir, noclose) int nochdir, noclose; { PID_T cpid; if ((cpid = fork()) == -1) return (-1); if (cpid) exit(0); (void) setsid(); if (!nochdir) (void) chdir("/"); if (!noclose) { int devnull = open("/dev/null", O_RDWR, 0); if (devnull != -1) { (void) dup2(devnull, 0); (void) dup2(devnull, 1); (void) dup2(devnull, 2); if (devnull > 2) (void) close(devnull); } } } /* * Display the contents of a uio structure on a terminal. Used by wall(1) * and syslogd(8). Forks and finishes in child if write would block, waiting * at most five minutes. Returns pointer to error string on unexpected error; * string is not newline-terminated. Various "normal" errors are ignored * (exclusive-use, lack of permission, etc.). */ char * ttymsg(iov, iovcnt, line) struct iovec *iov; int iovcnt; char *line; { static char device[64] = _PATH_DEV; static char errbuf[1024]; register int cnt, fd, left, wret; struct iovec localiov[6]; int forked = 0; if (iovcnt > 6) return ("too many iov's"); /* * open will fail on slip lines or exclusive-use lines * if not running as root; not an error. */ (void) strcpy(device + sizeof(_PATH_DEV) - 1, line); if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) { if (errno == EBUSY || errno == EACCES) return (NULL); (void) sprintf(errbuf, "%s: error %d", device, errno); return (errbuf); } for (cnt = left = 0; cnt < iovcnt; ++cnt) left += iov[cnt].iov_len; for (;;) { wret = writev(fd, iov, iovcnt); if (wret >= left) break; if (wret >= 0) { left -= wret; if (iov != localiov) { bcopy(iov, localiov, iovcnt * sizeof(struct iovec)); iov = localiov; } for (cnt = 0; wret >= iov->iov_len; ++cnt) { wret -= iov->iov_len; ++iov; --iovcnt; } if (wret) { iov->iov_base += wret; iov->iov_len -= wret; } continue; } if (errno == EWOULDBLOCK) { PID_T cpid; int off = 0; if (forked) { (void) close(fd); _exit(1); } cpid = fork(); if (cpid < 0) { (void) sprintf(errbuf, "fork: error %d", errno); (void) close(fd); return (errbuf); } if (cpid) { /* parent */ (void) close(fd); return (NULL); } forked++; /* wait at most 5 minutes */ (void) signal(SIGALRM, SIG_DFL); (void) signal(SIGTERM, SIG_DFL); /* XXX */ (void) sigsetmask(0); (void) alarm((u_int)(60 * 5)); (void) fcntl(fd, FNDELAY, &off); continue; } /* * We get ENODEV on a slip line if we're running as root, * and EIO if the line just went away. */ if (errno == ENODEV || errno == EIO) break; (void) close(fd); if (forked) _exit(1); (void) sprintf(errbuf, "%s: error %d", errno); return (errbuf); } (void) close(fd); if (forked) _exit(0); return (NULL); } inn-1.7.2/syslog/syslog.c0100644000175100001440000001476606443103542013651 0ustar mdusers/* $Revision: 1.12 $ ** Modified by Rich $alz to be more portable to older ** systems. */ /*#define INET_SYSLOG */ /* * Copyright (c) 1983, 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)syslog.c 5.28 (Berkeley) 6/27/90"; #endif /* LIBC_SCCS and not lint */ /* * SYSLOG -- print message on log file * * This routine looks a lot like printf, except that it outputs to the * log file instead of the standard output. Also: * adds a timestamp, * prints the module name in front of the message, * has some other formatting types (or will sometime), * adds a newline on the end of the message. * * The output of this routine is intended to be read by syslogd(8). * * Author: Eric Allman * Modified to use UNIX domain IPC by Ralph Campbell */ #include #include #include #include "syslog.h" #if !defined(INET_SYSLOG) #include #else #include #include #endif /* !defined(INET_SYSLOG) */ #include #include #if defined(INET_SYSLOG) #include #endif /* defined(INET_SYSLOG) */ #ifndef _PATH_LOGNAME /* if you are running an old syslog, change /dev/log to the same as it * is in syslogd.c */ #define _PATH_LOGNAME "/dev/log" #endif #define index strchr #define _PATH_CONSOLE "/dev/console" static int LogFile = -1; /* fd for log */ static int connected; /* have done connect */ static int LogStat = 0; /* status bits, set by openlog() */ static char *LogTag = "syslog"; /* string to tag the entry with */ static int LogFacility = LOG_USER; /* default facility code */ extern char *index(), *strcpy(), *strncpy(), *strcat(); /* =()@ strlen();>()= */ extern size_t strlen(); /* ** Return a string representation of errno. */ static char * xstrerror(e) int e; { extern int sys_nerr; extern char *sys_errlist[]; static char buff[30]; if (e >= 0 && e < sys_nerr) return sys_errlist[e]; (void)sprintf(buff, "Error code %d\n", e); return buff; } /* VARARGS0 */ syslog(va_alist) va_dcl { int pri; char *fmt; va_list ap; va_start(ap); pri = va_arg(ap, int); fmt = va_arg(ap, char*); vsyslog(pri, fmt, ap); va_end(ap); } vsyslog(pri, fmt, ap) int pri; register char *fmt; va_list ap; { extern int errno; register int cnt; register char *p; time_t now, time(); int fd, saved_errno; char tbuf[2048], fmt_cpy[1024], *stdp, *ctime(); saved_errno = errno; /* see if we should just throw out this message */ if (!LOG_MASK(LOG_PRI(pri)) || (pri &~ (LOG_PRIMASK|LOG_FACMASK))) return; if (LogFile < 0 || !connected) openlog(LogTag, LogStat | LOG_NDELAY, 0); /* set default facility if none specified */ if ((pri & LOG_FACMASK) == 0) pri |= LogFacility; /* build the message */ (void)time(&now); (void)sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4); for (p = tbuf; *p; ++p); if (LogStat & LOG_PERROR) stdp = p; if (LogTag) { (void)strcpy(p, LogTag); for (; *p; ++p); } if (LogStat & LOG_PID) { (void)sprintf(p, "[%ld]", (long) getpid()); for (; *p; ++p); } if (LogTag) { *p++ = ':'; *p++ = ' '; } /* substitute error message for %m */ { register char ch, *t1, *t2; char *xstrerror(); for (t1 = fmt_cpy; ch = *fmt; ++fmt) if (ch == '%' && fmt[1] == 'm') { ++fmt; for (t2 = xstrerror(saved_errno); *t1 = *t2++; ++t1); } else *t1++ = ch; *t1 = '\0'; } (void)vsprintf(p, fmt_cpy, ap); cnt = strlen(tbuf); /* output to stderr if requested */ if (LogStat & LOG_PERROR) { struct iovec iov[2]; register struct iovec *v = iov; v->iov_base = stdp; v->iov_len = cnt - (stdp - tbuf); ++v; v->iov_base = "\n"; v->iov_len = 1; (void)writev(2, iov, 2); } /* output the message to the local logger */ if (send(LogFile, tbuf, cnt, 0) >= 0 || !(LogStat&LOG_CONS)) return; /* * output the message to the console; don't worry about * blocking, if console blocks everything will. */ if ((fd = open(_PATH_CONSOLE, O_WRONLY, 0)) < 0) return; (void)strcat(tbuf, "\r\n"); cnt += 2; p = index(tbuf, '>') + 1; (void)write(fd, p, cnt - (p - tbuf)); (void)close(fd); } #if !defined(INET_SYSLOG) static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */ #else static struct sockaddr_in SyslogAddr; /* AF_INET address of local logger */ #endif /* !defined(INET_SYSLOG) */ /* * OPENLOG -- open system log */ openlog(ident, logstat, logfac) char *ident; int logstat, logfac; { if (ident != NULL) LogTag = ident; LogStat = logstat; if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) LogFacility = logfac; if (LogFile == -1) { #if !defined(INET_SYSLOG) SyslogAddr.sa_family = AF_UNIX; strncpy(SyslogAddr.sa_data, _PATH_LOGNAME, sizeof(SyslogAddr.sa_data)); if (LogStat & LOG_NDELAY) { LogFile = socket(AF_UNIX, SOCK_DGRAM, 0); fcntl(LogFile, F_SETFD, 1); } #else SyslogAddr.sin_family = AF_INET; SyslogAddr.sin_port = htons(514); SyslogAddr.sin_addr.s_addr = INADDR_ANY; if (LogStat & LOG_NDELAY) { LogFile = socket(AF_INET, SOCK_DGRAM, 0); fcntl(LogFile, F_SETFD, 1); } #endif /* !defined(INET_SYSLOG) */ } if (LogFile != -1 && !connected && connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) != -1) connected = 1; } /* * CLOSELOG -- close the system log */ closelog() { (void) close(LogFile); LogFile = -1; connected = 0; } static int LogMask = 0xff; /* mask of priorities to be logged */ /* * SETLOGMASK -- set the log mask level */ setlogmask(pmask) int pmask; { int omask; omask = LogMask; if (pmask != 0) LogMask = pmask; return (omask); } inn-1.7.2/syslog/syslog.30100644000175100001440000001256706443103542013566 0ustar mdusers.\" $Revision: 1.2 $ .\" Copyright (c) 1985 The Regents of the University of California. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms are permitted provided .\" that: (1) source distributions retain this entire copyright notice and .\" comment, and (2) distributions including binaries display the following .\" acknowledgement: ``This product includes software developed by the .\" University of California, Berkeley and its contributors'' in the .\" documentation or other materials provided with the distribution and in .\" all advertising materials mentioning features or use of this software. .\" Neither the name of the University nor the names of its contributors may .\" be used to endorse or promote products derived from this software without .\" specific prior written permission. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .\" @(#)syslog.3 6.13 (Berkeley) 6/23/90 .\" .TH SYSLOG 3 "June 23, 1990" .UC 5 .SH NAME syslog, openlog, closelog, setlogmask, vsyslog \- control system log .SH SYNOPSIS .B "#include .PP .B "openlog(ident, logopt, facility) .br .B "char *ident; .PP .B "syslog(priority, message, parameters ... ) .br .B "int priority; .br .B "char *message; .PP .B "#include .br .B "vsyslog(priority, message, args) .br .B "int priority; .br .B "char *message; .br .B "va_list args; .PP .B "closelog() .PP .B "setlogmask(maskpri) .SH DESCRIPTION .I Syslog arranges to write .I message onto the system log maintained by .IR syslogd (8). The message is tagged with .IR priority . The message looks like a .IR printf (3) string except that .B %m is replaced by the current error message (as referenced by .IR errno ). A trailing newline is added if needed. An alternate form, in which the arguments have already been captured using the variable-length argument facilities of .IR varargs (3), is available under the name .IR vsyslog . .PP This message will be read by .IR syslogd (8) and written to the system console, log files, or forwarded to .I syslogd on another host as appropriate. .PP Priorities are encoded as a .I facility and a .IR level . The facility describes the part of the system generating the message. The level is selected from an ordered list: .TP LOG_ALERT A condition that should be corrected immediately, such as a corrupted system database. .TP LOG_CRIT Critical conditions, e.g., hard device errors. .TP LOG_DEBUG Messages that contain information normally of use only when debugging a program. .TP LOG_EMERG A panic condition. This is normally broadcast to all users. .TP LOG_ERR Errors. .TP LOG_INFO Informational messages. .TP LOG_NOTICE Conditions that are not error conditions, but should possibly be handled specially. .TP LOG_WARNING Warning messages. .PP If .I syslog cannot pass the message to .IR syslogd , it will attempt to write the message to the console (``/dev/console'') if the LOG_CONS option is set (see below). .PP If special processing is needed, .I openlog can be called to initialize the log file. The parameter .I ident is a string that is prepended to every message. .I Logopt is a bit field indicating logging options. Current values for .I logopt are: .TP LOG_CONS If unable to send the message to .IR syslogd , write it to the console. .TP LOG_NDELAY Open the connection to .I syslogd immediately. Normally the open is delayed until the first message is logged. Useful for programs that need to manage the order in which file descriptors are allocated. .TP LOG_PERROR Write the message to stderr as well to the system log. .TP LOG_PID Log the process id with each message: useful for identifying instantiations of daemons. .PP The .I facility parameter encodes a default facility to be assigned to all messages that do not have an explicit facility encoded: .TP LOG_AUTH The authorization system: .IR login (1), .IR su (1), .IR getty (8), etc. .TP LOG_CRON The clock daemon. .TP LOG_DAEMON System daemons, such as .IR ftpd (8), .IR routed (8), etc, that are not provided for explicitly by other facilities. .TP LOG_KERN Messages generated by the kernel. These cannot be generated by any user processes. .TP LOG_LPR The line printer spooling system: .IR lpr (1), .IR lpc (8), .IR lpd (8), etc. .TP LOG_MAIL The mail system. .TP LOG_NEWS The network news system. .TP LOG_SYSLOG Messages generated internally by .IR syslogd (8). .TP LOG_USER Messages generated by random user processes. This is the default facility identifier if none is specified. .TP LOG_UUCP The uucp system. .TP LOG_LOCAL0 Reserved for local use. Similarly for LOG_LOCAL1 through LOG_LOCAL7. .PP .I Closelog can be used to close the log file. .PP .I Setlogmask sets the log priority mask to .I maskpri and returns the previous mask. Calls to .I syslog with a priority not set in .I maskpri are rejected. The mask for an individual priority .I pri is calculated by the macro LOG_MASK(\fIpri\fP); the mask for all priorities up to and including .I toppri is given by the macro LOG_UPTO(\fItoppri\fP). The default allows all priorities to be logged. .SH EXAMPLES .nf syslog(LOG_ALERT, "who: internal error 23"); openlog("ftpd", LOG_PID, LOG_DAEMON); setlogmask(LOG_UPTO(LOG_ERR)); syslog(LOG_INFO, "Connection from host %d", CallingHost); syslog(LOG_INFO|LOG_LOCAL2, "foobar error: %m"); .fi .SH "SEE ALSO" logger(1), syslogd(8) inn-1.7.2/syslog/README0100644000175100001440000000342206443103542013030 0ustar mdusers$Revision: 1.3 $ InterNetNews uses the "three-arg" version of syslog. That version is standard with many systems (4.3BSD, SunOS4.x, etc). Some vendors have not yet upgraded, however. The principal difference between the two versions is that the current syslog divides reports up into "facilities." For example, news reports can be filed separately from mail or login report. If your system is running the older version of syslog, you should complain to your vendor. I also encourage you to bring up the syslog that is included in this directory and replace what is running on your system. The sources are from the freely-redistributable BSD sources, and the syslog.conf file matches the old actions pretty closely. If you can't replace the syslog on your machine, you can run two syslog daemons for awhile. Edit syslog.c and syslogd.c so that #define _PATH_LOGNAME "/dev/log" points to something like "/dev/newsyslog". In syslogd.c you should also do the following #define NO_INET_SOCKET this will prevent the new syslog daemon from listening on the Internet port (the old syslog daemon is presumably doing that). You should also do #undef _PATH_KLOG which will tell the daemon to not try to read Unix kernel log messages. Change #define _PATH_LOGCONF "/etc/syslog.conf" #define _PATH_LOGPID "/etc/syslog.pid" to something like "/etc/newsyslog.conf" and "/etc/newsyslog.pid" Finally, install the new syslogd and make sure that it is started at system boot time. Good luck. I haven't tried this -- I replaced the daemon on my machines -- but it should work without too many problems. On machines without Unix-domain sockets you can just add this line to the top of syslog.c: #define INET_SYSLOG and add syslog to the INN library as exlained in the installation manual. /rich $alz inn-1.7.2/syslog/logger.c0100644000175100001440000001026606443103542013577 0ustar mdusers/* $Revision: 1.4 $ ** Modified by Rich $alz to be more portable to older ** systems. */ /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that: (1) source distributions retain this entire copyright * notice and comment, and (2) distributions including binaries display * the following acknowledgement: ``This product includes software * developed by the University of California, Berkeley and its contributors'' * in the documentation or other materials provided with the distribution * and in all advertising materials mentioning features or use of this * software. Neither the name of the University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)logger.c 6.14 (Berkeley) 6/1/90"; #endif /* not lint */ #include #define SYSLOG_NAMES #include "syslog.h" #include /* ** LOGGER -- read and log utility ** ** This routine reads from an input and arranges to write the ** result on the system log, along with a useful tag. */ /* ** Return a string representation of errno. */ static char * xstrerror(e) int e; { extern int sys_nerr; extern char *sys_errlist[]; static char buff[30]; if (e >= 0 && e < sys_nerr) return sys_errlist[e]; (void)sprintf(buff, "Error code %d\n", e); return buff; } main(argc, argv) int argc; char **argv; { extern char *optarg; extern int errno, optind; int pri = LOG_NOTICE; int ch, logflags = 0; char *tag, buf[1024], *getlogin(); tag = NULL; while ((ch = getopt(argc, argv, "f:ip:st:")) != EOF) switch((char)ch) { case 'f': /* file to log */ if (freopen(optarg, "r", stdin) == NULL) { (void)fprintf(stderr, "logger: %s: %s.\n", optarg, xstrerror(errno)); exit(1); } break; case 'i': /* log process id also */ logflags |= LOG_PID; break; case 'p': /* priority */ pri = pencode(optarg); break; case 's': /* log to standard error */ logflags |= LOG_PERROR; break; case 't': /* tag */ tag = optarg; break; case '?': default: usage(); } argc -= optind; argv += optind; /* setup for logging */ openlog(tag ? tag : getlogin(), logflags, 0); (void) fclose(stdout); /* log input line if appropriate */ if (argc > 0) { register char *p, *endp; int len; for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) { len = strlen(*argv); if (p + len > endp && p > buf) { syslog(pri, "%s", buf); p = buf; } if (len > sizeof(buf) - 1) syslog(pri, "%s", *argv++); else { if (p != buf) *p++ = ' '; bcopy(*argv++, p, len); *(p += len) = '\0'; } } if (p != buf) syslog(pri, "%s", buf); exit(0); } /* main loop */ while (fgets(buf, sizeof(buf), stdin) != NULL) syslog(pri, "%s", buf); exit(0); } /* * Decode a symbolic name to a numeric value */ pencode(s) register char *s; { char *save; int fac, lev; for (save = s; *s && *s != '.'; ++s); if (*s) { *s = '\0'; fac = decode(save, facilitynames); if (fac < 0) bailout("unknown facility name: ", save); *s++ = '.'; } else { fac = 0; s = save; } lev = decode(s, prioritynames); if (lev < 0) bailout("unknown priority name: ", save); return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK)); } decode(name, codetab) char *name; CODE *codetab; { register CODE *c; if (isdigit(*name)) return (atoi(name)); for (c = codetab; c->c_name; c++) if (!strcasecmp(name, c->c_name)) return (c->c_val); return (-1); } bailout(msg, arg) char *msg, *arg; { fprintf(stderr, "logger: %s%s\n", msg, arg); exit(1); } usage() { fputs("logger: [-i] [-f file] [-p pri] [-t tag] [ message ... ]\n", stderr); exit(1); } inn-1.7.2/include/0040755000175100001440000000000006443103542012255 5ustar mdusersinn-1.7.2/include/qio.h0100644000175100001440000000145306443103542013216 0ustar mdusers/* $Revision: 1.2 $ ** ** Quick I/O package -- optimized for reading through a file. */ /* ** State for a quick open file. */ typedef struct _QIOSTATE { int fd; int Size; int flag; int Length; char *Buffer; char *End; char *Start; long Count; } QIOSTATE; /* A reasonable buffersize to use. */ #define QIO_BUFFER 8192 /* Values for QIOstate.flag */ #define QIO_ok 0 #define QIO_error 1 #define QIO_long 2 #define QIOerror(qp) ((qp)->flag > 0) #define QIOtoolong(qp) ((qp)->flag == QIO_long) #define QIOtell(qp) ((qp)->Count - ((qp)->End - (qp)->Start)) #define QIOlength(qp) ((qp)->Length) #define QIOfileno(qp) ((qp)->fd) extern char *QIOread(); extern QIOSTATE *QIOopen(); extern QIOSTATE *QIOfdopen(); extern void QIOclose(); extern int QIOrewind(); inn-1.7.2/include/clibrary.h0100644000175100001440000001056006443103542014234 0ustar mdusers/* $Revision: 1.27 $ ** ** Here be declarations of routines and variables in the C library. ** You must #include and before this file. */ #if defined(DO_HAVE_UNISTD) #include #endif /* defined(DO_HAVE_UNISTD) */ #if defined(DO_HAVE_VFORK) #include #endif /* defined(DO_HAVE_VFORK) */ #include /* Generic pointer, used by memcpy, malloc, etc. */ /* =()@ *POINTER;>()= */ typedef void *POINTER; /* Const generic pointer, used by qsort. */ /* =()@ *CPOINTER;>()= */ typedef const void *CPOINTER; /* What is a file offset? Will not work unless long! */ /* =()@ OFFSET_T;>()= */ typedef long OFFSET_T; /* What is the type of an object size? */ /* =()@ SIZE_T;>()= */ typedef size_t SIZE_T; /* What is the type of a passwd uid and gid, for use in chown(2)? */ /* =()@ UID_T;>()= */ typedef uid_t UID_T; /* =()@ GID_T;>()= */ typedef gid_t GID_T; /* =()@ PID_T;>()= */ typedef pid_t PID_T; /* =()@ U_INT32_T;>()= */ typedef unsigned int U_INT32_T; /* =()@ INT32_T;>()= */ typedef int INT32_T; #include /* What should a signal handler return? */ /* =()<#define SIGHANDLER @@>()= */ #define SIGHANDLER void #if defined(SIG_DFL) /* What types of variables can be modified in a signal handler? */ /* =()@ SIGVAR;>()= */ typedef sig_atomic_t SIGVAR; #endif /* defined(SIG_DFL) */ /* =()<#include @@>()= */ #include /* =()<#include @@>()= */ #include #include /* ** It's a pity we have to go through these contortions, for broken ** systems that have fd_set but not the FD_SET. */ #if defined(FD_SETSIZE) #define FDSET fd_set #else #include #if !defined(NOFILE) error -- #define NOFILE to the number of files allowed on your machine! #endif /* !defined(NOFILE) */ #if !defined(howmany) #define howmany(x, y) (((x) + ((y) - 1)) / (y)) #endif /* !defined(howmany) */ #define FD_SETSIZE NOFILE #define NFDBITS (sizeof (long) * 8) typedef struct _FDSET { long fds_bits[howmany(FD_SETSIZE, NFDBITS)]; } FDSET; #define FD_SET(n, p) (p)->fds_bits[(n) / NFDBITS] |= (1 << ((n) % NFDBITS)) #define FD_CLR(n, p) (p)->fds_bits[(n) / NFDBITS] &= ~(1 << ((n) % NFDBITS)) #define FD_ISSET(n, p) ((p)->fds_bits[(n) / NFDBITS] & (1 << ((n) % NFDBITS))) #define FD_ZERO(p) (void)memset((POINTER)(p), 0, sizeof *(p)) #endif /* defined(FD_SETSIZE) */ #if !defined(SEEK_SET) #define SEEK_SET 0 #endif /* !defined(SEEK_SET) */ #if !defined(SEEK_END) #define SEEK_END 2 #endif /* !defined(SEEK_END) */ /* ** We must use #define to set FREEVAL, since "typedef void FREEVAL;" doesn't ** work on some broken compilers, sigh. */ /* =()<#define FREEVAL @@>()= */ #define FREEVAL void extern int optind; extern char *optarg; #if !defined(__STDC__) extern int errno; #endif /* !defined(__STDC__) */ extern char *crypt(); extern char *getenv(); extern char *inet_ntoa(); extern char *mktemp(); #if !defined(strerror) extern char *strerror(); #endif /* !defined(strerror) */ extern long atol(); extern time_t time(); extern unsigned long inet_addr(); extern FREEVAL free(); extern POINTER malloc(); extern POINTER realloc(); #if defined (ACT_MMAP) || defined(MMAP) /* =()@ MMAP_PTR;>()= */ typedef caddr_t MMAP_PTR; extern MMAP_PTR mmap(); #endif /* defined (ACT_MMAP) || defined(MMAP) */ /* Some backward systems need this. */ extern FILE *popen(); /* This is in , but not in some system string headers, * so we put it here just in case. */ extern int strncasecmp(); /* =()@ abort();>()= */ extern void abort(); /* =()@ alarm();>()= */ extern unsigned int alarm(); /* =()@ exit();>()= */ extern void exit(); /* =()@ getpid();>()= */ extern pid_t getpid(); /* =()@ lseek();>()= */ extern off_t lseek(); /* =()@ qsort();>()= */ extern void qsort(); /* =()@ sleep();>()= */ extern unsigned int sleep(); /* =()@ _exit();>()= */ extern void _exit(); #if defined(DO_HAVE_SETPROCTITLE) extern void setproctitle(); #endif /* defined(DO_HAVE_SETPROCTITLE) */ inn-1.7.2/include/mymemory.h0100644000175100001440000000023406443103542014300 0ustar mdusers/* $Revision: 1.2 $ ** ** Minimal file for systems without one. */ extern POINTER memchr(); extern POINTER memcpy(); extern POINTER memset(); inn-1.7.2/include/nntp.h0100644000175100001440000001173706443103542013413 0ustar mdusers/* $Revision: 1.21 $ ** ** Here be a set of NNTP response codes as defined in RFC977 and elsewhere. ** The reponse codes are three digits, RFI, defined like this: ** R, Response: ** 1xx Informative message ** 2xx Command ok ** 3xx Command ok so far, send the rest of it. ** 4xx Command was correct, but couldn't be performed for ** some reason. ** 5xx Command unimplemented, or incorrect, or a serious ** program error occurred. ** F, Function: ** x0x Connection, setup, and miscellaneous messages ** x1x Newsgroup selection ** x2x Article selection ** x3x Distribution functions ** x4x Posting ** x8x Nonstandard extensions (AUTHINFO, XGTITLE) ** x9x Debugging output ** I, Information: ** No defined semantics */ #define NNTP_HELPOK_VAL 100 #define NNTP_BAD_COMMAND_VAL 500 #define NNTP_BAD_COMMAND "500 Syntax error or bad command" #define NNTP_TEMPERR_VAL 503 #define NNTP_ACCESS "502 Permission denied" #define NNTP_ACCESS_VAL 502 #define NNTP_GOODBYE_ACK "205 ." #define NNTP_GOODBYE_ACK_VAL 205 #define NNTP_GOODBYE "400" #define NNTP_GOODBYE_VAL 400 #define NNTP_HAVEIT "435 Duplicate" #define NNTP_HAVEIT_BADID "435 Bad Message-ID" #define NNTP_HAVEIT_VAL 435 #define NNTP_LIST_FOLLOWS "215" #define NNTP_LIST_FOLLOWS_VAL 215 #define NNTP_HELP_FOLLOWS "100 Legal commands" #define NNTP_HELP_FOLLOWS_VAL 100 #define NNTP_NOTHING_FOLLOWS_VAL 223 #define NNTP_ARTICLE_FOLLOWS "220" #define NNTP_ARTICLE_FOLLOWS_VAL 220 #define NNTP_NEWGROUPS_FOLLOWS_VAL 231 #define NNTP_HEAD_FOLLOWS "221" #define NNTP_HEAD_FOLLOWS_VAL 221 #define NNTP_BODY_FOLLOWS_VAL 222 #define NNTP_OVERVIEW_FOLLOWS_VAL 224 #define NNTP_DATE_FOLLOWS_VAL 111 #define NNTP_POSTOK "200" #define NNTP_POSTOK_VAL 200 #define NNTP_START_POST_VAL 340 #define NNTP_NOPOSTOK_VAL 201 #define NNTP_SLAVEOK_VAL 202 #define NNTP_REJECTIT_VAL 437 #define NNTP_REJECTIT_EMPTY "437 Empty article" #define NNTP_DONTHAVEIT "430" #define NNTP_DONTHAVEIT_VAL 430 #define NNTP_RESENDIT_VAL 436 #define NNTP_POSTEDOK "240 Article posted" #define NNTP_POSTEDOK_VAL 240 #define NNTP_POSTFAIL_VAL 441 #define NNTP_GROUPOK_VAL 211 #define NNTP_SENDIT "335" #define NNTP_SENDIT_VAL 335 #define NNTP_SYNTAX_USE "501 Bad command use" #define NNTP_SYNTAX_VAL 501 #define NNTP_TOOKIT "235" #define NNTP_TOOKIT_VAL 235 #define NNTP_NOTINGROUP "412 Not in a newsgroup" #define NNTP_NOTINGROUP_VAL 412 #define NNTP_NOSUCHGROUP "411 No such group" #define NNTP_NOSUCHGROUP_VAL 411 #define NNTP_NEWNEWSOK "230 New news follows" #define NNTP_NOARTINGRP "423 Bad article number" #define NNTP_NOARTINGRP_VAL 423 #define NNTP_NOCURRART "420 No current article" #define NNTP_NOCURRART_VAL 420 #define NNTP_NONEXT_VAL 421 #define NNTP_NOPREV_VAL 422 #define NNTP_CANTPOST "440 Posting not allowed" #define NNTP_CANTPOST_VAL 440 #define NNTP_SERVER_TOOBUSY "504 Server overloaded, try later" #define NNTP_SERVER_TOOBUSY_VAL 504 #define NNTP_TOO_MANY_CONNECTS "505 Connection rejected, you're making too many connects per minute" #define NNTP_TOO_MANY_CONNECTS_VAL 505 /* new entries for the "streaming" protocol */ /* response to "mode stream" else 500 if stream not supported */ #define NNTP_OK_STREAM_VAL 203 /* Streaming supported */ /* response to "check ". Must include ID of article. ** Example: "431 <1234@host.domain>" */ #define NNTP_OK_SENDID_VAL 238 /* I want article */ #define NNTP_RESENDID_VAL 431 /* try again later */ #define NNTP_ERR_GOTID_VAL 438 /* Got , don't send */ /* responses to "takethis . Must include ID of article */ #define NNTP_OK_RECID_VAL 239 /* Article received OK */ #define NNTP_ERR_FAILID_VAL 439 /* Transfer of failed */ /* End of new entries for the "streaming" protocol */ /* ** The first character of an NNTP reply can be used as a category class. */ #define NNTP_CLASS_OK '2' #define NNTP_CLASS_ERROR '4' #define NNTP_CLASS_FATAL '5' /* ** The NNTP protocol currently has no way to say "offer me this article ** later, but don't close the connection." That will be fixed in NNTP2. #define NNTP_RESENDIT_LATER "?" #define NNTP_RESENDIT_LATER_VAL ? */ /* ** Authentication commands from the RFC update (not official). */ #define NNTP_AUTH_NEEDED "480" #define NNTP_AUTH_NEEDED_VAL 480 #define NNTP_AUTH_BAD "481" #define NNTP_AUTH_NEXT "381" #define NNTP_AUTH_NEXT_VAL 381 #define NNTP_AUTH_OK "281" #define NNTP_AUTH_OK_VAL 281 #define NNTP_AUTH_REJECT_VAL 482 /* ** XGTITLE, from ANU news. */ #define NNTP_XGTITLE_BAD 481 /* Yes, 481. */ #define NNTP_XGTITLE_OK 282 #define NNTP_OK_XBATCHED_VAL 239 /* Batch transferred successfully */ #define NNTP_OK_XBATCHED "239" #define NNTP_CONT_XBATCH_VAL 339 /* Continue to send batch */ #define NNTP_CONT_XBATCH "339" /* and one more meaning for the 436 code NNTP_RESENDIT_VAL */ #define NNTP_RESENDIT_XBATCHERR "436 xbatch failed: " /* and one more meaning for the 501 code NNTP_SYNTAX_USE */ #define NNTP_XBATCH_BADSIZE "501 Invalid or missing size for xbatch" #define NNTP_STRLEN 512 inn-1.7.2/include/mystring.h0100644000175100001440000000070206443103542014276 0ustar mdusers/* $Revision: 1.3 $ ** ** Minimal file for systems without one. */ extern char *strcat(); extern char *strchr(); extern char *strcpy(); extern char *strncat(); extern char *strncpy(); extern char *strpbrk(); extern char *strrchr(); extern char *strstr(); extern char *strtok(); extern int strcasecmp(); extern int strncasecmp(); extern int strcmp(); extern int strcspn(); extern int strlen(); extern int strncmp(); extern int strspn(); inn-1.7.2/include/patchlevel.h0100644000175100001440000000076206443103542014557 0ustar mdusers/* * $Revision: 1.22 $ */ /* ** If you make local modifications to INN, change this line as needed: */ #define LOCAL_STRING "" /* ** Try to avoid changing these. */ #define RELEASE "1" #define PATCHLEVEL "7.2" #define DATE "08-Dec-1997" /* ** See lib/innvers.c, but the version string should look like this: ** INN ${RELEASE}.${PATCHLEVEL} ${DATE} (${LOCAL_STRING}) ** for example: ** INN 1.0 10-Feb-92 (FOO.COM) */ #define RELEASE_C 1 #define PATCHLEVEL_C 7 #define SUB_PATCHLEVEL_C 1 inn-1.7.2/include/configdata.h0100644000175100001440000004034606443103542014531 0ustar mdusers/* $Revision: 1.43 $ ** ** Here be configuration data used by various InterNetNews programs. ** The numbers refer to sections in the config.dist file. */ #if ! defined (__configdata_h__) #define __configdata_h__ 1 /* ** 1. MAKE CONFIG PARAMETERS */ /* =()<#define @@_USE_CHAR_CONST>()= */ #define DUNNO_USE_CHAR_CONST #if defined(DO_USE_CHAR_CONST) typedef char const *STRING; typedef char * const CSTRING; #endif /* defined(DO_USE_CHAR_CONST) */ #if defined(DONT_USE_CHAR_CONST) typedef char *STRING; typedef char *CSTRING; #endif /* defined(DONT_USE_CHAR_CONST) */ #if defined(DUNNO_USE_CHAR_CONST) #if defined(__STDC__) typedef char const *STRING; typedef char * const CSTRING; #else typedef char *STRING; typedef char *CSTRING; #endif /* defined(__STDC__) */ #endif /* defined(DUNNO_USE_CHAR_CONST) */ /* ** Declare a function that doesn't return. */ #if defined(__dead) /* BSD4.4 */ #define NORETURN __dead void #else #if defined(__GNUC__) /* GCC */ #define NORETURN volatile void #else /* Everyone else */ #define NORETURN void #endif /* defined(__GNUC__) */ #endif /* defined(__dead) */ /* ** 3. OWNERSHIPS AND FILE MODES */ /* =()<#define NEWSUSER "@@">()= */ #define NEWSUSER "news" /* =()<#define NEWSGID "@@">()= */ #define NEWSGID "news" /* =()<#define NEWSMASTER "@@">()= */ #define NEWSMASTER "usenet" /* =()<#define PATHMASTER "@@">()= */ #define PATHMASTER "not-for-mail" /* Umask to set. */ /* =()<#define NEWSUMASK @@>()= */ #define NEWSUMASK 02 /* Mode that incoming articles are created under. */ /* =()<#define ARTFILE_MODE @@>()= */ #define ARTFILE_MODE 0664 /* Mode that batch files are created under. */ /* =()<#define BATCHFILE_MODE @@>()= */ #define BATCHFILE_MODE 0664 /* Mode that directories are created under. */ /* =()<#define GROUPDIR_MODE @@>()= */ #define GROUPDIR_MODE 0775 /* ** 4. C LIBRARY DIFFERENCES */ /* Use have stdargs, varargs, or neither? */ /* =()<#define VAR_@@>()= */ #define VAR_STDARGS /* Use BSD4.2 or Posix directory names? */ /* =()<#define DIR_@@>()= */ #define DIR_DIRENT /* Use flock, lockf, or nothing to lock files? */ /* =()<#define LOCK_@@>()= */ #define LOCK_FLOCK /* Do you have ? */ /* =()<#define @@_HAVE_UNISTD>()= */ #define DO_HAVE_UNISTD /* Do you have setbuffer? */ /* =()<#define @@_HAVE_SETBUFFER>()= */ #define DO_HAVE_SETBUFFER /* Do you have gettimeofday? */ /* =()<#define @@_HAVE_GETTIMEOFDAY>()= */ #define DO_HAVE_GETTIMEOFDAY /* Do you have fchmod? */ /* =()<#define @@_HAVE_FCHMOD>()= */ #define DO_HAVE_FCHMOD /* Do you have setproctitle()? */ /* =()<#define @@_HAVE_SETPROCTITLE>()= */ #define DO_HAVE_SETPROCTITLE /* Do you have setsid()? */ /* =()<#define @@_HAVE_SETSID>()= */ #define DO_HAVE_SETSID /* Does your (struct tm) have a tm_gmtoff field? */ /* =()<#define @@_HAVE_TM_GMTOFF>()= */ #define DO_HAVE_TM_GMTOFF /* Does your (struct stat) have a st_blksize field? */ /* =()<#define @@_HAVE_ST_BLKSIZE>()= */ #define DO_HAVE_ST_BLKSIZE /* Use waitpid instead of wait3? */ /* =()<#define @@_HAVE_WAITPID>()= */ #define DO_HAVE_WAITPID /* Use "union wait" instead of int? */ /* =()<#define @@_USE_UNION_WAIT>()= */ #define DONT_USE_UNION_WAIT /* How to fork? */ /* =()<#define FORK() @@()>()= */ #define FORK() vfork() /* Do you have symbolic links? */ /* =()<#define @@_HAVE_SYMLINK>()= */ #define DO_HAVE_SYMLINK /* Does your AF_UNIX bind use sizeof for the socket size? */ /* =()<#define @@_BIND_USE_SIZEOF>()= */ #define DO_BIND_USE_SIZEOF /* Do you have Unix-domain sockets? */ /* =()<#define @@_HAVE_UNIX_DOMAIN>()= */ #define DO_HAVE_UNIX_DOMAIN /* How should close-on-exec be done? */ /* =()<#define CLX_@@>()= */ #define CLX_IOCTL /* How should non-blocking I/O be done? */ /* =()<#define NBIO_@@>()= */ #define NBIO_FCNTL /* How should resource-totalling be done? */ /* =()<#define RES_@@>()= */ #define RES_RUSAGE /* How to get number of available descriptors? */ /* =()<#define FDCOUNT_@@>()= */ #define FDCOUNT_GETRLIMIT /* If greater than -1, then use [gs]etrlimit to set that many descriptors. */ /* If -1, then no [gs]etrlimit calls are done. */ /* =()<#define NOFILE_LIMIT @@>()= */ #define NOFILE_LIMIT -1 /* Do you need as well as ? */ /* =()<#define @@_NEED_TIME>()= */ #define DONT_NEED_TIME /* What predicate, if any, the macros need. */ /* =()<#define CTYPE(isXXXXX, c) (@@)>()= */ #define CTYPE(isXXXXX, c) ((isascii((c)) && isXXXXX((c)))) /* ** 6. MISCELLANEOUS CONFIG DATA */ /* Use mmap() to read the active file, or read it in? */ /* =()<#define ACT_@@>()= */ #define ACT_READ /* Should the routines that use mmap() also do a msync(). */ /* =()<#define @@_MMAP_SYNC>()= */ #define DONT_MMAP_SYNC /* Does the msync() function take 3 arguments? DO or DONT */ /* =()<#define @@_MSYNC_3_ARG>()= */ #define DONT_MSYNC_3_ARG /* Use our NNTP-server-open routine, or the one in NNTP? */ /* INND is nicer, but you must install inn.conf files everywhere; NNTP */ /* is better if you already have lots of /usr/lib/news/server files. */ /* =()<#define REM_@@>()= */ #define REM_INND /* Should rnews save articles that the server rejects? */ /* =()<#define @@_RNEWS_SAVE_BAD>()= */ #define DONT_RNEWS_SAVE_BAD /* Should rnews syslog articles innd already has? */ /* =()<#define @@_RNEWS_LOG_DUPS>()= */ #define DONT_RNEWS_LOG_DUPS /* Look in _PATH_RNEWSPROGS for rnews unpackers? */ /* =()<#define @@_RNEWSPROGS>()= */ #define DO_RNEWSPROGS /* Should rnews try the local host? */ /* =()<#define @@_RNEWSLOCALCONNECT>()= */ #define DO_RNEWSLOCALCONNECT /* Disallow posts with more than 50% inclusion (">") lines? */ /* (This is only for inews and nnrpd.) */ /* =()<#define @@_CHECK_INCLUDED_TEXT>()= */ #define DO_CHECK_INCLUDED_TEXT /* Put hosts in the inews Path header? */ /* =()<#define @@_INEWS_PATH>()= */ #define DO_INEWS_PATH /* Munge the gecos field of password entry? */ /* =()<#define @@_MUNGE_GECOS>()= */ #define DO_MUNGE_GECOS /* How many times to try before giving up */ /* =()<#define MAX_FORKS @@>()= */ #define MAX_FORKS 10 /* Largest acceptable article size; 0 allows any size */ /* =()<#define MAX_ART_SIZE @@>()= */ #define MAX_ART_SIZE 1000000L /* Value of dbzincore(FLAG) call in innd. */ /* =()<#define INND_DBZINCORE @@>()= */ #define INND_DBZINCORE 1 /* Should sub-processes get a nice(2) value? */ /* =()<#define @@_INND_NICE_KIDS>()= */ #define DO_INND_NICE_KIDS /* Value for nice(2) call in innd. */ /* =()<#define INND_NICE_VALUE @@>()= */ #define INND_NICE_VALUE 4 /* Null-terminated list of unknown commands to not log to syslog. */ /* =()<#define INND_QUIET_BADLIST @@>()= */ #define INND_QUIET_BADLIST NULL /* Null-terminated set of illegal distribution patterns. */ /* =()<#define BAD_DISTRIBS @@>()= */ #define BAD_DISTRIBS "*.*",NULL /* Check that poster is the person doing the cancel? */ /* =()<#define @@_VERIFY_CANCELS>()= */ #define DONT_VERIFY_CANCELS /* Log "ctlinnd cancel" commands to syslog? */ /* =()<#define @@_LOG_CANCEL_COMMANDS>()= */ #define DONT_LOG_CANCEL_COMMANDS /* File unknown "to.*" groups into the "to" newsgroup? */ /* =()<#define @@_MERGE_TO_GROUPS>()= */ #define DONT_MERGE_TO_GROUPS /* File articles in unknown newsgroups into junk? */ /* =()<#define @@_WANT_TRASH>()= */ #define DONT_WANT_TRASH /* Record rejected articles in history? */ /* =()<#define @@_REMEMBER_TRASH>()= */ #define DO_REMEMBER_TRASH /* Check the linecount against the Lines header? */ /* =()<#define @@_CHECK_LINECOUNT>()= */ #define DONT_CHECK_LINECOUNT /* If checking, the error must be within LINECOUNT_FUZZ lines. */ /* =()<#define LINECOUNT_FUZZ @@>()= */ #define LINECOUNT_FUZZ 5 /* Have innd throttle itself after this many I/O errors. */ /* =()<#define IO_ERROR_COUNT @@>()= */ #define IO_ERROR_COUNT 50 /* Default value for ctlinnd -t flag. */ /* =()<#define CTLINND_TIMEOUT @@>()= */ #define CTLINND_TIMEOUT 0 /* Flush logs (and NNRP connections) if we go this long with no I/O. */ /* =()<#define DEFAULT_TIMEOUT @@>()= */ #define DEFAULT_TIMEOUT 300 /* INND closes channel if inactive this long (seconds). */ /* =()<#define PEER_TIMEOUT @@>()= */ #define PEER_TIMEOUT (1 * 60 * 60) /* NNRP exits if first command doesn't arrive within this time (seconds).*/ /* =()<#define INITIAL_TIMEOUT @@>()= */ #define INITIAL_TIMEOUT 30 /* NNRP exits if inactive this long (seconds). */ /* =()<#define CLIENT_TIMEOUT @@>()= */ #define CLIENT_TIMEOUT (10 * 60) /* Allow nnrpd readers when paused or throttled? */ /* =()<#define @@_ALLOW_READERS>()= */ #define DO_ALLOW_READERS /* Refuse NNTP connections if load is higher then this; -1 disables. */ /* =()<#define NNRP_LOADLIMIT @@>()= */ #define NNRP_LOADLIMIT 16 /* Don't readdir() spool dir if same group within this many seconds. */ /* =()<#define NNRP_RESCAN_DELAY @@>()= */ #define NNRP_RESCAN_DELAY 60 /* Do gethostbyaddr on client addresses in nnrp? */ /* =()<#define @@_NNRP_GETHOSTBYADDR>()= */ #define DO_NNRP_GETHOSTBYADDR /* Should nnrpd do a dbzincore? */ /* =()<#define NNRP_DBZINCORE_DELAY @@>()= */ #define NNRP_DBZINCORE_DELAY 40 /* Strip Sender from posts that did authenticate? */ /* =()<#define @@_NNRP_AUTH_SENDER>()= */ #define DO_NNRP_AUTH_SENDER /* Make life easy for sucking feeds. DO or DONT */ /* =()<#define @@_LIKE_PULLERS>()= */ #define DONT_LIKE_PULLERS /* Allow the NEWNEWS NNTP command? */ /* =()<#define @@_ALLOW_NEWNEWS>()= */ #define DONT_ALLOW_NEWNEWS /* How many read/write failures until channel is put to sleep or closed? */ /* =()<#define BAD_IO_COUNT @@>()= */ #define BAD_IO_COUNT 5 /* Multiplier for sleep in EWOULDBLOCK writes (seconds). */ /* =()<#define BLOCK_BACKOFF @@>()= */ #define BLOCK_BACKOFF (2 * 60) /* How many article-writes between active and history updates? */ /* =()<#define ICD_SYNC_COUNT @@>()= */ #define ICD_SYNC_COUNT 10 /* Tell resolver _res.options to be fast? */ /* =()<#define @@_FAST_RESOLV>()= */ #define DONT_FAST_RESOLV /* Drop articles that were posted this many days ago. */ /* =()<#define DEFAULT_CUTOFF @@>()= */ #define DEFAULT_CUTOFF 14 /* Maximum number of incoming NNTP connections. */ /* =()<#define DEFAULT_CONNECTIONS @@>()= */ #define DEFAULT_CONNECTIONS 50 /* Wait this many seconds before channel restarts. */ /* =()<#define CHANNEL_RETRY_TIME @@>()= */ #define CHANNEL_RETRY_TIME (5 * 60) /* Wait this many seconds before seeing if pause is ended. */ /* =()<#define PAUSE_RETRY_TIME @@>()= */ #define PAUSE_RETRY_TIME (5 * 60) /* Wait this many seconds before seeing if pause is ended. */ /* =()<#define CHANNEL_INACTIVE_TIME @@>()= */ #define CHANNEL_INACTIVE_TIME (10 * 60) /* Put nntplink info (filename) into the log? */ /* =()<#define @@_NNTPLINK_LOG>()= */ #define DONT_NNTPLINK_LOG /* Put article size into the log? */ /* =()<#define @@_LOG_SIZE>()= */ #define DO_LOG_SIZE /* Log by host IP address, rather than from Path line? */ /* =()<#define @@_IPADDR_LOG>()= */ #define DO_IPADDR_LOG /* Log NNTP activity after this many articles. */ /* =()<#define NNTP_ACTIVITY_SYNC @@>()= */ #define NNTP_ACTIVITY_SYNC 200 /* Free buffers bigger than this when we're done with them. */ /* =()<#define BIG_BUFFER @@>()= */ #define BIG_BUFFER (2 * START_BUFF_SIZE) /* A general small buffer. */ /* =()<#define SMBUF @@>()= */ #define SMBUF 256 /* Buffer for a single article name. */ /* =()<#define MAXARTFNAME @@>()= */ #define MAXARTFNAME 10 /* Buffer for a single pathname in the spool directory. */ /* =()<#define SPOOLNAMEBUFF @@>()= */ #define SPOOLNAMEBUFF 512 /* Maximum size of a single header. */ /* =()<#define MAXHEADERSIZE @@>()= */ #define MAXHEADERSIZE 1024 /* Byte limit on locally-posted articles; 0 to disable the check. */ /* =()<#define LOCAL_MAX_ARTSIZE @@>()= */ #define LOCAL_MAX_ARTSIZE 1000000L /* Default number of bytes to hold in memory when buffered. */ /* =()<#define SITE_BUFFER_SIZE @@>()= */ #define SITE_BUFFER_SIZE (16 * 1024) /* Should Inn be calling setsockopt() on network fds. */ /* =()<#define @@_SET_SOCKOPT @@>()= */ #define DO_SET_SOCKOPT DO /* Function that returns no value, and a pointer to it. */ /* =()<#define FUNCTYPE @@>()= */ #define FUNCTYPE void typedef FUNCTYPE (*FUNCPTR)(); /* While reading input, if we have less than LOW_WATER bytes free, we * use the current buffersize as input to GROW_AMOUNT to determine how * much to realloc. Growth must be at least NNTP_STRLEN bytes! */ #define START_BUFF_SIZE (4 * 1024) #define LOW_WATER (1 * 1024) #define GROW_AMOUNT(x) ((x) < 128 * 1024 ? (x) : 128 * 1024) /* Some debuggers might need this set to an empty string. */ #define STATIC static /* How to store article numbers; note that INN is not int/long clean. */ typedef unsigned long ARTNUM; /* A general convenience; you shouldn't have to change this. */ typedef int BOOL; /* General values that you should not have to change. */ #define MEMCPY_THRESHOLD 12 #define MAX_BUILTIN_ARGV 20 #define NNTP_PORT 119 #define TRUE 1 #define FALSE 0 #define MAXLISTEN 25 #define STDIN 0 #define STDOUT 1 #define STDERR 2 #define PIPE_READ 0 #define PIPE_WRITE 1 #define DATE_FUZZ (24L * 60L * 60L) #define COMMENT_CHAR '#' #define ART_ACCEPT '+' #define ART_CANC 'c' #define ART_JUNK 'j' #define ART_REJECT '-' #define EXP_CONTROL '!' #define FEED_MAXFLAGS 20 #define FEED_BYTESIZE 'b' #define FEED_FULLNAME 'f' #define FEED_HDR_DISTRIB 'D' #define FEED_HDR_NEWSGROUP 'N' #define FEED_MESSAGEID 'm' #define FEED_FNLNAMES '*' #define FEED_HEADERS 'H' #define FEED_NAME 'n' #define FEED_NEWSGROUP 'g' #define FEED_OVERVIEW 'O' #define FEED_REPLIC 'R' #define FEED_SITE 's' #define FEED_TIMERECEIVED 't' #define FEED_TIMEPOSTED 'p' #define HIS_BADCHAR '_' #define HIS_FIELDSEP '\t' #define HIS_NOEXP "-" #define HIS_SUBFIELDSEP '~' #define NF_FIELD_SEP ':' #define NF_FLAG_ALIAS '=' #define NF_FLAG_EXCLUDED 'j' #define NF_FLAG_MODERATED 'm' #define NF_FLAG_OK 'y' #define NF_FLAG_NOLOCAL 'n' #define NF_FLAG_IGNORE 'x' #define NF_SUBFIELD_SEP '/' #define NG_SEPARATOR "," #define NG_ISSEP(c) ((c) == ',') #define RNEWS_MAGIC1 '#' #define RNEWS_MAGIC2 '!' #define SIG_MAXLINES 4 #define SIG_SEPARATOR "-- \n" #define SUB_DEFAULT FALSE #define SUB_NEGATE '!' #define SUB_POISON '@' #define LOOPBACK_HOST "127.0.0.1" /* ** 13. TCL Support */ /* =()<#define @@_TCL>()= */ #define DONT_TCL /* ** 17. Perl Support */ /* =()<#define @@_PERL>()= */ #define DONT_PERL #endif /* ! defined (__configdata_h__) */ inn-1.7.2/include/logging.h0100644000175100001440000000245506443103542014057 0ustar mdusers/* $Revision: 1.8 $ ** ** The logging levels in syslog(3) are confusing. We use only three, ** and give them more meaningful names. See section 2 in config.dist. */ #include /* ** 2. LOGGING LEVELS */ /* Facility innd should log under. */ /* =()<#define LOG_INN_SERVER @@>()= */ #define LOG_INN_SERVER LOG_NEWS /* Facility all other programs should log under. */ /* =()<#define LOG_INN_PROG @@>()= */ #define LOG_INN_PROG LOG_NEWS /* Flags to use in opening the logs; some programs add LOG_PID. */ /* =()<#define L_OPENLOG_FLAGS @@>()= */ #define L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) /* Fatal error, program is about to exit. */ /* =()<#define L_FATAL @@>()= */ #define L_FATAL LOG_CRIT /* Log an error that might mean one or more articles get lost. */ /* =()<#define L_ERROR @@>()= */ #define L_ERROR LOG_ERR /* Informational notice, usually not worth caring about. */ /* =()<#define L_NOTICE @@>()= */ #define L_NOTICE LOG_WARNING /* A protocol trace. */ /* =()<#define L_TRACE @@>()= */ #define L_TRACE LOG_DEBUG /* All incoming control commands (ctlinnd, etc). */ /* =()<#define L_CC_CMD @@>()= */ #define L_CC_CMD LOG_INFO inn-1.7.2/include/macros.h0100644000175100001440000000565106443103542013716 0ustar mdusers/* $Revision: 1.14 $ ** ** Here be some useful macros. */ /* ** Memory allocation. Wrappers around wrapper functions. ** Don't replace any existing definitions, for use with malloc-debug ** packages, e.g. */ #if defined(_DEBUG_MALLOC_INC) #undef _DEBUG_MALLOC_INC #include "malloc.h" #else #define malloc_enter(func) #define malloc_leave(func) #define malloc_chain_check() #define malloc_dump(fd) #define malloc_list(a,b,c) #define malloc_size(hist) (*(hist) = 0, 0) #endif /* defined(_DEBUG_MALLOC_INC) */ #if !defined(NEW) #define NEW(T, c) \ ((T *)xmalloc((unsigned int)(sizeof (T) * (c)))) #define RENEW(p, T, c) \ (p = (T *)xrealloc((char *)(p), (unsigned int)(sizeof (T) * (c)))) /* =()<#define DISPOSE(p) free((@@ *)p)>()= */ #define DISPOSE(p) free((void *)p) /* This properly belongs in libinn.h. */ extern int (*xmemfailure)(); #define ONALLOCFAIL(func) (xmemfailure = (func)) #endif /* !defined(NEW) */ /* ** Copy a string to allocated memory. */ #define COPY(p) \ strcpy(NEW(char, strlen(p) + 1), p) /* ** Wrappers around str[n]cmp. Don't add the ((a) == (b)) test here; it's ** already been done in places where it's time-critical. */ #define EQ(a, b) (strcmp((a), (b)) == 0) #define EQn(a, b, n) (strncmp((a), (b), (SIZE_T)(n)) == 0) #define caseEQ(a, b) (strcasecmp((a), (b)) == 0) #define caseEQn(a, b, n) (strncasecmp((a), (b), (SIZE_T)(n)) == 0) /* ** Cast a pointer into another point, but keep lint quiet. */ #if !defined(lint) #define CAST(t, p) ((t)(p)) #else #define CAST(t, p) ((p) ? (t)NULL : (t)NULL) #endif /* !defined(lint) */ /* ** usually includes \n, which is not what we want. */ #define ISWHITE(c) ((c) == ' ' || (c) == '\t') /* ** Get the number of elements in a fixed-size array, or a pointer just ** past the end of it. */ #define SIZEOF(array) ((int)(sizeof array / sizeof array[0])) #define ENDOF(array) (&array[SIZEOF(array)]) /* ** Get the length of a string constant. */ #define STRLEN(string) ((int)(sizeof string - 1)) /* ** Turn a TIMEINFO into a floating point number. */ #define TIMEINFOasDOUBLE(t) \ ((double)(t).time + ((double)(t).usec) / 1000000.0) /* ** Test data from a stat(2) call to see if it's a file or directory. */ #if !defined(S_ISDIR) #define S_ISDIR(st_mode) (((st_mode) & S_IFMT) == S_IFDIR) #endif /* !defined(S_ISDIR) */ #if !defined(S_ISREG) #define S_ISREG(st_mode) (((st_mode) & S_IFMT) == S_IFREG) #endif /* !defined(S_ISREG) */ /* ** Get the size when binding an AF_UNIX socket. */ #if defined(DO_BIND_USE_SIZEOF) #define AF_UNIX_SOCKSIZE(S) (sizeof S) #else #define AF_UNIX_SOCKSIZE(S) (sizeof S.sun_family + strlen(S.sun_path) + 1) #endif /* defined(DO_BIND_USE_SIZEOF) */ /* ** Use a read or recv call to read a descriptor. */ #if defined(DO_HAVE_UNIX_DOMAIN) #define RECVorREAD(fd, p, s) recv((fd), (p), (s), 0) #else #define RECVorREAD(fd, p, s) read((fd), (p), (s)) #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ inn-1.7.2/include/libinn.h0100644000175100001440000000276306443103542013706 0ustar mdusers/* $Revision: 1.15 $ ** ** Here be declarations of functions in the InterNetNews library. */ /* Memory allocation. */ /* Worst-case alignment, in order to shut lint up. */ /* =()@ *ALIGNPTR;>()= */ typedef int *ALIGNPTR; extern ALIGNPTR xmalloc(); extern ALIGNPTR xrealloc(); /* Headers. */ extern char *GenerateMessageID(); extern char *HeaderFind(); extern void HeaderCleanFrom(); extern struct _DDHANDLE *DDstart(); extern void DDcheck(); extern char *DDend(); /* NNTP functions. */ extern int NNTPlocalopen(); extern int NNTPremoteopen(); extern int NNTPconnect(); extern int NNTPsendarticle(); extern int NNTPsendpassword(); /* Opening the active file on a client. */ extern FILE *CAopen(); extern FILE *CAlistopen(); extern void CAclose(); /* Parameter retrieval. */ extern char *GetFQDN(); extern char *GetConfigValue(); extern char *GetFileConfigValue(); extern char *GetModeratorAddress(); /* Time functions. */ typedef struct _TIMEINFO { time_t time; long usec; long tzone; } TIMEINFO; extern time_t parsedate(); extern int GetTimeInfo(); /* Miscellaneous. */ extern int getfdcount(); extern int wildmat(); extern PID_T waitnb(); extern int xread(); extern int xwrite(); extern int xwritev(); extern int LockFile(); extern int GetResourceUsage(); extern int SetNonBlocking(); extern void CloseOnExec(); extern void Radix32(); extern char *INNVersion(); extern char *ReadInDescriptor(); extern char *ReadInFile(); extern void TempName(); extern FILE *xfopena(); inn-1.7.2/include/inndcomm.h0100644000175100001440000000315406443103542014232 0ustar mdusers/* $Revision: 1.21 $ ** ** Here be values used for communicating with the server once it is ** running. */ /* The header for the ICC protocol is a one-byte protocol version followed by a 4 byte messages length*/ #define HEADER_SIZE (sizeof (ICC_PROTOCOLTYPE) + sizeof (ICC_MSGLENTYPE)) typedef short ICC_MSGLENTYPE; /* Length code to prefix commands to ** the server. */ typedef char ICC_PROTOCOLTYPE ; /* Values for the protocol version field of the message. 8 bits wide. */ #define ICC_PROTOCOL_1 'a' #define SC_SEP '\001' #define SC_MAXFIELDS 6 #define SC_ADDHIST 'a' #define SC_ALLOW 'D' #define SC_BEGIN 'b' #define SC_CANCEL 'c' #define SC_CHANGEGROUP 'u' #define SC_CHECKFILE 'd' #define SC_DROP 'e' #define SC_FEEDINFO 'F' #define SC_FILTER 'T' #define SC_FLUSH 'f' #define SC_FLUSHLOGS 'g' #define SC_GO 'h' #define SC_HANGUP 'i' #define SC_LOGMODE 'E' #define SC_MODE 's' #define SC_NAME 'j' #define SC_NEWGROUP 'k' #define SC_PARAM 'l' #define SC_PAUSE 'm' #define SC_PERL 'P' #define SC_READERS 'v' #define SC_REFILE 't' #define SC_REJECT 'C' #define SC_RELOAD 'o' #define SC_RENUMBER 'n' #define SC_RESERVE 'z' #define SC_RMGROUP 'p' #define SC_SEND 'A' #define SC_SHUTDOWN 'q' #define SC_SIGNAL 'B' #define SC_THROTTLE 'r' #define SC_TRACE 'w' #define SC_XABORT 'x' #define SC_XEXEC 'y' /* Yes, we don't want anyone to use this. */ #define SC_FIRSTFREE G #define MAX_REASON_LEN 80 extern void ICCsettimeout(); extern int ICCopen(); extern int ICCclose(); extern int ICCcommand(); extern int ICCcancel(); extern int ICCgo(); extern int ICCpause(); extern int ICCreserve(); extern char *ICCfailure; inn-1.7.2/include/myserver.h0100644000175100001440000000146706443103542014307 0ustar mdusers/* $Revision: 1.4 $ ** ** Replacement "server.h" file for remote rn. */ #if !defined(NNTP_CLASS_OK) /* ** These are defined in INN . Rather then require this file ** to include that file, we duplicate the relevent lines here. */ #define NNTP_NOSUCHGROUP_VAL 411 #define NNTP_CLASS_OK '2' #define NNTP_CLASS_ERROR '4' #define NNTP_CLASS_FATAL '5' #define NNTP_SYNTAX_VAL 501 #define NNTP_STRLEN 512 #endif /* !defined(NNTP_CLASS_OK) */ #define CHAR_OK NNTP_CLASS_OK #define CHAR_ERR NNTP_CLASS_ERROR #define CHAR_FATAL NNTP_CLASS_FATAL #define ERR_NOGROUP NNTP_NOSUCHGROUP_VAL #define ERR_CMDSYN NNTP_SYNTAX_VAL extern char *getserverbyfile(); extern int get_server(); extern int server_init(); extern void close_server(); extern void put_server(); extern char ser_line[NNTP_STRLEN + 2]; inn-1.7.2/include/uio.h0100644000175100001440000000021306443103542013213 0ustar mdusers/* $Revision: 1.2 $ ** ** Minimal file for systems without one. */ struct iovec { char *iov_base; int iov_len; }; inn-1.7.2/include/paths.h0100644000175100001440000002073406443103542013550 0ustar mdusers/* $Revision: 1.33 $ ** ** Here be #define's for filenames, socket names, environment variables, ** and so on. The numbers refer to sections in the config.dist file. */ /* ** 7. PATHS TO COMMON PROGRAMS */ /* =()<#define _PATH_INND "@<_PATH_INND>@">()= */ #define _PATH_INND "/usr/news/bin/innd" /* =()<#define _PATH_INNDSTART "@<_PATH_INNDSTART>@">()= */ #define _PATH_INNDSTART "/usr/news/bin/inndstart" /* =()<#define _PATH_SENDMAIL "@<_PATH_SENDMAIL>@">()= */ #define _PATH_SENDMAIL "/usr/sbin/sendmail -t" /* =()<#define _PATH_SH "@<_PATH_SH>@">()= */ #define _PATH_SH "/bin/sh" /* =()<#define _PATH_NNRPD "@<_PATH_NNRPD>@">()= */ #define _PATH_NNRPD "/usr/news/bin/nnrpd" /* =()<#define _PATH_NNTPD "@<_PATH_NNTPD>@">()= */ #define _PATH_NNTPD "/usr/news/bin/nnrpd" /* =()<#define _PATH_NNQRD "@<_PATH_NNQRD>@">()= */ #define _PATH_NNQRD "/usr/news/bin/nnrpd" /* =()<#define _PATH_COMPRESS "@<_PATH_COMPRESS>@">()= */ #define _PATH_COMPRESS "/usr/bin/compress" /* =()<#define _PATH_RNEWS "@<_PATH_RNEWS>@">()= */ #define _PATH_RNEWS "/usr/news/bin/rnews" /* =()<#define _PATH_AUTHDIR "@<_PATH_AUTHDIR>@">()= */ #define _PATH_AUTHDIR "/usr/news/bin/auth" /* =()<#define _PATH_NEWSBIN "@<_PATH_NEWSBIN>@">()= */ #define _PATH_NEWSBIN "/usr/news/bin" /* =()<#define _PATH_TMP "@<_PATH_TMP>@">()= */ #define _PATH_TMP "/var/tmp" /* =()<#define _PATH_GZIP "@<_PATH_GZIP>@">()= */ #define _PATH_GZIP "/usr/contrib/bin/gzip" /* ** 8. PATHS RELATED TO THE SPOOL DIRECTORY */ /* =()<#define _PATH_SPOOL "@<_PATH_SPOOL>@">()= */ #define _PATH_SPOOL "/var/news/spool/articles" /* =()<#define _PATH_OVERVIEWDIR "@<_PATH_OVERVIEWDIR>@">()= */ #define _PATH_OVERVIEWDIR "/var/news/spool/over.view" /* =()<#define _PATH_OVERVIEW "@<_PATH_OVERVIEW>@">()= */ #define _PATH_OVERVIEW ".overview" /* =()<#define _PATH_SPOOLNEWS "@<_PATH_SPOOLNEWS>@">()= */ #define _PATH_SPOOLNEWS "/var/news/spool/in.coming" /* =()<#define _PATH_SPOOLTEMP "@<_PATH_SPOOLTEMP>@">()= */ #define _PATH_SPOOLTEMP "/var/tmp" /* =()<#define _PATH_BADNEWS "@<_PATH_BADNEWS>@">()= */ #define _PATH_BADNEWS "/var/news/spool/in.coming/bad" /* =()<#define _PATH_RELBAD "@<_PATH_RELBAD>@">()= */ #define _PATH_RELBAD "bad" /* ** 9. EXECUTION PATHS FOR INND AND RNEWS */ /* =()<#define _PATH_RNEWS_DUP_LOG "@<_PATH_RNEWS_DUP_LOG>@">()= */ #define _PATH_RNEWS_DUP_LOG "/dev/null" /* =()<#define _PATH_RNEWSPROGS "@<_PATH_RNEWSPROGS>@">()= */ #define _PATH_RNEWSPROGS "/usr/news/bin/rnews.libexec" /* =()<#define _PATH_CONTROLPROGS "@<_PATH_CONTROLPROGS>@">()= */ #define _PATH_CONTROLPROGS "/usr/news/bin/control" /* =()<#define _PATH_BADCONTROLPROG "@<_PATH_BADCONTROLPROG>@">()= */ #define _PATH_BADCONTROLPROG "default" /* ** 10. SOCKETS CREATED BY INND OR CLIENTS */ /* =()<#define _PATH_INNDDIR "@<_PATH_INNDDIR>@">()= */ #define _PATH_INNDDIR "/var/news/run" /* =()<#define _PATH_NNTPCONNECT "@<_PATH_NNTPCONNECT>@">()= */ #define _PATH_NNTPCONNECT "/var/news/run/nntpin" /* =()<#define _PATH_NEWSCONTROL "@<_PATH_NEWSCONTROL>@">()= */ #define _PATH_NEWSCONTROL "/var/news/run/control" /* =()<#define _PATH_TEMPSOCK "@<_PATH_TEMPSOCK>@">()= */ #define _PATH_TEMPSOCK "/var/news/run/ctlinndXXXXXX" /* ** 11. LOG AND CONFIG FILES */ /* =()<#define _PATH_NEWSLIB "@<_PATH_NEWSLIB>@">()= */ #define _PATH_NEWSLIB "/var/news/etc" /* =()<#define _PATH_LOGFILE "@<_PATH_LOGFILE>@">()= */ #define _PATH_LOGFILE "/var/log/news/news" /* =()<#define _PATH_ERRLOG "@<_PATH_ERRLOG>@">()= */ #define _PATH_ERRLOG "/var/log/news/errlog" /* =()<#define _PATH_SERVERPID "@<_PATH_SERVERPID>@">()= */ #define _PATH_SERVERPID "/var/news/run/innd.pid" /* =()<#define _PATH_NEWSFEEDS "@<_PATH_NEWSFEEDS>@">()= */ #define _PATH_NEWSFEEDS "/var/news/etc/newsfeeds" /* =()<#define _PATH_HISTORY "@<_PATH_HISTORY>@">()= */ #define _PATH_HISTORY "/var/news/etc/history" /* =()<#define _PATH_INNDHOSTS "@<_PATH_INNDHOSTS>@">()= */ #define _PATH_INNDHOSTS "/var/news/etc/hosts.nntp" /* =()<#define _PATH_ACTIVE "@<_PATH_ACTIVE>@">()= */ #define _PATH_ACTIVE "/var/news/etc/active" /* =()<#define _PATH_NEWACTIVE "@<_PATH_NEWACTIVE>@">()= */ #define _PATH_NEWACTIVE "/var/news/etc/active.tmp" /* =()<#define _PATH_OLDACTIVE "@<_PATH_OLDACTIVE>@">()= */ #define _PATH_OLDACTIVE "/var/news/etc/active.old" /* =()<#define _PATH_ACTIVETIMES "@<_PATH_ACTIVETIMES>@">()= */ #define _PATH_ACTIVETIMES "/var/news/etc/active.times" /* =()<#define _PATH_BATCHDIR "@<_PATH_BATCHDIR>@">()= */ #define _PATH_BATCHDIR "/var/news/spool/out.going" /* =()<#define _PATH_ARCHIVEDIR "@<_PATH_ARCHIVEDIR>@">()= */ #define _PATH_ARCHIVEDIR "/var/news/spool/archive" /* =()<#define _PATH_DISTPATS "@<_PATH_DISTPATS>@">()= */ #define _PATH_DISTPATS "/var/news/etc/distrib.pats" /* =()<#define _PATH_NNRPDIST "@<_PATH_NNRPDIST>@">()= */ #define _PATH_NNRPDIST "/var/news/etc/distributions" /* =()<#define _PATH_NNRPSUBS "@<_PATH_NNRPSUBS>@">()= */ #define _PATH_NNRPSUBS "/var/news/etc/subscriptions" /* =()<#define _PATH_NEWSGROUPS "@<_PATH_NEWSGROUPS>@">()= */ #define _PATH_NEWSGROUPS "/var/news/etc/newsgroups" /* =()<#define _PATH_CONFIG "@<_PATH_CONFIG>@">()= */ #define _PATH_CONFIG "/var/news/etc/inn.conf" /* =()<#define _PATH_CLIENTACTIVE "@<_PATH_CLIENTACTIVE>@">()= */ #define _PATH_CLIENTACTIVE "/var/news/etc/active" /* =()<#define _PATH_TEMPACTIVE "@<_PATH_TEMPACTIVE>@">()= */ #define _PATH_TEMPACTIVE "/var/tmp/activeXXXXXX" /* =()<#define _PATH_TEMPMODERATORS "@<_PATH_TEMPMODERATORS>@">()= */ #define _PATH_TEMPMODERATORS "/var/tmp/moderatorsXXXXXX" /* =()<#define _PATH_MODERATORS "@<_PATH_MODERATORS>@">()= */ #define _PATH_MODERATORS "/var/news/etc/moderators" /* =()<#define _PATH_SERVER "@<_PATH_SERVER>@">()= */ #define _PATH_SERVER "/var/news/etc/server" /* =()<#define _PATH_NNTPPASS "@<_PATH_NNTPPASS>@">()= */ #define _PATH_NNTPPASS "/var/news/etc/passwd.nntp" /* =()<#define _PATH_NNRPACCESS "@<_PATH_NNRPACCESS>@">()= */ #define _PATH_NNRPACCESS "/var/news/etc/nnrp.access" /* =()<#define _PATH_EXPIRECTL "@<_PATH_EXPIRECTL>@">()= */ #define _PATH_EXPIRECTL "/var/news/etc/expire.ctl" /* =()<#define _PATH_SCHEMA "@<_PATH_SCHEMA>@">()= */ #define _PATH_SCHEMA "/var/news/etc/overview.fmt" /* =()<#define _PATH_XBATCHES "@<_PATH_XBATCHES>@">()= */ #define _PATH_XBATCHES "/var/news/spool/in.coming" /* ** ENVIRONMENT VARIABLES */ /* The host name of the NNTP server, for client posting. */ #define _ENV_NNTPSERVER "NNTPSERVER" /* The Organization header line, for client posting. */ #define _ENV_ORGANIZATION "ORGANIZATION" /* What to put in the From line, for client posting. */ #define _ENV_FROMHOST "FROMHOST" /* =()<#define _ENV_UUCPHOST "@<_ENV_UUCPHOST>@">()= */ #define _ENV_UUCPHOST "UU_MACHINE" /* ** PARAMETERS IN THE _PATH_CONFIG FILE. */ /* Host for the From line; default is FQDN. */ #define _CONF_FROMHOST "fromhost" /* NNTP server to post to, if getenv(_ENV_NNTPSERVER) is NULL. */ #define _CONF_SERVER "server" /* Host for the Path line; default is FQDN. */ #define _CONF_PATHHOST "pathhost" /* Data for the Organization line if getenv(_ENV_ORGANIZATION) is NULL. */ #define _CONF_ORGANIZATION "organization" /* Default host to mail moderated articles to. */ #define _CONF_MODMAILER "moderatormailer" /* Default domain of local host. */ #define _CONF_DOMAIN "domain" /* Default mime version. */ #define _CONF_MIMEVERSION "mime-version" /* Default Content-Type */ #define _CONF_CONTENTTYPE "mime-contenttype" /* Default encoding */ #define _CONF_ENCODING "mime-encoding" /* ** 13. TCL Support */ /* =()<#define _PATH_TCL_STARTUP "@<_PATH_TCL_STARTUP>@">()= */ #define _PATH_TCL_STARTUP "/usr/news/bin/control/startup.tcl" /* =()<#define _PATH_TCL_FILTER "@<_PATH_TCL_FILTER>@">()= */ #define _PATH_TCL_FILTER "/usr/news/bin/control/filter.tcl" /* ** 15. Local Configuration */ /* =()<#define _PATH_NEWSHOME "@<_PATH_NEWSHOME>@">()= */ #define _PATH_NEWSHOME "/usr/news" /* ** 17. PERL Support */ /* =()<#define _PATH_PERL_STARTUP_INND "@<_PATH_PERL_STARTUP_INND>@">()= */ #define _PATH_PERL_STARTUP_INND "/usr/news/bin/control/startup_innd.pl" /* =()<#define _PATH_PERL_FILTER_INND "@<_PATH_PERL_FILTER_INND>@">()= */ #define _PATH_PERL_FILTER_INND "/usr/news/bin/control/filter_innd.pl" /* =()<#define _PATH_PERL_FILTER_NNRPD "@<_PATH_PERL_FILTER_NNRPD>@">()= */ #define _PATH_PERL_FILTER_NNRPD "/usr/news/bin/control/filter_nnrpd.pl" inn-1.7.2/include/mydir.h0100644000175100001440000000044306443103542013550 0ustar mdusers/* $Revision: 1.1 $ ** ** Encapsulate dirent/direct differences. */ #if defined(DIR_DIRENT) #include typedef struct dirent DIRENTRY; #endif /* defined(DIR_DIRENT) */ #if defined(DIR_DIRECT) #include typedef struct direct DIRENTRY; #endif /* defined(DIR_DIRECT) */ inn-1.7.2/makedirs.sh0100755000175100001440000000557006443103542012774 0ustar mdusers#! /bin/sh ## $Revision: 1.14 $ ## Script to make INN directories. ## Some systems don't support -x, so we have to use -f. CHOWN=chown if [ ${CHOWN} = chown ] ; then if [ -f /sbin/chown ] ; then CHOWN=/sbin/chown else if [ -f /etc/chown ] ; then CHOWN=/etc/chown else if [ -f /usr/etc/chown ] ; then CHOWN=/usr/etc/chown fi fi fi fi ## =()@>()= MAN1=/usr/news/man/man1 ## =()@>()= MAN3=/usr/news/man/man3 ## =()@>()= MAN5=/usr/news/man/man5 ## =()@>()= MAN8=/usr/news/man/man8 MAN=`echo $MAN8 | sed -e 's@\(.*\)/[^/]*@\1@'` ## =()@>()= SPOOL=/var/news/spool/articles ## =()@>()= OVERVIEWDIR=/var/news/spool/over.view ## =()@>()= ARCHIVEDIR=/var/news/spool/archive ## =()@>()= BATCHDIR=/var/news/spool/out.going ## =()@>()= MOST_LOGS=/var/log/news ## =()@>()= PATH_AUTHDIR=/usr/news/bin/auth ## =()@>()= SPOOLNEWS=/var/news/spool/in.coming ## =()@>()= BADNEWS=/var/news/spool/in.coming/bad ## =()@>()= SPOOLTEMP=/var/tmp ## =()@>()= NEWSLIB=/var/news/etc ## =()@>()= NEWSBIN=/usr/news/bin ## =()@>()= CONTROLPROGS=/usr/news/bin/control ## =()@>()= RNEWSPROGS=/usr/news/bin/rnews.libexec ## =()@>()= INNDDIR=/var/news/run ## =()@>()= LOCKSDIR=/var/news/locks ## =()@>()= MOST_LOGS=/var/log/news ## =()@>()= LOCKS=/var/news/locks ## =()@>()= NEWSETC=/usr/news/bin/rc.news NEWSETC="`dirname ${NEWSETC}`" ## =()@>()= NEWSHIST=/var/news/etc/history NEWSHIST="`dirname ${NEWSHIST}`" ## =()@>()= NEWSTMP=/var/tmp ## =()@>()= NEWSHOME=/usr/news NEWSLBIN=${NEWSHOME}/local ## =()@>()= NEWSUSER=news ## =()@>()= NEWSGROUP=news PFLAG="$1" umask 0 set -x for F in \ ${MAN} ${MAN1} ${MAN3} ${MAN5} ${MAN8} \ ${NEWSHOME} ${NEWSETC} ${NEWSHIST} ${NEWSTMP} ${NEWSLBIN} \ ${SPOOL} ${OVERVIEWDIR} ${ARCHIVEDIR} ${BATCHDIR} ${LOCKS} \ ${MOST_LOGS} ${MOST_LOGS}/OLD \ ${SPOOLNEWS} ${BADNEWS} ${SPOOLTEMP} \ ${NEWSLIB} ${INNDDIR} ${LOCKSDIR} \ ${NEWSBIN} ${CONTROLPROGS} ${RNEWSPROGS} \ ${PATH_AUTHDIR} ; do if [ ! -d ${F} ] ; then mkdir ${PFLAG} ${DESTDIR}${F} || exit 1 ${CHOWN} ${NEWSUSER} ${DESTDIR}${F} || exit 1 chgrp ${NEWSGROUP} ${DESTDIR}${F} || exit 1 case ${F} in ${INNDDIR}) chmod 0770 ${DESTDIR}${F} || exit 1 ;; *) chmod 0775 ${DESTDIR}${F} || exit 1 ;; esac fi done exit 0 inn-1.7.2/HISTORY0100644000175100001440000002757506443103542011733 0ustar mdusers$Revision: 1.6 $ This file contains a few messages of historical interest. Some of the information in these messages is out of date (e.g., you don't need any other software, ihave/sendme is suported, etc); see the README and installation manual. The first is a mail message I sent as soon as I got the idea. Six months later I had something to beta, and I posted the second message to Usenet. My ship date was optimistic. The third message is the application that I required all beta sites to fill out. The fourth is a copy of the release notice. From: Rich Salz Date: Sat, 8 Dec 90 15:23:20 EST Message-Id: <9012082023.AA13441@litchi.bbn.com> To: newsgurus@ucsd.edu, nntp-managers@ucbarpa.Berkeley.EDU Subject: Speed idea. Suppose inews, nntp, "rnews -U", newsunbatch, etc., all just fed their articles to a single daemon? An idea I started kicking around yesterday. This is intended only for sites supporting BSD networking. I believe that anyone else who needs this kind of speed would find Cnews good enough. A multi-threaded server that used non-blocking IO to read all incoming articles on several sockets (don't forker a server, select on the connection socket will return READOK when a connection request comes in). All articles are read into memory, then written out to the filesystem using a single writev call (easy way to splice the path). Hash the active file and compile the sys file so as soon as an article was accepted we can write out the batchfile entries. As one special case, write entries to another socket for articles that should be fed out via NNTPLINK or something. Put the socket inside a group-access-only directory, so that only trusted front-ends like inews "rnews -U" etc can connect to it. Oh yeah, for things like nntp use sendmsg/recvmesg to hand off the feeding site to the demon once it's authenticated the incoming call and recognized it as an "xfer no" site. I've a few pages of notes and code fragments to type in. No locks of any kind. active file is mmap'd or periodically flushed. Keep it all in core and blat it out with a single write. When you want to expire, or add a group, you send a special message on a control port, or perhaps a sighup/sigusr1 to force it to resynch. Any feedback? /r$ Path: papaya.bbn.com!rsalz From: rsalz@bbn.com (Rich Salz) Newsgroups: news.software.nntp,news.admin,comp.org.usenix Subject: Seeking beta-testers for a new NNTP transfer system Message-ID: <3632@litchi.bbn.com> Date: 18 Jun 91 15:47:21 GMT Followup-To: poster Organization: Bolt, Beranek and Newman, Inc. Lines: 72 Xref: papaya.bbn.com news.software.nntp:1550 news.admin:15565 comp.org.usenix:418 InterNetNews, or INN, is a news transport system. The core part of the package is a single long-running daemon that handles all incoming NNTP connections. It files the articles and arranges for them to be forwarded to downstream sites. Because it is long-running, it can be directed to spawn other long-running processes, telling them exactly when an article should be sent to a feed. This can replace the "watch the logfile" mode of nntplink, for example, with a much cleaner mechanism: read the batchfile on standard input. InterNetNews assumes that memory is cheap and fast while disks are slow. No temporary files are used while incoming articles are being received, and once processed the entire article is written out using a single writev(2) call (this includes updating the Path and Xref headers). The active file is kept in memory (a compile-time option can be set to use mmap(2)), and the newsfeeds file is parsed once to build a complete matrix of which sites receive which newsgroups. InterNetNews uses many features of standard BSD sockets including non-blocking I/O and Unix-domain stream and datagram sockets. It is highly doubtful that the official version will ever provide support for TLI, DECNET, or other facilities. INN is fast. Not many hard numbers are available (that is one requirement of being a beta-site), but some preliminary tests show it to be at least twice as fast as the current standard NNTP/C News combination. For example, Jim Thompson at Sun has had 20 nntpxmits feeding into a 4/490, and was getting over 14 articles per second, with the CPU 11% utilized. I was getting 10 articles/second feeding into a DECstations 3100, with the program (running profiled!) 50% idle and the load average under .7. (It is a scary thing to see several articles filed with the same timestamp.) The sys file format is somewhat different, and has been renamed. The arcane "foo.all" syntax is gone, replaced with a set of order-dependant shell patterns. For example, instead of "comp,comp.sys.sun,!comp.sys" you would write "comp.*,!comp.sys.*,comp.sys.sun"; to not get any groups related to binaries or pictures, you write "!*pictures*,!*binaries*". There are other incompatibilities as well. For example, ihave/sendme control messages are not supported. Also the philosophy is that that invalid articles are dropped, rather than filed into "junk." (A log message is written with the reason, and also sent back to the upstream feed as part of the NNTP reject reply.) The active file is taken to be the definitive list of groups that an article wants to recieve, and if none of an article's newsgroups are mentioned in the active file, then the article is invalid, logged, and dropped. The history and log files are intended to be compatible with those created by C News. I want to thank Henry and Geoff for their kind permission to use DBZ and SUBST. You will need to be running C News expire or a B2.11 expire that has been modified to use DBZ. The InterNetNews daemon does not implement all NNTP commands. If sites within your campus are going to post or read news via NNTP, you will need the standard NNTP distribution. The daemon will spawn the standard nntpd if any site not mentioned in its "hosts.nntp" file connects to the TCP port. InterNetNews includes a replacement for the "mini-inews" that comes with the standard NNTP distribution. This can be used on any machine that posts news and connects to an NNTP server somewhere; its use is not limited to INN. At some point I hope to have a replacement nntpd optimized for newsreaders, and an NNTP transmission program. These will remove the need for any external software beyond the C News expire program. If you would like to beta-test this version, please FTP the file pub/usenet/INN.BETA from cronus.bbn.com for directions. It will be a fairly tightly-screened beta: DO NOT ASK ME FOR COPIES! Once the system is stable, it will be freely redistributable. I hope to have the official release by August 7, so that schools can bring the system up before the semester starts. /rich $alz -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out. Thanks for your interest in InterNetNews. I want to run a fairly tightly-controlled beta test of the software before I make it generally available. This means that I'm going to screen the sites which will be able to participate in the test. Please don't be offended or upset by this whole procedure. I want to make the final package as stable as soon as possible so that the entire net can benefit (it will be freely redistributable). I've set up this mechanism because I think it's the best way for me to get the best test results as quickly as possible. I would therefore appreciate your answers to the following questions. If you think the answers to some of them will be obvious to me (e.g., "Describe your organization" --> "UUNET" :-) then feel free to leave it blank. If you have any other feedback or comments, please add them. Email your results to /r$ What software (transport, batching, readers, etc.) do you currently run? How much experience do you have with Usenet and NNTP? Describe your organization. How do you plan on testing InterNetNews? Be specific, describing the machine hardware, any test servers, etc. [The answers to this one won't be obvious to me -- you gotta write something.] What are the rough counts of the upstream and downstream feeds, and how do they break down by category (UUCP, NNTP, etc.)? What special news functions does your server perform (gatewaying, archiving, etc.)? Do you understand that by participating in the beta-test you agree not to redistribute the software outside of your administrative domain, and that you promise to upgrade to the official release in a timely manner? From: Rich Salz Message-Id: Newsgroups: news.software.b,news.protocols.nntp Subject: Announcing the release of InterNetNews I am pleased to announce the official release of InterNetNews. InterNetNews, or INN, is a news transport system. The core part of the package is a single long-running daemon that handles all incoming NNTP connections. It files the articles and arranges for them to be forwarded to downstream sites. Because it is long-running, it can be directed to spawn other long-running processes, telling them exactly when an article should be sent to a feed. INN is a complete Usenet system. It provides article expiration and archiving, NNTP transport, and UUCP support. Nntplink works fine. INN does not include a newsreader. It does provide a version of the NNTP reference implementation "clientlib" routines so that rrn and other newsreaders compile with little trouble. The next release of xrn will include INN support. The spool directory is unchanged while the history database is upwardly-compatible with that of C News and the log file is very similar. All system configuration files are different. INN assumes that memory is cheap and fast while disks are slow. No temporary files are used while incoming articles are being received, and once processed the entire article is written out using a single system call (this includes updating the Path and Xref headers). The active file is kept in memory, and the newsfeeds file is parsed at start-up to build a complete matrix of which sites receive which newsgroups. A paper describing the implementation was presented at the June 1992 Usenix conference. INN uses many features of standard BSD sockets including non-blocking I/O. It is highly doubtful that the official version will ever provide support for TLI, DECNET, or other facilities. Among others, INN beta sites include ATT Unix System V Release 4, Apple A/UX, BSDI BSD/386 0.3.3, DEC Ultrix 3.x and 4.x, HP-UX s800 8.0, IBM AIX 3.1 and 3.2, Next NeXT-OS 2.1, Pyramid OSx 5.1, SCO Xenix 2.3.4, SGI Irix 4.0, Sequent Dynix 3.0.4 and 3.0.12, and Sun SunOS 3.5 and 4.x. Almost all of the beta-testers have reported faster performance and less load once they installed INN. Many people find it easy to maintain. A number of sites have graciously agreed to provide FTP access to this release. The machine names and directories are listed below. Within those directories you will find one or more of the following files: README Intro and unpacking instructions; -or- a copy appears at the end of this README.INN article. inn1.0.tar.Z The full distribution inn.usenix.ps.Z The Usenix paper on INN The sites providing access are: cs.utexas.edu /pub/inn ftp.cs.widener.edu /pub/inn.tar.Z (or wherever). ftp.germany.eu.net /pub/news/inn ftp.ira.uka.de pub/network/news ftp.msen.com /pub/packages/inn ftp.uu.net /pub/news/nntp/inn gatekeeper.dec.com /pub/news/inn grasp1.univ-lyon1.fr /pub/unix/news/inn munnari.oz.au /pub/news/inn sparky.Sterling.COM /news/inn src.doc.ic.ac.uk /computing/usenet/software/transport stasys.sta.sub.org /pub/src/inn (Stasys also has anonymous UUCP; contact . ucsd.edu /INN usc.edu /pub/inn Discussion about INN should be posted to news.software.b and news.software.nntp. Email should be sent to . Please do NOT send it to -- it will only just delay your response since I will have to forward it to UUNET. The README follows after the formfeed. /r$ inn-1.7.2/sedf.aix0100644000175100001440000000120506443103542012251 0ustar mdusers/## Filter noise out of AIX lint output./d /## $Revision: 1.5 $/d /dbzwritethrough multiply declared/d /warning: conversion to long may sign-extend incorrectly/d /warning: struct.union iovec never defined/d /"llib-lc", line [0-9]*: warning: function [a-z]* argument type inconsistent/d /warning: use of old-style function definition in presence of prototype/d /warning: mix of old and new style function declaration/d /warning: incomplete type for [a-zA-Z]* has already been completed/d /warning: possible pointer alignment problem, op CAST/d /[fs]printf argument count mismatch/d /printf argument count mismatch/d /dbz.3.* Unmatched \.SM/d p inn-1.7.2/PGPKEYS0100644000175100001440000000663306443103542011704 0ustar mdusers List of PGP Public Keys for Newsgroup Administration This is a list of keys known to be used for maintaining various parts of the newsgroup namespace. They are listed alphabetically by the hierarchies they are used for, along with the email address they are sent by (for use in control.ctl) and the group that people should follow if they are interested in tracking announcements about the hierarchy. The "Check also" references point to locations that should have identical public key blocks; it is best if you confirm the block listed here by checking against the others. The existence of key here only means that I, David Lawrence, trust the person who uses it to be a responsible maintainer of that particular hierarchy of groups. You are solely responsible for deciding whether you will use the keys here at your own site. _____________________________________________________________ COMP, HUMANITIES, MISC, NEWS, REC, SCI, SOC, TALK Control message sender: tale@uunet.uu.net Administrative group: news.announce.newgroups Check also: + ftp://ftp.uu.net/usenet/news.announce.newgroups/PGP.PUBLICKEY + pgp-public-keys-beta@pgp.ai.mit.edu ("Subject: GET 0xB88DA9C1", empty body) -----BEGIN PGP PUBLIC KEY BLOCK----- Version: 2.7 mQCNAjFsLmQAAAEEAKPbDQI6oDtYJYPvYxt7I4PMxThaq51Z/5kqfW7C3dMn6vPL d+UsXHfRzMaQXkLBR4nIaQj5OHVtbKCjVTVIMtgfgsPeh9GRSONW870S5HUTQcB7 eDhQqvvst1ZEowhTf/CX01chaxOfWq3ZPB09VVohQTmvRJn2BMJdOtO4janBAAUR tBduZXdzLmFubm91bmNlLm5ld2dyb3Vwc4kAlQIFEDF33BHCXTrTuI2pwQEBiJQD /1uiv20adyB2a3tzBYESEEhKtugAVHGRJQJE4Ar5PrcnovF3aNpLFumslIaAzCwP XlCANMjFHg140IB6SgJ8W8XH15u+1cMOmqTbk0wtmVgeLOLaSMgNWt65FV4AUn7e RZdhK8j/JKxE0a+6gKu4S0PiUDrvnCEWUPjlXiqsbnjR =E8K8 -----END PGP PUBLIC KEY BLOCK----- _____________________________________________________________ FR Control message sender: control@usenet.fr.net Administrative group: fr.announce.newgroups Check also: + pgp-public-keys-beta@pgp.ai.mit.edu ("Subject: GET 0x382B64FD", empty body) -----BEGIN PGP PUBLIC KEY BLOCK----- Version: 2.6.2i mQCNAzF41OMAAAEEAOnjgblNPQ+Xhnxw3K/EMz1vm2sfi2Ci/XG8HsWg2yc+hQla fMGQbQciSDFsBK0Kmy7gNvC9c7qAsQfeqpvQqJ+3hJiUvbQIi6bj2ZOSqE58Vh80 7Y+Fx71R/AKGZ88dGbysUg1r5770aw6JP1wn6Ve29PRTdS7yasmXGhU4K2T9AAUT tBVmci5hbm5vdW5jZS5uZXdncm91cHOJAJUDBRAxf8MhyZcaFTgrZP0BAZ0ZA/0S nxzmcN/yI858v+80ZpWaMkO/OtdF49gCfv/yv8xrRQfdGkjLFIl+Gry/H9236MZD rTSjb5R2PaicExO3b0tcRAAGOXyrRwc1squDdSvldko2ewQE9giZ4T1+fJRou1yO hbwPmaOBOt2EropUpvRPfKNeu/vjdKv1GEREkhIZTQ== =o/05 -----END PGP PUBLIC KEY BLOCK----- _____________________________________________________________ HUMANITIES See the comp hierarchy entry. _____________________________________________________________ MISC See the comp hierarchy entry. _____________________________________________________________ NEWS See the comp hierarchy entry. _____________________________________________________________ REC See the comp hierarchy entry. _____________________________________________________________ SCI See the comp hierarchy entry. _____________________________________________________________ SOC See the comp hierarchy entry. _____________________________________________________________ TALK See the comp hierarchy entry. inn-1.7.2/dbz/0040755000175100001440000000000006443103542011411 5ustar mdusersinn-1.7.2/dbz/dbz.h0100644000175100001440000000152406443103542012340 0ustar mdusers/* for dbm and dbz */ typedef struct { char *dptr; int dsize; } datum; /* standard dbm functions */ extern int dbminit(); extern datum fetch(); extern int store(); extern int delete(); /* not in dbz */ extern datum firstkey(); /* not in dbz */ extern datum nextkey(); /* not in dbz */ extern int dbmclose(); /* in dbz, but not in old dbm */ /* new stuff for dbz */ extern int dbzfresh(); extern int dbzagain(); extern datum dbzfetch(); extern int dbzstore(); extern int dbzsync(); extern long dbzsize(); extern int dbzincore(); extern int dbzcancel(); extern int dbzdebug(); extern int dbzwritethrough(); /* * In principle we could handle unlimited-length keys by operating a chunk * at a time, but it's not worth it in practice. Setting a nice large * bound on them simplifies the code and doesn't hurt anything. */ #define DBZMAXKEY 255 inn-1.7.2/dbz/dbz.3z0100644000175100001440000003026406443103542012450 0ustar mdusers.TH DBZ 3Z "3 Feb 1991" .BY "C News" .SH NAME dbminit, fetch, store, dbmclose \- somewhat dbm-compatible database routines .br dbzfresh, dbzagain, dbzfetch, dbzstore \- database routines .br dbzsync, dbzsize, dbzincore, dbzcancel, dbzdebug \- database routines .SH SYNOPSIS .nf .B #include .PP .B dbminit(base) .B char *base; .PP .B datum .B fetch(key) .B datum key; .PP .B store(key, value) .B datum key; .B datum value; .PP .B dbmclose() .PP .B dbzfresh(base, size, fieldsep, cmap, tagmask) .B char *base; .B long size; .B int fieldsep; .B int cmap; .B long tagmask; .PP .B dbzagain(base, oldbase) .B char *base; .B char *oldbase; .PP .B datum .B dbzfetch(key) .B datum key; .PP .B dbzstore(key, value) .B datum key; .B datum value; .PP .B dbzsync() .PP .B long .B dbzsize(nentries) .B long nentries; .PP .B dbzincore(newvalue) .PP .B dbzcancel() .PP .B dbzdebug(newvalue) .SH DESCRIPTION These functions provide an indexing system for rapid random access to a text file (the .I base .IR file ). Subject to certain constraints, they are call-compatible with .IR dbm (3), although they also provide some extensions. (Note that they are .I not file-compatible with .I dbm or any variant thereof.) .PP In principle, .I dbz stores key-value pairs, where both key and value are arbitrary sequences of bytes, specified to the functions by values of type .IR datum , typedefed in the header file to be a structure with members .I dptr (a value of type .I char * pointing to the bytes) and .I dsize (a value of type .I int indicating how long the byte sequence is). .PP In practice, .I dbz is more restricted than .IR dbm . A .I dbz database must be an index into a base file, with the database .IR value s being .IR fseek (3) offsets into the base file. Each such .I value must ``point to'' a place in the base file where the corresponding .I key sequence is found. A key can be no longer than .SM DBZMAXKEY (a constant defined in the header file) bytes. No key can be an initial subsequence of another, which in most applications requires that keys be either bracketed or terminated in some way (see the discussion of the .I fieldsep parameter of .IR dbzfresh , below, for a fine point on terminators). .PP .I Dbminit opens a database, an index into the base file .IR base , consisting of files .IB base .dir and .IB base .pag which must already exist. (If the database is new, they should be zero-length files.) Subsequent accesses go to that database until .I dbmclose is called to close the database. The base file need not exist at the time of the .IR dbminit , but it must exist before accesses are attempted. .PP .I Fetch searches the database for the specified .IR key , returning the corresponding .IR value if any. .I Store stores the .IR key - value pair in the database. .I Store will fail unless the database files are writeable. See below for a complication arising from case mapping. .PP .I Dbzfresh is a variant of .I dbminit for creating a new database with more control over details. Unlike for .IR dbminit , the database files need not exist: they will be created if necessary, and truncated in any case. .PP .IR Dbzfresh 's .I size parameter specifies the size of the first hash table within the database, in key-value pairs. Performance will be best if .I size is a prime number and the number of key-value pairs stored in the database does not exceed about 2/3 of .IR size . (The .I dbzsize function, given the expected number of key-value pairs, will suggest a database size that meets these criteria.) Assuming that an .I fseek offset is 4 bytes, the .B .pag file will be .RI 4* size bytes (the .B .dir file is tiny and roughly constant in size) until the number of key-value pairs exceeds about 80% of .IR size . (Nothing awful will happen if the database grows beyond 100% of .IR size , but accesses will slow down somewhat and the .B .pag file will grow somewhat.) .PP .IR Dbzfresh 's .I fieldsep parameter specifies the field separator in the base file. If this is not NUL (0), and the last character of a .I key argument is NUL, that NUL compares equal to either a NUL or a .I fieldsep in the base file. This permits use of NUL to terminate key strings without requiring that NULs appear in the base file. The .I fieldsep of a database created with .I dbminit is the horizontal-tab character. .PP For use in news systems, various forms of case mapping (e.g. uppercase to lowercase) in keys are available. The .I cmap parameter to .I dbzfresh is a single character specifying which of several mapping algorithms to use. Available algorithms are: .RS .TP .B 0 case-sensitive: no case mapping .TP .B B same as .B 0 .TP .B NUL same as .B 0 .TP .B = case-insensitive: uppercase and lowercase equivalent .TP .B b same as .B = .TP .B C RFC822 message-ID rules, case-sensitive before `@' (with certain exceptions) and case-insensitive after .TP .B ? whatever the local default is, normally .B C .RE .PP Mapping algorithm .B 0 (no mapping) is faster than the others and is overwhelmingly the correct choice for most applications. Unless compatibility constraints interfere, it is more efficient to pre-map the keys, storing mapped keys in the base file, than to have .I dbz do the mapping on every search. .PP For historical reasons, .I fetch and .I store expect their .I key arguments to be pre-mapped, but expect unmapped keys in the base file. .I Dbzfetch and .I dbzstore do the same jobs but handle all case mapping internally, so the customer need not worry about it. .PP .I Dbz stores only the database .IR value s in its files, relying on reference to the base file to confirm a hit on a key. References to the base file can be minimized, greatly speeding up searches, if a little bit of information about the keys can be stored in the .I dbz files. This is ``free'' if there are some unused bits in an .I fseek offset, so that the offset can be .I tagged with some information about the key. The .I tagmask parameter of .I dbzfresh allows specifying the location of unused bits. .I Tagmask should be a mask with one group of contiguous .B 1 bits. The bits in the mask should be unused (0) in .I most offsets. The bit immediately above the mask (the .I flag bit) should be unused (0) in .I all offsets; .I (dbz)store will reject attempts to store a key-value pair in which the .I value has the flag bit on. Apart from this restriction, tagging is invisible to the user. As a special case, a .I tagmask of 1 means ``no tagging'', for use with enormous base files or on systems with unusual offset representations. .PP A .I size of 0 given to .I dbzfresh is synonymous with the local default; the normal default is suitable for tables of 90-100,000 key-value pairs. A .I cmap of 0 (NUL) is synonymous with the character .BR 0 , signifying no case mapping (note that the character .B ? specifies the local default mapping, normally .BR C ). A .I tagmask of 0 is synonymous with the local default tag mask, normally 0x7f000000 (specifying the top bit in a 32-bit offset as the flag bit, and the next 7 bits as the mask, which is suitable for base files up to circa 24MB). Calling .I dbminit(name) with the database files empty is equivalent to calling .IR dbzfresh(name,0,'\et','?',0) . .PP When databases are regenerated periodically, as in news, it is simplest to pick the parameters for a new database based on the old one. This also permits some memory of past sizes of the old database, so that a new database size can be chosen to cover expected fluctuations. .I Dbzagain is a variant of .I dbminit for creating a new database as a new generation of an old database. The database files for .I oldbase must exist. .I Dbzagain is equivalent to calling .I dbzfresh with the same field separator, case mapping, and tag mask as the old database, and a .I size equal to the result of applying .I dbzsize to the largest number of entries in the .I oldbase database and its previous 10 generations. .PP When many accesses are being done by the same program, .I dbz is massively faster if its first hash table is in memory. If an internal flag is 1, an attempt is made to read the table in when the database is opened, and .I dbmclose writes it out to disk again (if it was read successfully and has been modified). .I Dbzincore sets the flag to .I newvalue (which should be 0 or 1) and returns the previous value; this does not affect the status of a database that has already been opened. The default is 0. The attempt to read the table in may fail due to memory shortage; in this case .I dbz quietly falls back on its default behavior. .IR Store s to an in-memory database are not (in general) written out to the file until .IR dbmclose or .IR dbzsync , so if robustness in the presence of crashes or concurrent accesses is crucial, in-memory databases should probably be avoided. .PP .I Dbzsync causes all buffers etc. to be flushed out to the files. It is typically used as a precaution against crashes or concurrent accesses when a .IR dbz -using process will be running for a long time. It is a somewhat expensive operation, especially for an in-memory database. .PP .I Dbzcancel cancels any pending writes from buffers. This is typically useful only for in-core databases, since writes are otherwise done immediately. Its main purpose is to let a child process, in the wake of a .IR fork , do a .I dbmclose without writing its parent's data to disk. .PP If .I dbz has been compiled with debugging facilities available (which makes it bigger and a bit slower), .I dbzdebug alters the value (and returns the previous value) of an internal flag which (when 1; default is 0) causes verbose and cryptic debugging output on standard output. .PP Concurrent reading of databases is fairly safe, but there is no (inter)locking, so concurrent updating is not. .PP The database files include a record of the byte order of the processor creating the database, and accesses by processors with different byte order will work, although they will be slightly slower. Byte order is preserved by .IR dbzagain . However, agreement on the size and internal structure of an .I fseek offset is necessary, as is consensus on the character set. .PP An open database occupies three .I stdio streams and their corresponding file descriptors; a fourth is needed for an in-memory database. Memory consumption is negligible (except for .I stdio buffers) except for in-memory databases. .SH SEE ALSO dbz(1), dbm(3) .SH DIAGNOSTICS Functions returning .I int values return 0 for success, \-1 for failure. Functions returning .I datum values return a value with .I dptr set to NULL for failure. .I Dbminit attempts to have .I errno set plausibly on return, but otherwise this is not guaranteed. An .I errno of .B EDOM from .I dbminit indicates that the database did not appear to be in .I dbz format. .SH HISTORY The original .I dbz was written by Jon Zeeff (zeeff@b-tech.ann-arbor.mi.us). Later contributions by David Butler and Mark Moraes. Extensive reworking, including this documentation, by Henry Spencer (henry@zoo.toronto.edu) as part of the C News project. Hashing function by Peter Honeyman. .SH BUGS The .I dptr members of returned .I datum values point to static storage which is overwritten by later calls. .PP Unlike .IR dbm , .I dbz will misbehave if an existing key-value pair is `overwritten' by a new .I (dbz)store with the same key. The user is responsible for avoiding this by using .I (dbz)fetch first to check for duplicates; an internal optimization remembers the result of the first search so there is minimal overhead in this. .PP Waiting until after .I dbminit to bring the base file into existence will fail if .IR chdir (2) has been used meanwhile. .PP The RFC822 case mapper implements only a first approximation to the hideously-complex RFC822 case rules. .PP The prime finder in .I dbzsize is not particularly quick. .PP Should implement the .I dbm functions .IR delete , .IR firstkey , and .IR nextkey . .PP On C implementations which trap integer overflow, .I dbz will refuse to .I (dbz)store an .I fseek offset equal to the greatest representable positive number, as this would cause overflow in the biased representation used. .PP .I Dbzagain perhaps ought to notice when many offsets in the old database were too big for tagging, and shrink the tag mask to match. .PP Marking .IR dbz 's file descriptors .RI close-on- exec would be a better approach to the problem .I dbzcancel tries to address, but that's harder to do portably. inn-1.7.2/dbz/dbz.c0100644000175100001440000013535706443103542012347 0ustar mdusers/* dbz.c V3.2 Copyright 1988 Jon Zeeff (zeeff@b-tech.ann-arbor.mi.us) You can use this code in any manner, as long as you leave my name on it and don't hold me responsible for any problems with it. Hacked on by gdb@ninja.UUCP (David Butler); Sun Jun 5 00:27:08 CDT 1988 Various improvments + INCORE by moraes@ai.toronto.edu (Mark Moraes) Major reworking by Henry Spencer as part of the C News project. Minor lint and CodeCenter (Saber) fluff removal by Rich $alz (March, 1991). Non-portable CloseOnExec() calls added by Rich $alz (September, 1991). Added "writethrough" and tagmask calculation code from and by Rich $alz (December, 1992). Merged in MMAP code by David Robinson, formerly now (January, 1993). These routines replace dbm as used by the usenet news software (it's not a full dbm replacement by any means). It's fast and simple. It contains no AT&T code. In general, dbz's files are 1/20 the size of dbm's. Lookup performance is somewhat better, while file creation is spectacularly faster, especially if the incore facility is used. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #ifndef __STDC__ extern int errno; #endif #include /* * #ifdef index. "LIA" = "leave it alone unless you know what you're doing". * * INDEX_SIZE backward compatibility with old dbz; avoid using this * NMEMORY number of days of memory for use in sizing new table (LIA) * INCORE backward compatibility with old dbz; use dbzincore() instead * DBZDEBUG enable debugging * DEFSIZE default table size (not as critical as in old dbz) * OLDBNEWS default case mapping as in old B News; set NOBUFFER * BNEWS default case mapping as in current B News; set NOBUFFER * DEFCASE default case-map algorithm selector * NOTAGS fseek offsets are strange, do not do tagging (see below) * NPAGBUF size of .pag buffer, in longs (LIA) * SHISTBUF size of ASCII-file buffer, in bytes (LIA) * MAXRUN length of run which shifts to next table (see below) (LIA) * OVERFLOW long-int arithmetic overflow must be avoided, will trap * NOBUFFER do not buffer hash-table i/o, B News locking is defective * MMAP Use SunOS style mmap() for efficient incore */ /* SUPPRESS 530 *//* Empty body for statement */ /* SUPPRESS 701 on free *//* Conflicting declaration */ #ifndef SEEK_SET #define SEEK_SET 0 #endif #define OVERFLOW #ifdef OVERFLOW #include #endif static int dbzversion = 3; /* for validating .dir file format */ /* * The dbz database exploits the fact that when news stores a * tuple, the `value' part is a seek offset into a text file, pointing to * a copy of the `key' part. This avoids the need to store a copy of * the key in the dbz files. However, the text file *must* exist and be * consistent with the dbz files, or things will fail. * * The basic format of the database is a simple hash table containing the * values. A value is stored by indexing into the table using a hash value * computed from the key; collisions are resolved by linear probing (just * search forward for an empty slot, wrapping around to the beginning of * the table if necessary). Linear probing is a performance disaster when * the table starts to get full, so a complication is introduced. The * database is actually one *or more* tables, stored sequentially in the * .pag file, and the length of linear-probe sequences is limited. The * search (for an existing item or an empty slot) always starts in the * first table, and whenever MAXRUN probes have been done in table N, * probing continues in table N+1. This behaves reasonably well even in * cases of massive overflow. There are some other small complications * added, see comments below. * * The table size is fixed for any particular database, but is determined * dynamically when a database is rebuilt. The strategy is to try to pick * the size so the first table will be no more than 2/3 full, that being * slightly before the point where performance starts to degrade. (It is * desirable to be a bit conservative because the overflow strategy tends * to produce files with holes in them, which is a nuisance.) */ /* * The following is for backward compatibility. */ #ifdef INDEX_SIZE #define DEFSIZE INDEX_SIZE #endif /* * ANSI C says an offset into a file is a long, not an off_t, for some * reason. This actually does simplify life a bit, but it's still nice * to have a distinctive name for it. Beware, this is just for readability, * don't try to change this. */ #define of_t long #define SOF (sizeof(of_t)) /* * We assume that unused areas of a binary file are zeros, and that the * bit pattern of `(of_t)0' is all zeros. The alternative is rather * painful file initialization. Note that okayvalue(), if OVERFLOW is * defined, knows what value of an offset would cause overflow. */ #define VACANT ((of_t)0) #define BIAS(o) ((o)+1) /* make any valid of_t non-VACANT */ #define UNBIAS(o) ((o)-1) /* reverse BIAS() effect */ /* * In a Unix implementation, or indeed any in which an of_t is a byte * count, there are a bunch of high bits free in an of_t. There is a * use for them. Checking a possible hit by looking it up in the base * file is relatively expensive, and the cost can be dramatically reduced * by using some of those high bits to tag the value with a few more bits * of the key's hash. This detects most false hits without the overhead of * seek+read+strcmp. We use the top bit to indicate whether the value is * tagged or not, and don't tag a value which is using the tag bits itself. * We're in trouble if the of_t representation wants to use the top bit. * The actual bitmasks and offset come from the configuration stuff, * which permits fiddling with them as necessary, and also suppressing * them completely (by defining the masks to 0). We build pre-shifted * versions of the masks for efficiency. */ static of_t tagbits; /* pre-shifted tag mask */ static of_t taghere; /* pre-shifted tag-enable bit */ static of_t tagboth; /* tagbits|taghere */ #define HASTAG(o) ((o)&taghere) #define TAG(o) ((o)&tagbits) #define NOTAG(o) ((o)&~tagboth) #define CANTAG(o) (((o)&tagboth) == 0) #define MKTAG(v) (((v)< #ifdef MAP_FILE #define MAP__ARG (MAP_FILE | MAP_SHARED) #else #define MAP__ARG (MAP_SHARED) #endif #ifndef INCORE #define INCORE #endif #endif /* * For a program that makes many, many references to the database, it * is a large performance win to keep the table in core, if it will fit. * Note that this does hurt robustness in the event of crashes, and * dbmclose() *must* be called to flush the in-core database to disk. * The code is prepared to deal with the possibility that there isn't * enough memory. There *is* an assumption that a size_t is big enough * to hold the size (in bytes) of one table, so dbminit() tries to figure * out whether this is possible first. * * The preferred way to ask for an in-core table is to do dbzincore(1) * before dbminit(). The default is not to do it, although -DINCORE * overrides this for backward compatibility with old dbz. * * We keep only the first table in core. This greatly simplifies the * code, and bounds memory demand. Furthermore, doing this is a large * performance win even in the event of massive overflow. */ #ifdef INCORE static int incore = 1; #else static int incore = 0; #endif /* * Write to filesystem even if incore? This replaces a single multi- * megabyte write when doing a dbzsync with a multi-byte write each * time an article is added. On most systems, this will give an overall * performance boost. */ static int writethrough = 0; /* * Stdio buffer for .pag reads. Buffering more than about 16 does not help * significantly at the densities we try to maintain, and the much larger * buffers that most stdios default to are much more expensive to fill. * With small buffers, stdio is performance-competitive with raw read(), * and it's much more portable. */ #ifndef NPAGBUF #define NPAGBUF 16 #endif #ifndef NOBUFFER #ifdef _IOFBF static of_t pagbuf[NPAGBUF]; /* only needed if !NOBUFFER && _IOFBF */ #endif #endif /* * Stdio buffer for base-file reads. Message-IDs (all news ever needs to * read) are essentially never longer than 64 bytes, and the typical stdio * buffer is so much larger that it is much more expensive to fill. */ #ifndef SHISTBUF #define SHISTBUF 64 #endif #ifdef _IOFBF static char basebuf[SHISTBUF]; /* only needed if _IOFBF exists */ #endif /* * Data structure for recording info about searches. */ struct searcher { of_t place; /* current location in file */ int tabno; /* which table we're in */ int run; /* how long we'll stay in this table */ # ifndef MAXRUN # define MAXRUN 100 # endif long hash; /* the key's hash code (for optimization) */ of_t tag; /* tag we are looking for */ int seen; /* have we examined current location? */ int aborted; /* has i/o error aborted search? */ }; static void start(); #define FRESH ((struct searcher *)NULL) static of_t search(); #define NOTFOUND ((of_t)-1) static int okayvalue(); static int set(); /* * Arguably the searcher struct for a given routine ought to be local to * it, but a fetch() is very often immediately followed by a store(), and * in some circumstances it is a useful performance win to remember where * the fetch() completed. So we use a global struct and remember whether * it is current. */ static struct searcher srch; static struct searcher *prevp; /* &srch or FRESH */ /* byte-ordering stuff */ static int mybmap[SOF]; /* my byte order (see mybytemap()) */ static int bytesame; /* is database order same as mine? */ #define MAPIN(o) ((bytesame) ? (o) : bytemap((o), conf.bytemap, mybmap)) #define MAPOUT(o) ((bytesame) ? (o) : bytemap((o), mybmap, conf.bytemap)) /* * The double parentheses needed to make this work are ugly, but the * alternative (under most compilers) is to pack around 2K of unused * strings -- there's just no way to get rid of them. */ #ifdef DBZDEBUG static int debug; /* controlled by dbzdebug() */ #define DEBUG(args) if (debug) { (void) printf args ; } else #else #define DEBUG(args) ; #endif /* externals used */ #if 0 extern char *memcpy(); extern char *memchr(); extern char *malloc(); extern char *calloc(); extern void free(); /* ANSI C; some old implementations say int */ #endif /* 0 */ extern int atoi(); extern long atol(); extern void CloseOnExec(); /* misc. forwards */ static long hash(); static void crcinit(); static char *cipoint(); static char *mapcase(); static int isprime(); static FILE *latebase(); /* file-naming stuff */ static char dir[] = ".dir"; static char pag[] = ".pag"; static char *enstring(); /* central data structures */ static FILE *basef; /* descriptor for base file */ static char *basefname; /* name for not-yet-opened base file */ static FILE *dirf; /* descriptor for .dir file */ static int dirronly; /* dirf open read-only? */ static FILE *pagf = NULL; /* descriptor for .pag file */ static of_t pagpos; /* posn in pagf; only search may set != -1 */ static int pagronly; /* pagf open read-only? */ static of_t *corepag; /* incore version of .pag file, if any */ static FILE *bufpagf; /* well-buffered pagf, for incore rewrite */ static of_t *getcore(); #ifndef MMAP static int putcore(); #endif static int written; /* has a store() been done? */ /* - dbzfresh - set up a new database, no historical info */ int /* 0 success, -1 failure */ dbzfresh(name, size, fs, cmap, tagmask) char *name; /* base name; .dir and .pag must exist */ long size; /* table size (0 means default) */ int fs; /* field-separator character in base file */ int cmap; /* case-map algorithm (0 means default) */ of_t tagmask; /* 0 default, 1 no tags */ { register char *fn; struct dbzconfig c; register of_t m; register FILE *f; if (pagf != NULL) { DEBUG(("dbzfresh: database already open\n")); return(-1); } if (size != 0 && size < 2) { DEBUG(("dbzfresh: preposterous size (%ld)\n", size)); return(-1); } /* get default configuration */ if (getconf((FILE *)NULL, (FILE *)NULL, &c) < 0) return(-1); /* "can't happen" */ /* and mess with it as specified */ if (size != 0) c.tsize = size; c.fieldsep = fs; switch (cmap) { case 0: case '0': case 'B': /* 2.10 compat */ c.casemap = '0'; /* '\0' nicer, but '0' printable! */ break; case '=': case 'b': /* 2.11 compat */ c.casemap = '='; break; case 'C': c.casemap = 'C'; break; case '?': c.casemap = DEFCASE; break; default: DEBUG(("dbzfresh case map `%c' unknown\n", cmap)); return(-1); } switch ((int)tagmask) { case 0: /* default */ break; case 1: /* no tags */ c.tagshift = 0; c.tagmask = 0; c.tagenb = 0; break; default: m = tagmask; c.tagshift = 0; while (!(m&01)) { m >>= 1; c.tagshift++; } c.tagmask = m; c.tagenb = (m << 1) & ~m; break; } /* write it out */ fn = enstring(name, dir); if (fn == NULL) return(-1); f = fopen(fn, "w"); free((POINTER)fn); if (f == NULL) { DEBUG(("dbzfresh: unable to write config\n")); return(-1); } if (putconf(f, &c) < 0) { (void) fclose(f); return(-1); } if (fclose(f) == EOF) { DEBUG(("dbzfresh: fclose failure\n")); return(-1); } /* create/truncate .pag */ fn = enstring(name, pag); if (fn == NULL) return(-1); f = fopen(fn, "w"); free((POINTER)fn); if (f == NULL) { DEBUG(("dbzfresh: unable to create/truncate .pag file\n")); return(-1); } else (void) fclose(f); /* and punt to dbminit for the hard work */ return(dbminit(name)); } /* - dbzsize - what's a good table size to hold this many entries? */ long dbzsize(contents) long contents; /* 0 means what's the default */ { register long n; if (contents <= 0) { /* foulup or default inquiry */ DEBUG(("dbzsize: preposterous input (%ld)\n", contents)); return(DEFSIZE); } n = (contents/2)*3; /* try to keep table at most 2/3 full */ if (!(n&01)) /* make it odd */ n++; DEBUG(("dbzsize: tentative size %ld\n", n)); while (!isprime(n)) /* and look for a prime */ n += 2; DEBUG(("dbzsize: final size %ld\n", n)); return(n); } /* - isprime - is a number prime? * * This is not a terribly efficient approach. */ static int /* predicate */ isprime(x) register long x; { static int quick[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 0 }; register int *ip; register long div; register long stop; /* hit the first few primes quickly to eliminate easy ones */ /* this incidentally prevents ridiculously small tables */ for (ip = quick; (div = *ip) != 0; ip++) if (x%div == 0) { DEBUG(("isprime: quick result on %ld\n", (long)x)); return(0); } /* approximate square root of x */ for (stop = x; x/stop < stop; stop >>= 1) continue; stop <<= 1; /* try odd numbers up to stop */ for (div = *--ip; div < stop; div += 2) if (x%div == 0) return(0); return(1); } /* - dbzagain - set up a new database to be a rebuild of an old one */ int /* 0 success, -1 failure */ dbzagain(name, oldname) char *name; /* base name; .dir and .pag must exist */ char *oldname; /* base name; all must exist */ { register char *fn; struct dbzconfig c; register int i; register long top; register FILE *f; register int newtable; register of_t newsize; struct stat sb; register of_t m; if (pagf != NULL) { DEBUG(("dbzagain: database already open\n")); return(-1); } /* pick up the old configuration */ fn = enstring(oldname, dir); if (fn == NULL) return(-1); f = fopen(fn, "r"); free((POINTER)fn); if (f == NULL) { DEBUG(("dbzagain: cannot open old .dir file\n")); return(-1); } i = getconf(f, (FILE *)NULL, &c); (void) fclose(f); if (i < 0) { DEBUG(("dbzagain: getconf failed\n")); return(-1); } /* calculate tagging from old file */ if (stat(oldname, &sb) != -1) { for (m = 1, i = 0; m < sb.st_size; i++, m <<= 1) continue; /* if we had more tags than the default, use the new data */ if ((c.tagmask | c.tagenb) && m > (1 << TAGSHIFT)) { c.tagshift = i; c.tagmask = (~(unsigned long)0) >> (i + 1); c.tagenb = (c.tagmask << 1) & ~c.tagmask; } } /* tinker with it */ top = 0; newtable = 0; for (i = 0; i < NUSEDS; i++) { if (top < c.used[i]) top = c.used[i]; if (c.used[i] == 0) newtable = 1; /* hasn't got full usage history yet */ } if (top == 0) { DEBUG(("dbzagain: old table has no contents!\n")); newtable = 1; } for (i = NUSEDS-1; i > 0; i--) c.used[i] = c.used[i-1]; c.used[0] = 0; newsize = dbzsize(top); if (!newtable || newsize > c.tsize) /* don't shrink new table */ c.tsize = newsize; /* write it out */ fn = enstring(name, dir); if (fn == NULL) return(-1); f = fopen(fn, "w"); free((POINTER)fn); if (f == NULL) { DEBUG(("dbzagain: unable to write new .dir\n")); return(-1); } i = putconf(f, &c); (void) fclose(f); if (i < 0) { DEBUG(("dbzagain: putconf failed\n")); return(-1); } /* create/truncate .pag */ fn = enstring(name, pag); if (fn == NULL) return(-1); f = fopen(fn, "w"); free((POINTER)fn); if (f == NULL) { DEBUG(("dbzagain: unable to create/truncate .pag file\n")); return(-1); } else (void) fclose(f); /* and let dbminit do the work */ return(dbminit(name)); } /* - dbminit - open a database, creating it (using defaults) if necessary * * We try to leave errno set plausibly, to the extent that underlying * functions permit this, since many people consult it if dbminit() fails. */ int /* 0 success, -1 failure */ dbminit(name) char *name; { register int i; register size_t s; register char *dirfname; register char *pagfname; if (pagf != NULL) { DEBUG(("dbminit: dbminit already called once\n")); errno = 0; return(-1); } /* open the .dir file */ dirfname = enstring(name, dir); if (dirfname == NULL) return(-1); dirf = fopen(dirfname, "r+"); if (dirf == NULL) { dirf = fopen(dirfname, "r"); dirronly = 1; } else dirronly = 0; free((POINTER)dirfname); if (dirf == NULL) { DEBUG(("dbminit: can't open .dir file\n")); return(-1); } CloseOnExec((int)fileno(dirf), 1); /* open the .pag file */ pagfname = enstring(name, pag); if (pagfname == NULL) { (void) fclose(dirf); return(-1); } pagf = fopen(pagfname, "r+b"); if (pagf == NULL) { pagf = fopen(pagfname, "rb"); if (pagf == NULL) { DEBUG(("dbminit: .pag open failed\n")); (void) fclose(dirf); free((POINTER)pagfname); return(-1); } pagronly = 1; } else if (dirronly) pagronly = 1; else pagronly = 0; if (pagf != NULL) CloseOnExec((int)fileno(pagf), 1); #ifdef NOBUFFER /* * B News does not do adequate locking on its database accesses. * Why it doesn't get into trouble using dbm is a mystery. In any * case, doing unbuffered i/o does not cure the problem, but does * enormously reduce its incidence. */ (void) setbuf(pagf, (char *)NULL); #else #ifdef _IOFBF (void) setvbuf(pagf, (char *)pagbuf, _IOFBF, sizeof(pagbuf)); #endif #endif pagpos = -1; /* don't free pagfname, need it below */ /* open the base file */ basef = fopen(name, "r"); if (basef == NULL) { DEBUG(("dbminit: basefile open failed\n")); basefname = enstring(name, ""); if (basefname == NULL) { (void) fclose(pagf); (void) fclose(dirf); free((POINTER)pagfname); pagf = NULL; return(-1); } } else basefname = NULL; if (basef != NULL) CloseOnExec((int)fileno(basef), 1); #ifdef _IOFBF if (basef != NULL) (void) setvbuf(basef, basebuf, _IOFBF, sizeof(basebuf)); #endif /* pick up configuration */ if (getconf(dirf, pagf, &conf) < 0) { DEBUG(("dbminit: getconf failure\n")); (void) fclose(basef); (void) fclose(pagf); (void) fclose(dirf); free((POINTER)pagfname); pagf = NULL; errno = EDOM; /* kind of a kludge, but very portable */ return(-1); } tagbits = conf.tagmask << conf.tagshift; taghere = conf.tagenb << conf.tagshift; tagboth = tagbits | taghere; mybytemap(mybmap); bytesame = 1; for (i = 0; i < SOF; i++) if (mybmap[i] != conf.bytemap[i]) bytesame = 0; /* get first table into core, if it looks desirable and feasible */ s = (size_t)conf.tsize * SOF; if (incore && (of_t)(s/SOF) == conf.tsize) { bufpagf = fopen(pagfname, (pagronly) ? "rb" : "r+b"); if (bufpagf != NULL) { corepag = getcore(bufpagf); CloseOnExec((int)fileno(bufpagf), 1); } } else { bufpagf = NULL; corepag = NULL; } free((POINTER)pagfname); /* misc. setup */ crcinit(); written = 0; prevp = FRESH; DEBUG(("dbminit: succeeded\n")); return(0); } /* - enstring - concatenate two strings into a malloced area */ static char * /* NULL if malloc fails */ enstring(s1, s2) char *s1; char *s2; { register char *p; p = malloc((size_t)strlen(s1) + (size_t)strlen(s2) + 1); if (p != NULL) { (void) strcpy(p, s1); (void) strcat(p, s2); } else { DEBUG(("enstring(%s, %s) out of memory\n", s1, s2)); } return(p); } /* - dbmclose - close a database */ int dbmclose() { register int ret = 0; if (pagf == NULL) { DEBUG(("dbmclose: not opened!\n")); return(-1); } if (fclose(pagf) == EOF) { DEBUG(("dbmclose: fclose(pagf) failed\n")); ret = -1; } pagf = basef; /* ensure valid pointer; dbzsync checks it */ if (dbzsync() < 0) ret = -1; if (bufpagf != NULL && fclose(bufpagf) == EOF) { DEBUG(("dbmclose: fclose(bufpagf) failed\n")); ret = -1; } if (corepag != NULL) #ifdef MMAP if (munmap((MMAP_PTR) corepag, (int)conf.tsize * SOF) == -1) { DEBUG(("dbmclose: munmap failed\n")); ret = -1; } #else free((POINTER)corepag); #endif corepag = NULL; if (fclose(basef) == EOF) { DEBUG(("dbmclose: fclose(basef) failed\n")); ret = -1; } if (basefname != NULL) free((POINTER)basefname); basef = NULL; pagf = NULL; if (fclose(dirf) == EOF) { DEBUG(("dbmclose: fclose(dirf) failed\n")); ret = -1; } DEBUG(("dbmclose: %s\n", (ret == 0) ? "succeeded" : "failed")); return(ret); } /* - dbzsync - push all in-core data out to disk */ int dbzsync() { register int ret = 0; if (pagf == NULL) { DEBUG(("dbzsync: not opened!\n")); return(-1); } if (!written) return(0); #ifndef MMAP if (corepag != NULL && !writethrough) { if (putcore(corepag, bufpagf) < 0) { DEBUG(("dbzsync: putcore failed\n")); ret = -1; } } #endif if (!conf.olddbz) if (putconf(dirf, &conf) < 0) ret = -1; DEBUG(("dbzsync: %s\n", (ret == 0) ? "succeeded" : "failed")); return(ret); } /* - dbzcancel - cancel writing of in-core data * Mostly for use from child processes. * Note that we don't need to futz around with stdio buffers, because we * always fflush them immediately anyway and so they never have stale data. */ int dbzcancel() { if (pagf == NULL) { DEBUG(("dbzcancel: not opened!\n")); return(-1); } written = 0; return(0); } /* - dbzfetch - fetch() with case mapping built in */ datum dbzfetch(key) datum key; { char buffer[DBZMAXKEY + 1]; datum mappedkey; register size_t keysize; DEBUG(("dbzfetch: (%s)\n", key.dptr)); /* Key is supposed to be less than DBZMAXKEY */ keysize = key.dsize; if (keysize >= DBZMAXKEY) { keysize = DBZMAXKEY; DEBUG(("keysize is %d - truncated to %d\n", key.dsize, DBZMAXKEY)); } mappedkey.dptr = mapcase(buffer, key.dptr, keysize); buffer[keysize] = '\0'; /* just a debug aid */ mappedkey.dsize = keysize; return(fetch(mappedkey)); } /* - fetch - get an entry from the database * * Disgusting fine point, in the name of backward compatibility: if the * last character of "key" is a NUL, that character is (effectively) not * part of the comparison against the stored keys. */ datum /* dptr NULL, dsize 0 means failure */ fetch(key) datum key; { char buffer[DBZMAXKEY + 1]; static of_t key_ptr; /* return value points here */ datum output; register size_t keysize; register size_t cmplen; register char *sepp; DEBUG(("fetch: (%s)\n", key.dptr)); output.dptr = NULL; output.dsize = 0; prevp = FRESH; /* Key is supposed to be less than DBZMAXKEY */ keysize = key.dsize; if (keysize >= DBZMAXKEY) { keysize = DBZMAXKEY; DEBUG(("keysize is %d - truncated to %d\n", key.dsize, DBZMAXKEY)); } if (pagf == NULL) { DEBUG(("fetch: database not open!\n")); return(output); } else if (basef == NULL) { /* basef didn't exist yet */ basef = latebase(); if (basef == NULL) return(output); } cmplen = keysize; sepp = &conf.fieldsep; if (key.dptr[keysize-1] == '\0') { cmplen--; sepp = &buffer[keysize-1]; } start(&srch, &key, FRESH); while ((key_ptr = search(&srch)) != NOTFOUND) { DEBUG(("got 0x%lx\n", key_ptr)); /* fetch the key */ if (fseek(basef, key_ptr, SEEK_SET) != 0) { DEBUG(("fetch: seek failed\n")); return(output); } if (fread((POINTER)buffer, 1, keysize, basef) != keysize) { DEBUG(("fetch: read failed\n")); return(output); } /* try it */ buffer[keysize] = '\0'; /* terminated for DEBUG */ (void) mapcase(buffer, buffer, keysize); DEBUG(("fetch: buffer (%s) looking for (%s) size = %d\n", buffer, key.dptr, keysize)); if (memcmp((POINTER)key.dptr, (POINTER)buffer, cmplen) == 0 && (*sepp == conf.fieldsep || *sepp == '\0')) { /* we found it */ output.dptr = (char *)&key_ptr; output.dsize = SOF; DEBUG(("fetch: successful\n")); return(output); } } /* we didn't find it */ DEBUG(("fetch: failed\n")); prevp = &srch; /* remember where we stopped */ return(output); } /* - latebase - try to open a base file that wasn't there at the start */ static FILE * latebase() { register FILE *it; if (basefname == NULL) { DEBUG(("latebase: name foulup\n")); return(NULL); } it = fopen(basefname, "r"); if (it == NULL) { DEBUG(("latebase: still can't open base\n")); } else { DEBUG(("latebase: late open succeeded\n")); free((POINTER)basefname); basefname = NULL; #ifdef _IOFBF (void) setvbuf(it, basebuf, _IOFBF, sizeof(basebuf)); #endif } if (it != NULL) CloseOnExec((int)fileno(it), 1); return(it); } /* - dbzstore - store() with case mapping built in */ int dbzstore(key, data) datum key; datum data; { char buffer[DBZMAXKEY + 1]; datum mappedkey; register size_t keysize; DEBUG(("dbzstore: (%s)\n", key.dptr)); /* Key is supposed to be less than DBZMAXKEY */ keysize = key.dsize; if (keysize >= DBZMAXKEY) { DEBUG(("dbzstore: key size too big (%d)\n", key.dsize)); return(-1); } mappedkey.dptr = mapcase(buffer, key.dptr, keysize); buffer[keysize] = '\0'; /* just a debug aid */ mappedkey.dsize = keysize; return(store(mappedkey, data)); } /* - store - add an entry to the database */ int /* 0 success, -1 failure */ store(key, data) datum key; datum data; { of_t value; if (pagf == NULL) { DEBUG(("store: database not open!\n")); return(-1); } else if (basef == NULL) { /* basef didn't exist yet */ basef = latebase(); if (basef == NULL) return(-1); } if (pagronly) { DEBUG(("store: database open read-only\n")); return(-1); } if (data.dsize != SOF) { DEBUG(("store: value size wrong (%d)\n", data.dsize)); return(-1); } if (key.dsize >= DBZMAXKEY) { DEBUG(("store: key size too big (%d)\n", key.dsize)); return(-1); } /* copy the value in to ensure alignment */ (void) memcpy((POINTER)&value, (POINTER)data.dptr, SOF); DEBUG(("store: (%s, %ld)\n", key.dptr, (long)value)); if (!okayvalue(value)) { DEBUG(("store: reserved bit or overflow in 0x%lx\n", value)); return(-1); } /* find the place, exploiting previous search if possible */ start(&srch, &key, prevp); while (search(&srch) != NOTFOUND) continue; prevp = FRESH; conf.used[0]++; DEBUG(("store: used count %ld\n", conf.used[0])); written = 1; return(set(&srch, value)); } /* - dbzincore - control attempts to keep .pag file in core */ int /* old setting */ dbzincore(value) int value; { register int old = incore; #ifndef MMAP incore = value; #endif return(old); } /* - dbzwritethrough - write through the pag file in core */ int /* old setting */ dbzwritethrough(value) int value; { register int old = writethrough; writethrough = value; return(old); } /* - dbztagmask - calculate the correct tagmask for the given base file size */ long dbztagmask(size) register long size; { register long m; register long tagmask; register int i; if (size <= 0) return(0L); /* silly size */ for (m = 1, i = 0; m < size; i++, m <<= 1) continue; if (m < (1 << TAGSHIFT)) return(0L); /* not worth tagging */ tagmask = (~(unsigned long)0) >> (i + 1); tagmask = tagmask << i; return(tagmask); } /* - getconf - get configuration from .dir file */ static int /* 0 success, -1 failure */ getconf(df, pf, cp) register FILE *df; /* NULL means just give me the default */ register FILE *pf; /* NULL means don't care about .pag */ register struct dbzconfig *cp; { register int c; register int i; int err = 0; c = (df != NULL) ? getc(df) : EOF; if (c == EOF) { /* empty file, no configuration known */ cp->olddbz = 0; if (df != NULL && pf != NULL && getc(pf) != EOF) cp->olddbz = 1; cp->tsize = DEFSIZE; cp->fieldsep = '\t'; for (i = 0; i < NUSEDS; i++) cp->used[i] = 0; cp->valuesize = SOF; mybytemap(cp->bytemap); cp->casemap = DEFCASE; cp->tagenb = TAGENB; cp->tagmask = TAGMASK; cp->tagshift = TAGSHIFT; DEBUG(("getconf: defaults (%ld, %c, (0x%lx/0x%lx<<%d))\n", cp->tsize, cp->casemap, cp->tagenb, cp->tagmask, cp->tagshift)); return(0); } (void) ungetc(c, df); /* first line, the vital stuff */ if (getc(df) != 'd' || getc(df) != 'b' || getc(df) != 'z') err = -1; if (getno(df, &err) != dbzversion) err = -1; cp->tsize = getno(df, &err); cp->fieldsep = (int)getno(df, &err); while ((c = getc(df)) == ' ') continue; cp->casemap = c; cp->tagenb = getno(df, &err); cp->tagmask = getno(df, &err); cp->tagshift = getno(df, &err); cp->valuesize = getno(df, &err); if (cp->valuesize != SOF) { DEBUG(("getconf: wrong of_t size (%d)\n", cp->valuesize)); err = -1; cp->valuesize = SOF; /* to protect the loops below */ } for (i = 0; i < cp->valuesize; i++) cp->bytemap[i] = getno(df, &err); if (getc(df) != '\n') err = -1; #ifdef DBZDEBUG DEBUG(("size %ld, sep %d, cmap %c, tags 0x%lx/0x%lx<<%d, ", cp->tsize, cp->fieldsep, cp->casemap, cp->tagenb, cp->tagmask, cp->tagshift)); DEBUG(("bytemap (%d)", cp->valuesize)); for (i = 0; i < cp->valuesize; i++) { DEBUG((" %d", cp->bytemap[i])); } DEBUG(("\n")); #endif /* second line, the usages */ for (i = 0; i < NUSEDS; i++) cp->used[i] = getno(df, &err); if (getc(df) != '\n') err = -1; DEBUG(("used %ld %ld %ld...\n", cp->used[0], cp->used[1], cp->used[2])); if (err < 0) { DEBUG(("getconf error\n")); return(-1); } return(0); } /* - getno - get a long */ static long getno(f, ep) FILE *f; int *ep; { register char *p; # define MAXN 50 char getbuf[MAXN]; register int c; while ((c = getc(f)) == ' ') continue; if (c == EOF || c == '\n') { DEBUG(("getno: missing number\n")); *ep = -1; return(0); } p = getbuf; *p++ = c; while ((c = getc(f)) != EOF && c != '\n' && c != ' ') if (p < &getbuf[MAXN-1]) *p++ = c; if (c == EOF) { DEBUG(("getno: EOF\n")); *ep = -1; } else (void) ungetc(c, f); *p = '\0'; if (strspn(getbuf, "-1234567890") != strlen(getbuf)) { DEBUG(("getno: `%s' non-numeric\n", getbuf)); *ep = -1; } return(atol(getbuf)); } /* - putconf - write configuration to .dir file */ static int /* 0 success, -1 failure */ putconf(f, cp) register FILE *f; register struct dbzconfig *cp; { register int i; register int ret = 0; if (fseek(f, (of_t)0, SEEK_SET) != 0) { DEBUG(("fseek failure in putconf\n")); ret = -1; } (void) fprintf(f, "dbz %d %ld %d %c %ld %ld %d %d", dbzversion, cp->tsize, cp->fieldsep, cp->casemap, cp->tagenb, cp->tagmask, cp->tagshift, cp->valuesize); for (i = 0; i < cp->valuesize; i++) (void) fprintf(f, " %d", cp->bytemap[i]); (void) fprintf(f, "\n"); for (i = 0; i < NUSEDS; i++) (void) fprintf(f, "%ld%c", cp->used[i], (i < NUSEDS-1) ? ' ' : '\n'); (void) fflush(f); if (ferror(f)) ret = -1; DEBUG(("putconf status %d\n", ret)); return(ret); } /* - getcore - try to set up an in-core copy of .pag file */ static of_t * /* pointer to copy, or NULL */ getcore(f) FILE *f; { register of_t *p; register size_t i; register size_t nread; register char *it; #ifdef MMAP struct stat st; if (fstat(fileno(f), &st) == -1) { DEBUG(("getcore: fstat failed\n")); return(NULL); } if (((size_t)conf.tsize * SOF) > st.st_size) { /* file too small; extend it */ if (ftruncate((int)fileno(f), conf.tsize * SOF) == -1) { DEBUG(("getcore: ftruncate failed\n")); return(NULL); } } it = mmap((caddr_t)0, (size_t)conf.tsize * SOF, pagronly ? PROT_READ : PROT_WRITE | PROT_READ, MAP__ARG, (int)fileno(f), (off_t)0); if (it == (char *)-1) { DEBUG(("getcore: mmap failed\n")); return(NULL); } #if defined (MADV_RANDOM) /* not present in all versions of mmap() */ madvise(it, (size_t)conf.tsize * SOF, MADV_RANDOM); #endif #else it = malloc((size_t)conf.tsize * SOF); if (it == NULL) { DEBUG(("getcore: malloc failed\n")); return(NULL); } nread = fread((POINTER)it, SOF, (size_t)conf.tsize, f); if (ferror(f)) { DEBUG(("getcore: read failed\n")); free((POINTER)it); return(NULL); } /* NOSTRICT *//* Possible pointer alignment problem */ p = (of_t *)it + nread; i = (size_t)conf.tsize - nread; while (i-- > 0) *p++ = VACANT; #endif /* NOSTRICT *//* Possible pointer alignment problem */ return((of_t *)it); } #ifndef MMAP /* - putcore - try to rewrite an in-core table */ static int /* 0 okay, -1 fail */ putcore(tab, f) of_t *tab; FILE *f; { if (fseek(f, (of_t)0, SEEK_SET) != 0) { DEBUG(("fseek failure in putcore\n")); return(-1); } (void) fwrite((POINTER)tab, SOF, (size_t)conf.tsize, f); (void) fflush(f); return((ferror(f)) ? -1 : 0); } #endif /* - start - set up to start or restart a search */ static void start(sp, kp, osp) register struct searcher *sp; register datum *kp; register struct searcher *osp; /* may be FRESH, i.e. NULL */ { register long h; h = hash(kp->dptr, kp->dsize); if (osp != FRESH && osp->hash == h) { if (sp != osp) *sp = *osp; DEBUG(("search restarted\n")); } else { sp->hash = h; sp->tag = MKTAG(h / conf.tsize); DEBUG(("tag 0x%lx\n", sp->tag)); sp->place = h % conf.tsize; sp->tabno = 0; sp->run = (conf.olddbz) ? conf.tsize : MAXRUN; sp->aborted = 0; } sp->seen = 0; } /* - search - conduct part of a search */ static of_t /* NOTFOUND if we hit VACANT or error */ search(sp) register struct searcher *sp; { register of_t dest; register of_t value; of_t val; /* buffer for value (can't fread register) */ register of_t place; if (sp->aborted) return(NOTFOUND); for (;;) { /* determine location to be examined */ place = sp->place; if (sp->seen) { /* go to next location */ if (--sp->run <= 0) { sp->tabno++; sp->run = MAXRUN; } place = (place+1)%conf.tsize + sp->tabno*conf.tsize; sp->place = place; } else sp->seen = 1; /* now looking at current location */ DEBUG(("search @ %ld\n", place)); /* get the tagged value */ if (corepag != NULL && place < conf.tsize) { DEBUG(("search: in core\n")); value = MAPIN(corepag[place]); } else { /* seek, if necessary */ dest = place * SOF; if (pagpos != dest) { if (fseek(pagf, dest, SEEK_SET) != 0) { DEBUG(("search: seek failed\n")); pagpos = -1; sp->aborted = 1; return(NOTFOUND); } pagpos = dest; } /* read it */ if (fread((POINTER)&val, sizeof(val), 1, pagf) == 1) value = MAPIN(val); else if (ferror(pagf)) { DEBUG(("search: read failed\n")); pagpos = -1; sp->aborted = 1; return(NOTFOUND); } else value = VACANT; /* and finish up */ pagpos += sizeof(val); } /* vacant slot is always cause to return */ if (value == VACANT) { DEBUG(("search: empty slot\n")); return(NOTFOUND); }; /* check the tag */ value = UNBIAS(value); DEBUG(("got 0x%lx\n", value)); if (!HASTAG(value)) { DEBUG(("tagless\n")); return(value); } else if (TAG(value) == sp->tag) { DEBUG(("match\n")); return(NOTAG(value)); } else { DEBUG(("mismatch 0x%lx\n", TAG(value))); } } /* NOTREACHED */ } /* - okayvalue - check that a value can be stored */ static int /* predicate */ okayvalue(value) of_t value; { if (HASTAG(value)) return(0); #ifdef OVERFLOW if (value == LONG_MAX) /* BIAS() and UNBIAS() will overflow */ return(0); #endif return(1); } /* - set - store a value into a location previously found by search */ static int /* 0 success, -1 failure */ set(sp, value) register struct searcher *sp; of_t value; { register of_t place = sp->place; register of_t v = value; if (sp->aborted) return(-1); if (CANTAG(v) && !conf.olddbz) { v |= sp->tag | taghere; if (v != UNBIAS(VACANT)) /* BIAS(v) won't look VACANT */ #ifdef OVERFLOW if (v != LONG_MAX) /* and it won't overflow */ #endif value = v; } DEBUG(("tagged value is 0x%lx\n", value)); value = BIAS(value); value = MAPOUT(value); /* If we have the index file in memory, use it */ if (corepag != NULL && place < conf.tsize) { corepag[place] = value; DEBUG(("set: incore\n")); #ifdef MMAP return(0); #else if (!writethrough) return(0); #endif } /* seek to spot */ pagpos = -1; /* invalidate position memory */ if (fseek(pagf, (of_t)(place * SOF), SEEK_SET) != 0) { DEBUG(("set: seek failed\n")); sp->aborted = 1; return(-1); } /* write in data */ if (fwrite((POINTER)&value, SOF, 1, pagf) != 1) { DEBUG(("set: write failed\n")); sp->aborted = 1; return(-1); } /* fflush improves robustness, and buffer re-use is rare anyway */ if (fflush(pagf) == EOF) { DEBUG(("set: fflush failed\n")); sp->aborted = 1; return(-1); } DEBUG(("set: succeeded\n")); return(0); } /* - mybytemap - determine this machine's byte map * * A byte map is an array of ints, sizeof(of_t) of them. The 0th int * is the byte number of the high-order byte in my of_t, and so forth. */ static void mybytemap(map) int map[]; /* -> int[SOF] */ { union { of_t o; char c[SOF]; } u; register int *mp = &map[SOF]; register int ntodo; register int i; u.o = 1; for (ntodo = (int)SOF; ntodo > 0; ntodo--) { for (i = 0; i < SOF; i++) /* SUPPRESS 112 *//* Retrieving char where long is stored */ if (u.c[i] != 0) break; if (i == SOF) { /* trouble -- set it to *something* consistent */ DEBUG(("mybytemap: nonexistent byte %d!!!\n", ntodo)); for (i = 0; i < SOF; i++) map[i] = i; return; } DEBUG(("mybytemap: byte %d\n", i)); *--mp = i; /* SUPPRESS 112 *//* Retrieving char where long is stored */ while (u.c[i] != 0) u.o <<= 1; } } /* - bytemap - transform an of_t from byte ordering map1 to map2 */ static of_t /* transformed result */ bytemap(ino, map1, map2) of_t ino; int *map1; int *map2; { union oc { of_t o; char c[SOF]; }; union oc in; union oc out; register int i; in.o = ino; for (i = 0; i < SOF; i++) out.c[map2[i]] = in.c[map1[i]]; return(out.o); } /* * This is a simplified version of the pathalias hashing function. * Thanks to Steve Belovin and Peter Honeyman * * hash a string into a long int. 31 bit crc (from andrew appel). * the crc table is computed at run time by crcinit() -- we could * precompute, but it takes 1 clock tick on a 750. * * This fast table calculation works only if POLY is a prime polynomial * in the field of integers modulo 2. Since the coefficients of a * 32-bit polynomial won't fit in a 32-bit word, the high-order bit is * implicit. IT MUST ALSO BE THE CASE that the coefficients of orders * 31 down to 25 are zero. Happily, we have candidates, from * E. J. Watson, "Primitive Polynomials (Mod 2)", Math. Comp. 16 (1962): * x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + x^0 * x^31 + x^3 + x^0 * * We reverse the bits to get: * 111101010000000000000000000000001 but drop the last 1 * f 5 0 0 0 0 0 0 * 010010000000000000000000000000001 ditto, for 31-bit crc * 4 8 0 0 0 0 0 0 */ #define POLY 0x48000000L /* 31-bit polynomial (avoids sign problems) */ static long CrcTable[128]; /* - crcinit - initialize tables for hash function */ static void crcinit() { register int i, j; register long sum; for (i = 0; i < 128; ++i) { sum = 0L; for (j = 7 - 1; j >= 0; --j) if (i & (1 << j)) sum ^= POLY >> j; CrcTable[i] = sum; } DEBUG(("crcinit: done\n")); } /* - hash - Honeyman's nice hashing function */ static long hash(name, size) register char *name; register int size; { register long sum = 0L; while (size--) { sum = (sum >> 7) ^ CrcTable[(sum ^ (*name++)) & 0x7f]; } DEBUG(("hash: returns (%ld)\n", sum)); return(sum); } /* * case-mapping stuff * * Borrowed from C News, by permission of the authors. Somewhat modified. * * We exploit the fact that we are dealing only with headers here, and * headers are limited to the ASCII characters by RFC822. It is barely * possible that we might be dealing with a translation into another * character set, but in particular it's very unlikely for a header * character to be outside -128..255. * * Life would be a whole lot simpler if tolower() could safely and portably * be applied to any char. */ #define OFFSET 128 /* avoid trouble with negative chars */ /* must call casencmp before invoking TOLOW... */ #define TOLOW(c) (cmap[(c)+OFFSET]) /* ...but the use of it in CISTREQN is safe without the preliminary call (!) */ /* CISTREQN is an optimised case-insensitive strncmp(a,b,n)==0; n > 0 */ #define CISTREQN(a, b, n) \ (TOLOW((a)[0]) == TOLOW((b)[0]) && casencmp(a, b, n) == 0) #define MAPSIZE (256+OFFSET) static char cmap[MAPSIZE]; /* relies on init to '\0' */ static int mprimed = 0; /* has cmap been set up? */ /* - mapprime - set up case-mapping stuff */ static void mapprime() { register char *lp; register char *up; register int c; register int i; static char lower[] = "abcdefghijklmnopqrstuvwxyz"; static char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; for (lp = lower, up = upper; *lp != '\0'; lp++, up++) { c = *lp; cmap[c+OFFSET] = c; cmap[*up+OFFSET] = c; } for (i = 0; i < MAPSIZE; i++) if (cmap[i] == '\0') cmap[i] = (char)(i-OFFSET); mprimed = 1; } /* - casencmp - case-independent strncmp */ static int /* < == > 0 */ casencmp(s1, s2, len) char *s1; char *s2; int len; { register char *p1; register char *p2; register int n; if (!mprimed) mapprime(); p1 = s1; p2 = s2; n = len; while (--n >= 0 && *p1 != '\0' && TOLOW(*p1) == TOLOW(*p2)) { p1++; p2++; } if (n < 0) return(0); /* * The following case analysis is necessary so that characters * which look negative collate low against normal characters but * high against the end-of-string NUL. */ if (*p1 == '\0' && *p2 == '\0') return(0); else if (*p1 == '\0') return(-1); else if (*p2 == '\0') return(1); else return(TOLOW(*p1) - TOLOW(*p2)); } /* - mapcase - do case-mapped copy */ static char * /* returns src or dst */ mapcase(dst, src, siz) char *dst; /* destination, used only if mapping needed */ char *src; /* source; src == dst is legal */ size_t siz; { register char *s; register char *d; register char *c; /* case break */ register char *e; /* end of source */ c = cipoint(src, siz); if (c == NULL) return(src); if (!mprimed) mapprime(); s = src; e = s + siz; d = dst; while (s < c) *d++ = *s++; while (s < e) *d++ = TOLOW(*s++); return(dst); } /* - cipoint - where in this message-ID does it become case-insensitive? * * The RFC822 code is not quite complete. Absolute, total, full RFC822 * compliance requires a horrible parsing job, because of the arcane * quoting conventions -- abc"def"ghi is not equivalent to abc"DEF"ghi, * for example. There are three or four things that might occur in the * domain part of a message-id that are case-sensitive. They don't seem * to ever occur in real news, thank Cthulhu. (What? You were expecting * a merciful and forgiving deity to be invoked in connection with RFC822? * Forget it; none of them would come near it.) */ static char * /* pointer into s, or NULL for "nowhere" */ cipoint(s, siz) char *s; size_t siz; { register char *p; static char post[] = "postmaster"; static int plen = sizeof(post)-1; switch (conf.casemap) { case '0': /* unmapped, sensible */ return(NULL); case 'C': /* C News, RFC 822 conformant (approx.) */ p = memchr((POINTER)s, '@', siz); if (p == NULL) /* no local/domain split */ return(NULL); /* assume all local */ if (p - (s+1) == plen && CISTREQN(s+1, post, plen)) { /* crazy -- "postmaster" is case-insensitive */ return(s); } return(p); case '=': /* 2.11, neither sensible nor conformant */ return(s); /* all case-insensitive */ } DEBUG(("cipoint: unknown case mapping `%c'\n", conf.casemap)); return(NULL); /* just leave it alone */ } /* - dbzdebug - control dbz debugging at run time */ #ifdef DBZDEBUG int /* old value */ dbzdebug(value) int value; { register int old = debug; debug = value; return(old); } #endif inn-1.7.2/MakeRnews0100755000175100001440000000541706443103542012460 0ustar mdusers#! /bin/sh ## $Revision: 1.6 $ ## Script to build an easy-to-ship single directory that contains ## everything needed to build rnews on a machine. ## Optional first argument is the destination architecture, like "sun4" DIR=rnews.${1-dist} if [ -d ${DIR} ] ; then echo ${DIR} exists! exit 1 fi mkdir ${DIR} ## Copy the files. for I in \ config/subst.c config/subst.sh config/config.data \ doc/rnews.1 doc/inn.conf.5 frontends/rnews.c \ include/clibrary.h include/configdata.h include/libinn.h \ include/logging.h include/macros.h include/mydir.h include/mystring.h \ include/mymemory.h include/nntp.h include/paths.h \ lib/closeonexec.c lib/findheader.c lib/getconfig.c lib/getfqdn.c \ lib/localopen.c lib/remopen.c lib/sendarticle.c lib/sendpass.c \ lib/strerror.c lib/waitnb.c lib/xmemerr.c lib/xmalloc.c \ lib/xrealloc.c \ site/inn.conf site/passwd.nntp ; do \ cp $I ${DIR} done ## Write the Makefile. We duplicate the RCS revision string of the ## script into the Makefile on purpose. cat <<\EOF >${DIR}/Makefile ## $Revision: 1.6 $ SHELL = /bin/sh MAKE = make ## Configuration dependencies -- edit as appropriate DEFS = CFLAGS = $(DEFS) -g LDFLAGS = -Bstatic LINTFLAGS=-b -h $(DEFS) ## Manual pages -- install as appropriate for your system DOC = rnews.1 inn.conf.5 ## Configuration files -- install in /usr/lib/news CONF = inn.conf passwd.nntp ## Program sources. HEADERS = \ clibrary.h configdata.h libinn.h macros.h nntp.h paths.h SOURCES = \ closeonexec.c findheader.c getconfig.c getfqdn.c localopen.c \ remopen.c rnews.c sendarticle.c sendpass.c strerror.c waitnb.c \ xmalloc.c xmemerr.c xrealloc.c OBJECTS = \ closeonexec.o findheader.o getconfig.o getfqdn.o localopen.o \ remopen.o rnews.o sendarticle.o sendpass.o strerror.o waitnb.o \ xmalloc.o xmemerr.o xrealloc.o ## First target, just compile everything. all: rnews $(DOC) $(CONF) date >all ## Edit these lines as appropriate for your system install: all cp rnews /usr/bin/rnews cp $(CONF) /usr/lib/news cp rnews.1 /usr/man/man1 cp inn.conf.5 /usr/man/man5 ## Clean up, remove non-essentials. clobber clean: rm -f rnews core tags lint a.out *.o lint: rnews lint $(LINTFLAGS) $(SOURCES) >lint rnews: $(OBJECTS) rm -f rnews $(CC) $(LDFLAGS) -o rnews $(CFLAGS) $(OBJECTS) subst: subst.c subst.sh make c || make sh || { rm -f subst ; echo Failed 1>&2 ; } config: subst config.data $(DOC) $(HEADERS) Makefile ./subst -f config.data $(DOC) $(HEADERS) Makefile date >config c: @rm -f subst $(CC) -o subst subst.c sh: @rm -f subst cp subst.sh subst chmod +x subst ## Dependencies. Default list, below, is probably good enough. depend: Makefile $(SOURCES) makedepend $(DEFS) $(SOURCES) # DO NOT DELETE THIS LINE -- make depend depends on it. $(OBJECTS): $(HEADERS) EOF inn-1.7.2/backends/0040755000175100001440000000000006443103542012404 5ustar mdusersinn-1.7.2/backends/shrinkfile.c0100644000175100001440000002153106443103542014705 0ustar mdusers/* $Revision: 1.6 $ ** Shrink files on line boundaries. ** Written by Landon Curt Noll , and placed in the ** public domain. Rewritten for INN by Rich Salz. ** Usage: ** shrinkfile [-n] [-s size [-m maxsize]] [-v] file... ** -n No writes, exit 0 if any file is too large, 1 otherwise ** -s size Truncation size (0 default); suffix may be k, m, ** or g to scale. Must not be larger than 2^31 - 1. ** -m maxsize Maximum size allowed before truncation. If maxsize ** <= size, then it is reset to size. Default == size. ** -v Print status line. ** ** Files will be shrunk an end of line boundary. In no case will the ** file be longer than size bytes if it was longer than maxsize bytes. ** If the first line is longer than the absolute value of size, the file ** will be truncated to zero length. ** ** The -n flag may be used to determine of any file is too large. No ** files will be altered in this mode. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #include #include "libinn.h" #include "macros.h" #define MAX_SIZE (OFFSET_T)0x7fffffff static char *program = NULL; /* our name */ /* ** Open a safe unique temporary file that will go away when closed. */ STATIC FILE * OpenTemp() { FILE *F; char *p; char buff[SMBUF]; int i; /* Get filename. */ if ((p = getenv("TMPDIR")) == NULL) p = "/usr/tmp"; (void)sprintf(buff, "%s/shrinkXXXXXX", p); (void)mktemp(buff); /* Open the file. */ if ((i = open(buff, O_RDWR | O_CREAT | O_EXCL | O_TRUNC, 0600)) < 0) { (void)fprintf(stderr, "%s: Can't make temporary file, %s\n", program, strerror(errno)); exit(1); } if ((F = fdopen(i, "w+")) == NULL) { (void)fprintf(stderr, "%s: Can't fdopen %d, %s\n", program, i, strerror(errno)); exit(1); } (void)unlink(buff); return F; } /* ** Does file end with \n? Assume it does on I/O error, to avoid doing I/O. */ STATIC int EndsWithNewline(F) FILE *F; { int c; if (fseek(F, (OFFSET_T)1, SEEK_END) < 0) { (void)fprintf(stderr, "%s: Can't seek to end of file, %s\n", program, strerror(errno)); return TRUE; } /* return the actual character or EOF */ if ((c = fgetc(F)) == EOF) { if (ferror(F)) (void)fprintf(stderr, "%s: Can't read last byte, %s\n", program, strerror(errno)); return TRUE; } return c == '\n'; } /* ** Add a newline to location of a file. */ STATIC BOOL AppendNewline(name) char *name; { FILE *F; if ((F = xfopena(name)) == NULL) { (void)fprintf(stderr, "%s: Can't add newline, %s\n", program, strerror(errno)); return FALSE; } if (fputc('\n', F) == EOF || fflush(F) == EOF || ferror(F) || fclose(F) == EOF) { (void)fprintf(stderr, "%s: Can't add newline, %s\n", program, strerror(errno)); return FALSE; } return TRUE; } /* ** Just check if it is too big */ STATIC BOOL TooBig(F, maxsize) FILE *F; OFFSET_T maxsize; { struct stat Sb; /* Get the file's size. */ if (fstat((int)fileno(F), &Sb) < 0) { (void)fprintf(stderr, "%s: Can't fstat, %s\n", program, strerror(errno)); return FALSE; } /* return TRUE if too large */ return (maxsize > Sb.st_size ? FALSE : TRUE); } /* ** This routine does all the work. */ STATIC BOOL Process(F, name, size, maxsize, Changedp) FILE *F; char *name; OFFSET_T size; OFFSET_T maxsize; BOOL *Changedp; { OFFSET_T len; FILE *tmp; struct stat Sb; char buff[BUFSIZ + 1]; int c; int i; /* Get the file's size. */ if (fstat((int)fileno(F), &Sb) < 0) { (void)fprintf(stderr, "%s: Can't fstat, %s\n", program, strerror(errno)); return FALSE; } len = Sb.st_size; /* Process a zero size request. */ if (size == 0 && len > maxsize) { if (len > 0) { (void)fclose(F); if ((F = fopen(name, "w")) == NULL) { (void)fprintf(stderr, "%s: Can't overwrite, %s\n", program, strerror(errno)); return FALSE; } (void)fclose(F); *Changedp = TRUE; } return TRUE; } /* See if already small enough. */ if (len <= maxsize) { /* Newline already present? */ if (EndsWithNewline(F)) { (void)fclose(F); return TRUE; } /* No newline, add it if it fits. */ if (len < size - 1) { (void)fclose(F); *Changedp = TRUE; return AppendNewline(name); } } else if (!EndsWithNewline(F)) { if (!AppendNewline(name)) { (void)fclose(F); return FALSE; } } /* We now have a file that ends with a newline that is bigger than * we want. Starting from {size} bytes from end, move forward * until we get a newline. */ if (fseek(F, -size, SEEK_END) < 0) { (void)fprintf(stderr, "%s: Can't fseek, %s\n", program, strerror(errno)); (void)fclose(F); return FALSE; } while ((c = getc(F)) != '\n') if (c == EOF) { (void)fprintf(stderr, "%s: Can't read, %s\n", program, strerror(errno)); (void)fclose(F); return FALSE; } /* Copy rest of file to temp. */ tmp = OpenTemp(); while ((i = fread((POINTER)buff, (SIZE_T)1, (SIZE_T)sizeof buff, F)) > 0) if (fwrite((POINTER)buff, (SIZE_T)1, (SIZE_T)i, tmp) != i) { i = -1; break; } if (i < 0) { (void)fprintf(stderr, "%s: Can't copy to temp file, %s\n", program, strerror(errno)); (void)fclose(F); (void)fclose(tmp); return FALSE; } /* Now copy temp back to original file. */ (void)fclose(F); if ((F = fopen(name, "w")) == NULL) { (void)fprintf(stderr, "%s: Can't overwrite, %s\n", program, strerror(errno)); (void)fclose(tmp); return FALSE; } (void)fseek(tmp, (OFFSET_T)0, SEEK_SET); while ((i = fread((POINTER)buff, (SIZE_T)1, (SIZE_T)sizeof buff, tmp)) > 0) if (fwrite((POINTER)buff, (SIZE_T)1, (SIZE_T)i, F) != i) { i = -1; break; } if (i < 0) { (void)fprintf(stderr, "%s: Can't overwrite file, %s\n", program, strerror(errno)); (void)fclose(F); (void)fclose(tmp); return FALSE; } (void)fclose(F); (void)fclose(tmp); *Changedp = TRUE; return TRUE; } /* ** Convert size argument to numeric value. Return -1 on error. */ STATIC OFFSET_T ParseSize(p) char *p; { OFFSET_T scale; long str_num; char *q; /* Skip leading spaces */ while (ISWHITE(*p)) p++; if (*p == '\0') return -1; /* determine the scaling factor */ q = &p[strlen(p) - 1]; switch (*q) { default: return -1; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': scale = 1; break; case 'k': case 'K': scale = 1024; *q = '\0'; break; case 'm': case 'M': scale = 1024 * 1024; *q = '\0'; break; case 'g': case 'G': scale = 1024 * 1024 * 1024; *q = '\0'; break; } /* Convert string to number. */ if (sscanf(p, "%ld", &str_num) != 1) return -1; if (str_num > MAX_SIZE / scale) { (void)fprintf(stderr, "%s: Size is too big\n", program); exit(1); } return scale * str_num; } /* ** Print usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage: %s [-n] [ -m maxsize ] [-s size] [-v] file...\n", program); exit(1); } int main(ac, av) int ac; char *av[]; { BOOL Changed; BOOL Verbose; BOOL no_op; FILE *F; char *p; int i; OFFSET_T size = (OFFSET_T)0; OFFSET_T maxsize = (OFFSET_T)0; /* Set defaults. */ program = av[0]; Verbose = FALSE; no_op = FALSE; (void)umask(NEWSUMASK); /* Parse JCL. */ while ((i = getopt(ac, av, "m:s:vn")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'n': no_op = TRUE; break; case 'm': if ((maxsize = ParseSize(optarg)) < 0) Usage(); break; case 's': if ((size = ParseSize(optarg)) < 0) Usage(); break; case 'v': Verbose = TRUE; break; } if (maxsize < size) { maxsize = size; } ac -= optind; av += optind; if (ac == 0) Usage(); while ((p = *av++) != NULL) { if ((F = fopen(p, "r")) == NULL) { (void)fprintf(stderr, "%s: Can't open %s, %s\n", program, p, strerror(errno)); continue; } /* -n (no_op) or normal processing */ if (no_op) { /* check if too big and exit zero if it is */ if (TooBig(F, maxsize)) { if (Verbose) (void)printf("%s: %s is too large\n", program, p); exit(0); /* NOTREACHED */ } /* no -n, do some real work */ } else { Changed = FALSE; if (!Process(F, p, size, maxsize, &Changed)) (void)fprintf(stderr, "%s: Can't shrink %s\n", program, p); else if (Verbose && Changed) (void)printf("%s: Shrunk %s\n", program, p); } } if (no_op && Verbose) { (void)printf("%s: did not find a file that was too large\n", program); } /* if -n, then exit non-zero to indicate no file too big */ exit(no_op ? 1 : 0); /* NOTREACHED */ } inn-1.7.2/backends/crosspost.c0100644000175100001440000001473506443103542014616 0ustar mdusers/* $Revision: 1.7 $ ** ** Parse input to add links for cross posted articles ** Input format is one line per article. Dots '.' are changed to ** '/'. Commas ',' or blanks ' ' separate entries. Typically this ** is via a channel feed from innd though an edit of the history file ** can also be used for recovery purposes. Sample newsfeeds entry: ** ** # Create the links for cross posted articles ** crosspost:*:Tc,Ap,WR:/usr/local/newsbin/crosspost ** */ #include #include #include #include "configdata.h" #include #include #include #include "clibrary.h" #include "libinn.h" #include "macros.h" #include "paths.h" #include "qio.h" STATIC BOOL InSpoolDir; STATIC char *Dir; STATIC int debug = FALSE; STATIC int syncfiles = TRUE; #define MAXXPOST 256 /* ** Try to make one directory. Return FALSE on error. */ STATIC BOOL MakeDir(Name) char *Name; { struct stat Sb; if (mkdir(Name, GROUPDIR_MODE) >= 0) return TRUE; /* See if it failed because it already exists. */ return stat(Name, &Sb) >= 0 && S_ISDIR(Sb.st_mode); } /* ** Make spool directory. Return FALSE on error. */ STATIC BOOL MakeSpoolDir(Name) register char *Name; { register char *p; BOOL made; /* Optimize common case -- parent almost always exists. */ if (MakeDir(Name)) return TRUE; /* Try to make each of comp and comp/foo in turn. */ for (p = Name; *p; p++) if (*p == '/') { *p = '\0'; made = MakeDir(Name); *p = '/'; if (!made) return FALSE; } return MakeDir(Name); } /* ** Process the input. Data can come from innd: ** news/group/name/ [space news/group/]... ** or ** news.group.name/,[news.group.name/]... */ STATIC void ProcessIncoming(qp) QIOSTATE *qp; { register char *p; register int i; int nxp; int fd; int lnval ; char *names[MAXXPOST]; for ( ; ; ) { /* Read the first line of data. */ if ((p = QIOread(qp)) == NULL) { if (QIOtoolong(qp)) { (void)fprintf(stderr, "crosspost line too long\n"); continue; } break; } for (i = 0; *p && (i < MAXXPOST); i++) { /* parse input into array */ names[i] = p; for ( ; *p; p++) { if (*p == '.') *p++ = '/'; /* dot to slash translation */ else if ((*p == ',') /* name separators */ || (*p == ' ') || (*p == '\t') || (*p == '\n')) { *p++ = '\0'; break; } } } nxp = i; if (debug) { for (i = 0; i < nxp; i++) (void)fprintf(stderr, "crosspost: debug %d %s\n", i, names[i]); } if(syncfiles) fd = open(names[0], O_RDWR); for (i = 1; i < nxp; i++) { lnval = link(names[0], names[i]) ; if (lnval < 0 && errno != EXDEV) { /* first try to link */ register int j; char path[SPOOLNAMEBUFF+2]; for (j = 0; (path[j] = names[i][j]) != '\0' ; j++) ; for (j--; (j > 0) && (path[j] != '/'); j--) ; if (path[j] == '/') { path[j] = '\0'; /* try making parent dir */ if (MakeSpoolDir(path) == FALSE) { (void)fprintf(stderr, "crosspost cant mkdir %s\n", path); } else { /* 2nd try to link */ lnval = link(names[0], names[i]) ; if (lnval < 0 && errno == EXDEV) { #if defined(DONT_HAVE_SYMLINK) (void)fprintf(stderr, "crosspost cant link %s %s", names[0], names[i]); perror(" "); #else /* Try to make a symbolic link ** to the full pathname. */ for (j = 0, p = Dir; (j < SPOOLNAMEBUFF) && *p; ) path[j++] = *p++; /* copy spool dir */ if (j < SPOOLNAMEBUFF) path[j++] = '/'; for (p = names[0]; (j < SPOOLNAMEBUFF) && *p; ) path[j++] = *p++; /* append path */ path[j++] = '\0'; if (symlink(path, names[i]) < 0) { (void)fprintf(stderr, "crosspost cant symlink %s %s", path, names[i]); perror(" "); } #endif /* defined(DONT_HAVE_SYMLINK) */ } else if (lnval < 0) { (void)fprintf(stderr, "crosspost cant link %s %s", names[0], names[i]); perror(" "); } } } else { (void)fprintf(stderr, "crosspost bad path %s\n", names[i]); } } else if (lnval < 0) { register int j; char path[SPOOLNAMEBUFF+2]; #if defined(DONT_HAVE_SYMLINK) (void)fprintf(stderr, "crosspost cant link %s %s", names[0], names[i]); perror(" "); #else /* Try to make a symbolic link ** to the full pathname. */ for (j = 0, p = Dir; (j < SPOOLNAMEBUFF) && *p; ) path[j++] = *p++; /* copy spool dir */ if (j < SPOOLNAMEBUFF) path[j++] = '/'; for (p = names[0]; (j < SPOOLNAMEBUFF) && *p; ) path[j++] = *p++; /* append path */ path[j++] = '\0'; if (symlink(path, names[i]) < 0) { (void)fprintf(stderr, "crosspost cant symlink %s %s", path, names[i]); perror(" "); } #endif /* defined(DONT_HAVE_SYMLINK) */ } } if (syncfiles && (fd >= 0)) { (void)fsync(fd); (void)close(fd); } } if (QIOerror(qp)) (void)fprintf(stderr, "crosspost cant read %s\n", strerror(errno)); QIOclose(qp); } STATIC NORETURN Usage() { (void)fprintf(stderr, "usage: crosspost [-D dir] [files...]\n"); exit(1); } int main(ac, av) int ac; char *av[]; { register int i; QIOSTATE *qp; /* Set defaults. */ Dir = _PATH_SPOOL; (void)umask(NEWSUMASK); /* Parse JCL. */ while ((i = getopt(ac, av, "D:ds")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'D': Dir = optarg; /* specify spool path */ break; case 'd': debug = TRUE; break; case 's': syncfiles = FALSE; /* do not fsync articles */ break; } ac -= optind; av += optind; InSpoolDir = EQ(Dir, _PATH_SPOOL); if (chdir(Dir) < 0) { (void)fprintf(stderr, "crosspost cant chdir %s %s\n", Dir, strerror(errno)); exit(1); } if (ac == 0) ProcessIncoming(QIOfdopen(STDIN, QIO_BUFFER)); else { for ( ; *av; av++) if (EQ(*av, "-")) ProcessIncoming(QIOfdopen(STDIN, QIO_BUFFER)); else if ((qp = QIOopen(*av, QIO_BUFFER)) == NULL) (void)fprintf(stderr, "crosspost cant open %s %s\n", *av, strerror(errno)); else ProcessIncoming(qp); } exit(0); /* NOTREACHED */ } inn-1.7.2/backends/archive.c0100644000175100001440000002357206443103542014177 0ustar mdusers/* $Revision: 1.9 $ ** ** Read batchfiles on standard input and archive them. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include "paths.h" #include "libinn.h" #include "qio.h" #include "macros.h" STATIC STRING Archive = _PATH_ARCHIVEDIR; STATIC char SPOOL[] = _PATH_SPOOL; static char BATCHDIR[] = _PATH_BATCHDIR; /* ** Try to make one directory. Return FALSE on error. */ STATIC BOOL MakeDir(Name) char *Name; { struct stat Sb; if (mkdir(Name, GROUPDIR_MODE) >= 0) return TRUE; /* See if it failed because it already exists. */ return stat(Name, &Sb) >= 0 && S_ISDIR(Sb.st_mode); } /* ** Given an entry, comp/foo/bar/1123, create the directory and all ** parent directories needed. Return FALSE on error. */ STATIC BOOL MakeArchiveDirectory(Name) register char *Name; { register char *p; register char *save; BOOL made; if ((save = strrchr(Name, '/')) != NULL) *save = '\0'; /* Optimize common case -- parent almost always exists. */ if (MakeDir(Name)) { if (save) *save = '/'; return TRUE; } /* Try to make each of comp and comp/foo in turn. */ for (p = Name; *p; p++) if (*p == '/' && p != Name) { *p = '\0'; made = MakeDir(Name); *p = '/'; if (!made) { if (save) *save = '/'; return FALSE; } } made = MakeDir(Name); if (save) *save = '/'; return made; } /* ** Write an index entry. Ignore I/O errors; our caller checks for them. */ STATIC void WriteIndex(FullName, ShortName) char *FullName; char *ShortName; { static char SUBJECT[] = "Subject:"; static char MESSAGEID[] = "Message-ID:"; register char *p; register QIOSTATE *qp; char Subject[BUFSIZ]; char MessageID[BUFSIZ]; /* Open the file. */ if ((qp = QIOopen(FullName, QIO_BUFFER)) == NULL) { (void)printf("%s %s\n", ShortName, strerror(errno)); return; } /* Scan for the desired headers. */ for (Subject[0] = '\0', MessageID[0] = '\0'; ; ) { if ((p = QIOread(qp)) == NULL) { if (QIOerror(qp)) { (void)printf("%s %s\n", ShortName, strerror(errno)); QIOclose(qp); return; } if (QIOtoolong(qp)) { (void)QIOread(qp); continue; } /* End of headers (and article) -- we're done. */ break; } /* End of headers -- we're done. */ if (*p == '\0') break; /* Is this a header we want? */ switch (*p) { default: continue; case 'S': case 's': if (caseEQn(p, SUBJECT, STRLEN(SUBJECT))) { for (p += STRLEN(SUBJECT); ISWHITE(*p); p++) continue; (void)strcpy(Subject, p); } break; case 'M': case 'm': if (caseEQn(p, MESSAGEID, STRLEN(MESSAGEID))) { for (p += STRLEN(MESSAGEID); ISWHITE(*p); p++) continue; (void)strcpy(MessageID, p); } break; } /* Got them all? */ if (Subject[0] && MessageID[0]) break; } /* Close file, write the line. */ QIOclose(qp); (void)printf("%s %s %s\n", ShortName, MessageID[0] ? MessageID : "", Subject[0] ? Subject : ""); } /* ** Copy a file. Return FALSE if error. */ STATIC BOOL Copy(src, dest) char *src; char *dest; { register FILE *in; register FILE *out; register SIZE_T i; char *p; char buff[BUFSIZ]; /* Open the output file. */ if ((out = fopen(dest, "w")) == NULL) { /* Failed; make any missing directories and try again. */ if ((p = strrchr(dest, '/')) != NULL) { if (!MakeArchiveDirectory(dest)) { (void)fprintf(stderr, "Can't mkdir for \"%s\", %s\n", dest, strerror(errno)); return FALSE; } out = fopen(dest, "w"); } if (p == NULL || out == NULL) { (void)fprintf(stderr, "Can't open \"%s\" for writing, %s\n", src, strerror(errno)); return FALSE; } } /* Opening the input file is easier. */ if ((in = fopen(src, "r")) == NULL) { (void)fprintf(stderr, "Can't open \"%s\" for reading, %s\n", src, strerror(errno)); (void)fclose(out); (void)unlink(dest); return FALSE; } /* Write the data. */ while ((i = fread((POINTER)buff, (SIZE_T)1, (SIZE_T)sizeof buff, in)) != 0) if (fwrite((POINTER)buff, (SIZE_T)1, i, out) != i) { (void)fprintf(stderr, "Can't write \"%s\", %s\n", dest, strerror(errno)); (void)fclose(in); (void)fclose(out); (void)unlink(dest); return FALSE; } (void)fclose(in); /* Flush and close the output. */ if (ferror(out) || fflush(out) == EOF) { (void)fprintf(stderr, "Can't close \"%s\", %s\n", dest, strerror(errno)); (void)unlink(dest); (void)fclose(out); return FALSE; } if (fclose(out) == EOF) { (void)fprintf(stderr, "Can't close \"%s\", %s\n", dest, strerror(errno)); (void)unlink(dest); return FALSE; } return TRUE; } /* ** Print a usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage error.\n"); exit(1); } int main(ac, av) int ac; char *av[]; { register char *Name; register char *p; register FILE *F; register int i; BOOL Flat; BOOL Move; BOOL Redirect; char *Index; char *last; char buff[BUFSIZ]; char temp[BUFSIZ]; char dest[BUFSIZ]; struct stat Sb; /* Set defaults. */ Flat = FALSE; Index = NULL; Move = FALSE; Redirect = TRUE; (void)umask(NEWSUMASK); /* Parse JCL. */ while ((i = getopt(ac, av, "a:fi:mr")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'a': Archive = optarg; break; case 'f': Flat = TRUE; break; case 'i': Index = optarg; break; case 'm': Move = TRUE; break; case 'r': Redirect = FALSE; break; } #if defined(DONT_HAVE_SYMLINK) if (Move) (void)fprintf(stderr, "archive: Ignoring ``-m'' flag\n"); #endif /* defined(DONT_HAVE_SYMLINK) */ /* Parse arguments -- at most one, the batchfile. */ ac -= optind; av += optind; if (ac > 2) Usage(); /* Do file redirections. */ if (Redirect) (void)freopen(_PATH_ERRLOG, "a", stderr); if (ac == 1 && freopen(av[0], "r", stdin) == NULL) { (void)fprintf(stderr, "archive: Can't open \"%s\" for input, %s\n", av[0], strerror(errno)); exit(1); } if (Index && freopen(Index, "a", stdout) == NULL) { (void)fprintf(stderr, "archive: Can't open \"%s\" for output, %s\n", Index, strerror(errno)); exit(1); } /* Go to where the action is. */ if (chdir(SPOOL) < 0) { (void)fprintf(stderr, "archive: Can't cd to \"%s\", %s\n", SPOOL, strerror(errno)); exit(1); } /* Set up the destination. */ (void)strcpy(dest, Archive); Name = dest + strlen(dest); *Name++ = '/'; /* Read input. */ while (fgets(buff, sizeof buff, stdin) != NULL) { if ((p = strchr(buff, '\n')) == NULL) { (void)fprintf(stderr, "archive: Skipping \"%.40s...\" -- too long\n", buff); continue; } *p = '\0'; if (buff[0] == '\0' || buff[0] == COMMENT_CHAR) continue; /* Make sure we're only copying files. */ if (stat(buff, &Sb) < 0) { if (errno != ENOENT) (void)fprintf(stderr, "Can't stat \"%s\", %s\n", buff, strerror(errno)); continue; } if (!S_ISREG(Sb.st_mode)) { (void)fprintf(stderr, "\"%s\" is not a regular file\n", buff); continue; } /* Set up the destination name. */ (void)strcpy(Name, buff); if (Flat) { for (last = NULL, p = Name; *p; p++) if (*p == '/') { last = p; *p = '.'; } if (last) *last = '/'; } #if defined(DO_HAVE_SYMLINK) if (Move) { if (!Copy(buff, dest)) continue; if (unlink(buff) < 0 && errno != ENOENT) (void)fprintf(stderr, "Can't remove \"%s\", %s\n", buff, strerror(errno)); if (symlink(dest, buff) < 0) (void)fprintf(stderr, "Can't symlink \"%s\" to \"%s\", %s\n", buff, dest, strerror(errno)); continue; } #endif /* defined(DO_HAVE_SYMLINK) */ /* Try to link the file into the archive. */ if (link(buff, dest) < 0) { /* Make the archive directory. */ if (!MakeArchiveDirectory(dest)) { (void)fprintf(stderr, "Can't mkdir for \"%s\", %s\n", dest, strerror(errno)); continue; } /* Try to link again; if that fails, make a copy. */ if (link(buff, dest) < 0 && !Copy(buff, dest)) continue; } /* Write index. */ if (Index) { WriteIndex(dest, Name); if (ferror(stdout) || fflush(stdout) == EOF) (void)fprintf(stderr, "Can't write index for \"%s\", %s\n", Name, strerror(errno)); } } /* If we read all our input, try to remove the file, and we're done. */ if (feof(stdin)) { (void)fclose(stdin); if (av[0]) (void)unlink(av[0]); exit(0); } /* Make an appropriate spool file. */ p = av[0]; if (p == NULL) (void)sprintf(temp, "%s/%s", BATCHDIR, "archive"); else if (*p == '/') (void)sprintf(temp, "%s.bch", p); else (void)sprintf(temp, "%s/%s.bch", BATCHDIR, p); if ((F = xfopena(temp)) == NULL) { (void)fprintf(stderr, "archive: Can't spool to \"%s\", %s\n", temp, strerror(errno)); exit(1); } /* Write the rest of stdin to the spool file. */ i = 0; if (fprintf(F, "%s\n", buff) == EOF) { (void)fprintf(stderr, "archive: Can't start spool, %s\n", strerror(errno)); i = 1; } while (fgets(buff, sizeof buff, stdin) != NULL) if (fputs(buff, F) == EOF) { (void)fprintf(stderr, "archive: Can't write spool, %s\n", strerror(errno)); i = 1; break; } if (fclose(F) == EOF) { (void)fprintf(stderr, "archive: Can't close spool, %s\n", strerror(errno)); i = 1; } /* If we had a named input file, try to rename the spool. */ if (p != NULL && rename(temp, av[0]) < 0) { (void)fprintf(stderr, "archive: Can't rename spool, %s\n", strerror(errno)); i = 1; } exit(i); /* NOTREACHED */ } inn-1.7.2/backends/actmerge.sh0100644000175100001440000001110106443103542014516 0ustar mdusers#!/bin/sh # @(#) $Id: actmerge.sh,v 1.6 1996/11/19 13:51:00 brister Exp $ # @(#) Under RCS control in /usr/local/news/src/inn/local/RCS/actmerge.sh,v # # actmerge - merge two active files # # usage: # actmerge [-s] ign1 ign2 host1 host2 # # -s - write status on stderr even if no fatal error # ign1 - ignore file for host1 # ign2 - ignore file for host2 # host1 - 1st active file or host # host2 - 2nd active file or host # # The merge of two active files are sent to stdout. The status is # written to stderr. # By: Landon Curt Noll chongo@toad.com (chongo was here /\../\) # # Copyright (c) Landon Curt Noll, 1996. # All rights reserved. # # Permission to use and modify is hereby granted so long as this # notice remains. Use at your own risk. No warranty is implied. # preset vars # # =()<. @<_PATH_SHELLVARS>@>()= . /var/news/etc/innshellvars # Our lock file LOCK=${LOCKS}/LOCK.actmerge # where actsync is located ACTSYNC=${NEWSBIN}/actsync # exit value of actsync if unable to get an active file NOSYNC=127 # args used by actsync a fetch of an active file FETCH="-b 0 -d 0 -g 0 -o aK -p 0 -q 12 -s 0 -t 0 -v 2" # args used to merge two active files MERGE="-b 0 -d 0 -g 0 -m -o aK -p 0 -q 12 -s 0 -t 0 -v 3" # unless -q QUIET=true # parse args # if [ $# -gt 1 ]; then if [ X"-s" = X"$1" ]; then QUIET= shift fi fi if [ $# -ne 4 ]; then echo "usage: $0 ign1 ign2 host1 host2" 1>&2 exit 1 fi ign1="$1" if [ ! -s "$ign1" ]; then echo "$0: host1 ignore file not found or empty: $ign1" 1>&2 exit 2 fi ign2="$2" if [ ! -s "$ign2" ]; then echo "$0: host2 ignore file not found or empty: $ign2" 1>&2 exit 3 fi host1="$3" host2="$4" # Lock out others # trap 'rm -f ${LOCK}; exit 1' 0 1 2 3 15 shlock -p $$ -f ${LOCK} || { echo "$0: Locked by `cat ${LOCK}`" 1>&2 exit 4 } # setup # tmp="$TMPDIR/.merge$$" act1="$TMPDIR/.act1$$" act2="$TMPDIR/.act2$$" trap "rm -f $tmp ${LOCK} $act1 $act2; exit" 0 1 2 3 15 rm -f "$tmp" touch "$tmp" chmod 0600 "$tmp" rm -f "$act1" touch "$act1" chmod 0600 "$act1" rm -f "$act2" touch "$act2" chmod 0600 "$act2" # try to fetch the first active file # echo "=-= fetching $host1" >>$tmp eval "$ACTSYNC -i $ign1 $FETCH /dev/null $host1 > $act1 2>>$tmp" status=$? if [ "$status" -ne 0 ]; then # We failed on our first try, so we will trice knock 3 times after # waiting 5 minutes. # for loop in 1 2 3; do # wait 5 minutes sleep 300 # try #1 eval "$ACTSYNC -i $ign1 $FETCH /dev/null $host1 > $act1 2>>$tmp" status=$? if [ "$status" -eq "$NOSYNC" ]; then break; fi # try #2 eval "$ACTSYNC -i $ign1 $FETCH /dev/null $host1 > $act1 2>>$tmp" status=$? if [ "$status" -eq "$NOSYNC" ]; then break; fi # try #3 eval "$ACTSYNC -i $ign1 $FETCH /dev/null $host1 > $act1 2>>$tmp" status=$? if [ "$status" -eq "$NOSYNC" ]; then break; fi done # give up # if [ "$status" -ne 0 ]; then echo "=-= `date` merge $host1 $host2 exit $status" 1>&2 sed -e 's/^/ /' < "$tmp" 1>&2 exit "$status" fi fi if [ ! -s "$act1" ]; then echo "$0: host1 active file not found or empty: $act1" 1>&2 exit 5 fi # try to fetch the second active file # echo "=-= fetching $host2" >>$tmp eval "$ACTSYNC -i $ign2 $FETCH /dev/null $host2 > $act2 2>>$tmp" status=$? if [ "$status" -ne 0 ]; then # We failed on our first try, so we will trice knock 3 times after # waiting 5 minutes. # for loop in 1 2 3; do # wait 5 minutes sleep 300 # try #1 eval "$ACTSYNC -i $ign2 $FETCH /dev/null $host2 > $act2 2>>$tmp" status=$? if [ "$status" -eq "$NOSYNC" ]; then break; fi # try #2 eval "$ACTSYNC -i $ign2 $FETCH /dev/null $host2 > $act2 2>>$tmp" status=$? if [ "$status" -eq "$NOSYNC" ]; then break; fi # try #3 eval "$ACTSYNC -i $ign2 $FETCH /dev/null $host2 > $act2 2>>$tmp" status=$? if [ "$status" -eq "$NOSYNC" ]; then break; fi done # give up # if [ "$status" -ne 0 ]; then echo "=-= `date` merge $host1 $host2 exit $status" 1>&2 sed -e 's/^/ /' < "$tmp" 1>&2 exit "$status" fi fi if [ ! -s "$act2" ]; then echo "$0: host2 active file not found or empty: $act2" 1>&2 exit 6 fi # merge the 2 active files to stdout # echo "=-= merging $host1 and $host2" >>$tmp eval "$ACTSYNC $MERGE $act1 $act2" 2>>$tmp status=$? if [ "$status" -ne 0 ]; then echo "=-= `date` merge $host1 $host2 exit $status" 1>&2 sed -e 's/^/ /' < "$tmp" 1>&2 exit "$status" fi # if not -q, send status to stderr # if [ -z "$QUIET" ]; then echo "=-= `date` merge $host1 $host2 successful" 1>&2 sed -e 's/^/ /' < "$tmp" 1>&2 fi # all done # rm -f "${LOCK}" exit 0 inn-1.7.2/backends/innxbatch.c0100644000175100001440000003352706443103542014535 0ustar mdusers/* ** innxbatch.c ** ** $Id: innxbatch.c,v 1.2 1996/10/16 15:14:20 brister Exp $ ** ** Transmit batches to remote site, using the XBATCH command ** Modelled after innxmit.c and nntpbatch.c ** ** Invocation: ** innxbatch [options] ... #ifdef FROMSTDIN ** innxbatch -i #endif FROMSTDIN ** will connect to serverhost's nntp port, and transfer the named files, ** with an xbatch command for every file. Files that have been sent ** successfully are unlink()ed. In case of any error, innxbatch terminates ** and leaves any remaining files untouched, for later transmission. ** Options: ** -D increase debug level ** -v report statistics to stdout #ifdef FROMSTDIN ** -i read batch file names from stdin instead from command line. ** For each successfully transmitted batch, an OK is printed on ** stdout, to indicate that another file name is expected. #endif ** -t Timeout for connection attempt ** -T Timeout for batch transfers. ** We do not use any file locking. At worst, a batch could be transmitted ** twice in parallel by two independant invocations of innxbatch. ** To prevent this, innxbatch should e invoked by a shell script that uses ** shlock(1) to achieve mutual exclusion. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #include #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include /*#include */ #include "nntp.h" #include "logging.h" #include "libinn.h" #include "macros.h" /* ** Syslog formats - collected together so they remain consistent */ STATIC char STAT1[] = "%s stats offered %lu accepted %lu refused %lu rejected %lu"; STATIC char STAT2[] = "%s times user %.3f system %.3f elapsed %.3f"; STATIC char CANT_CONNECT[] = "%s connect failed %s"; STATIC char CANT_AUTHENTICATE[] = "%s authenticate failed %s"; STATIC char XBATCH_FAIL[] = "%s xbatch failed %s"; STATIC char UNKNOWN_REPLY[] = "Unknown reply after sending batch -- %s"; STATIC char CANNOT_UNLINK[] = "cannot unlink %s: %m"; /* ** Global variables. */ STATIC BOOL Debug = 0; STATIC BOOL STATprint; STATIC char *REMhost; STATIC double STATbegin; STATIC double STATend; STATIC char *XBATCHname; STATIC int FromServer; STATIC int ToServer; STATIC SIGVAR GotAlarm; STATIC SIGVAR GotInterrupt; STATIC SIGVAR JMPyes; STATIC jmp_buf JMPwhere; STATIC unsigned long STATaccepted; STATIC unsigned long STAToffered; STATIC unsigned long STATrefused; STATIC unsigned long STATrejected; /* ** Send a line to the server. \r\n will be appended */ STATIC BOOL REMwrite(fd, p) register int fd; register char *p; { register int i; register int err; register char *dest; static char buff[NNTP_STRLEN]; for (dest = buff, i = 0; p[i]; ) *dest++ = p[i++]; *dest++ = '\r'; *dest++ = '\n'; *dest++ = '\0'; for (dest = buff, i+=2; i; dest += err, i -= err) { err = write(fd, dest, i); if (err < 0) { (void)fprintf(stderr, "cant write %s to %s: %s\n", REMhost, dest, strerror(errno)); return FALSE; } } if (Debug) (void)fprintf(stderr, "> %s\n", p); return TRUE; } /* ** Print transfer statistics, clean up, and exit. */ STATIC NORETURN ExitWithStats(x) int x; { static char QUIT[] = "quit"; TIMEINFO Now; double usertime; double systime; (void)REMwrite(ToServer, QUIT); (void)GetTimeInfo(&Now); STATend = TIMEINFOasDOUBLE(Now); if (GetResourceUsage(&usertime, &systime) < 0) { usertime = 0; systime = 0; } if (STATprint) { (void)printf(STAT1, REMhost, STAToffered, STATaccepted, STATrefused, STATrejected); (void)printf("\n"); (void)printf(STAT2, REMhost, usertime, systime, STATend - STATbegin); (void)printf("\n"); } syslog(L_NOTICE, STAT1, REMhost, STAToffered, STATaccepted, STATrefused, STATrejected); syslog(L_NOTICE, STAT2, REMhost, usertime, systime, STATend - STATbegin); exit(x); /* NOTREACHED */ } /* ** Clean up the NNTP escapes from a line. */ STATIC char * REMclean(buff) char *buff; { char *p; if ((p = strchr(buff, '\r')) != NULL) *p = '\0'; if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; /* The dot-escape is only in text, not command responses. */ return buff; } /* ** Read a line of input, with timeout. We expect only answer lines, so ** we ignore \r\n-->\n mapping and the dot escape. ** Return TRUE if okay, *or we got interrupted.* */ STATIC BOOL REMread(start, size) char *start; int size; { register char *p; register char *h; struct timeval t; FDSET rmask; int i; for (p = start; size; ) { FD_ZERO(&rmask); FD_SET(FromServer, &rmask); t.tv_sec = 10 * 60; t.tv_usec = 0; i = select(FromServer + 1, &rmask, (FDSET *)NULL, (FDSET *)NULL, &t); if (GotInterrupt) return TRUE; if (i < 0) { if (errno == EINTR) continue; else return FALSE; } if (i == 0 || !FD_ISSET(FromServer, &rmask)) return FALSE; i = read(FromServer, p, size-1); if (GotInterrupt) return TRUE; if (i <= 0) return FALSE; h = p; p += i; size -= i; for ( ; h < p; h++) { if (h > start && '\n' == *h && '\r' == h[-1]) { *h = h[-1] = '\0'; size = 0; } } } if (Debug) (void)fprintf(stderr, "< %s\n", start); return TRUE; } /* ** Handle the interrupt. */ static void Interrupted() { (void)fprintf(stderr, "Interrupted\n"); ExitWithStats(1); } /* ** Send a whole xbatch to the server. Uses the global variables ** REMbuffer & friends */ STATIC BOOL REMsendxbatch(fd, buf, size) int fd; char *buf; int size; { register char *p; int i; int err; for (i = size, p = buf; i; p += err, i -= err) { err = write(fd, p, i); if (err < 0) { (void)fprintf(stderr, "cant write xbatch to %s: %s\n", REMhost, strerror(errno)); return FALSE; } } if (GotInterrupt) Interrupted(); if (Debug) (void)fprintf(stderr, "> [%d bytes of xbatch]\n", size); /* What did the remote site say? */ if (!REMread(buf, size)) { (void)fprintf(stderr, "No reply after sending xbatch, %s\n", strerror(errno)); return FALSE; } if (GotInterrupt) Interrupted(); /* Parse the reply. */ switch (atoi(buf)) { default: (void)fprintf(stderr, "Unknown reply after sending batch -- %s", buf); syslog(L_ERROR, UNKNOWN_REPLY, buf); return FALSE; /* NOTREACHED */ break; case NNTP_RESENDIT_VAL: case NNTP_GOODBYE_VAL: syslog(L_NOTICE, XBATCH_FAIL, REMhost, buf); STATrejected++; return FALSE; /* NOTREACHED */ break; case NNTP_OK_XBATCHED_VAL: STATaccepted++; if (Debug) (void)fprintf(stderr, "will unlink(%s)\n", XBATCHname); if (unlink(XBATCHname)) { /* probably another incarantion was faster, so avoid further duplicate * work */ (void)fprintf(stderr, "cannot unlink %s: %s\n", XBATCHname, strerror(errno)); syslog(L_NOTICE, CANNOT_UNLINK, XBATCHname); return FALSE; } break; } /* Article sent */ return TRUE; } /* ** Mark that we got interrupted. */ STATIC SIGHANDLER CATCHinterrupt(s) int s; { GotInterrupt = TRUE; /* Let two interrupts kill us. */ (void)signal(s, SIG_DFL); } /* ** Mark that the alarm went off. */ /* ARGSUSED0 */ STATIC SIGHANDLER CATCHalarm(s) int s; { GotAlarm = TRUE; if (JMPyes) longjmp(JMPwhere, 1); } /* ** Print a usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage: innxbatch [-D] [-v] [-t#] [-T#] host file ...\n"); #ifdef FROMSTDIN (void)fprintf(stderr, " innxbatch [-D] [-v] [-t#] [-T#] -i host\n"); #endif exit(1); } int main(ac, av) int ac; char *av[]; { int i; register char *p; TIMEINFO Now; FILE *From; FILE *To; char buff[NNTP_STRLEN]; SIGHANDLER (*old)(); unsigned int ConnectTimeout; unsigned int TotalTimeout; struct stat statbuf; int fd; int err; char *XBATCHbuffer = NULL; int XBATCHbuffersize = 0; int XBATCHsize; /* Set defaults. */ ConnectTimeout = 0; TotalTimeout = 0; (void)umask(NEWSUMASK); /* Parse JCL. */ while ((i = getopt(ac, av, "Dit:T:v")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ break; case 'D': Debug++; break; #ifdef FROMSTDIN case 'i': FromStdin = TRUE; break; #endif case 't': ConnectTimeout = atoi(optarg); break; case 'T': TotalTimeout = atoi(optarg); break; case 'v': STATprint = TRUE; break; } ac -= optind; av += optind; /* Parse arguments; host and filename. */ if (ac < 2) Usage(); REMhost = av[0]; ac--; av++; (void)openlog("innxmit", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG); /* Open a connection to the remote server. */ if (ConnectTimeout) { GotAlarm = FALSE; old = signal(SIGALRM, CATCHalarm); (void)alarm(ConnectTimeout); JMPyes = TRUE; if (setjmp(JMPwhere)) { (void)fprintf(stderr, "Can't connect to %s, timed out\n", REMhost); exit(1); } } if (NNTPconnect(REMhost, &From, &To, buff) < 0 || GotAlarm) { i = errno; (void)fprintf(stderr, "Can't connect to %s, %s\n", REMhost, buff[0] ? REMclean(buff) : strerror(errno)); if (GotAlarm) syslog(L_NOTICE, CANT_CONNECT, REMhost, "timeout"); else syslog(L_NOTICE, CANT_CONNECT, REMhost, buff[0] ? REMclean(buff) : strerror(i)); exit(1); } if (Debug) (void)fprintf(stderr, "< %s\n", REMclean(buff)); if (NNTPsendpassword(REMhost, From, To) < 0 || GotAlarm) { i = errno; (void)fprintf(stderr, "Can't authenticate with %s, %s\n", REMhost, strerror(errno)); syslog(L_ERROR, CANT_AUTHENTICATE, REMhost, GotAlarm ? "timeout" : strerror(i)); /* Don't send quit; we want the remote to print a message. */ exit(1); } if (ConnectTimeout) { (void)alarm(0); (void)signal(SIGALRM, old); JMPyes = FALSE; } /* We no longer need standard I/O. */ FromServer = fileno(From); ToServer = fileno(To); #if defined(SOL_SOCKET) && defined(SO_SNDBUF) && defined(SO_RCVBUF) i = 24 * 1024; if (setsockopt(ToServer, SOL_SOCKET, SO_SNDBUF, (char *)&i, sizeof i) < 0) (void)perror("cant setsockopt(SNDBUF)"); if (setsockopt(FromServer, SOL_SOCKET, SO_RCVBUF, (char *)&i, sizeof i) < 0) (void)perror("cant setsockopt(RCVBUF)"); #endif /* defined(SOL_SOCKET) && defined(SO_SNDBUF) && defined(SO_RCVBUF) */ /* Set up signal handlers. */ (void)signal(SIGHUP, CATCHinterrupt); (void)signal(SIGINT, CATCHinterrupt); (void)signal(SIGTERM, CATCHinterrupt); (void)signal(SIGPIPE, SIG_IGN); if (TotalTimeout) { (void)alarm(TotalTimeout); (void)signal(SIGALRM, CATCHalarm); } GotInterrupt = FALSE; GotAlarm = FALSE; /* Start timing. */ if (GetTimeInfo(&Now) < 0) { (void)fprintf(stderr, "Can't get time, %s\n", strerror(errno)); exit(1); } STATbegin = TIMEINFOasDOUBLE(Now); /* main loop over all specified files */ for (XBATCHname = *av; ac && (XBATCHname = *av); av++, ac--) { if (Debug) (void)fprintf(stderr, "will work on %s\n", XBATCHname); if (GotAlarm) { (void)fprintf(stderr, "Timed out\n"); ExitWithStats(1); } if (GotInterrupt) Interrupted(); if ((fd = open(XBATCHname, O_RDONLY, 0)) < 0) { (void)fprintf(stderr, "Can't open \"%s\", %s - skipping it\n", XBATCHname, strerror(errno)); continue; } if (fstat(fd, &statbuf)) { (void)fprintf(stderr, "Can't stat \"%s\", %s - skipping it\n", XBATCHname, strerror(errno)); (void)close(i); continue; } XBATCHsize = statbuf.st_size; if (XBATCHsize == 0) { (void)fprintf(stderr, "Batch file \"%s\" is zero length, - skipping it\n", XBATCHname); (void)close(i); (void)unlink(XBATCHname); continue; } else if (XBATCHsize > XBATCHbuffersize) { XBATCHbuffersize = XBATCHsize; if (XBATCHbuffer) DISPOSE(XBATCHbuffer); XBATCHbuffer = NEW(char, XBATCHsize); } for (i = XBATCHsize, p = XBATCHbuffer; i; i -= err, p+= err) { err = read(fd, p, i); if (err < 0) { (void)fprintf(stderr, "error reading %s: %s - skipping it\n", XBATCHname, strerror(errno)); break; } else if (0 == err) { (void)fprintf(stderr, "unexpected EOF reading %s: %s - truncated\n", XBATCHname, strerror(errno)); XBATCHsize = p - XBATCHbuffer; break; } } (void)close(fd); if (err < 0) continue; if (GotInterrupt) Interrupted(); /* Offer the xbatch. */ (void)sprintf(buff, "xbatch %d", XBATCHsize); if (!REMwrite(ToServer, buff)) { (void)fprintf(stderr, "Can't offer xbatch to %s, %s\n", REMhost, strerror(errno)); ExitWithStats(1); } STAToffered++; if (GotInterrupt) Interrupted(); /* Does he want it? */ if (!REMread(buff, (int)sizeof buff)) { (void)fprintf(stderr, "No reply to XBATCH %d from %s, %s\n", XBATCHsize, REMhost, strerror(errno)); ExitWithStats(1); } if (GotInterrupt) Interrupted(); /* Parse the reply. */ switch (atoi(buff)) { default: (void)fprintf(stderr, "Unknown reply to \"%s\" -- %s", XBATCHname, buff); ExitWithStats(1); /* NOTREACHED */ break; case NNTP_RESENDIT_VAL: case NNTP_GOODBYE_VAL: /* Most likely out of space -- no point in continuing. */ syslog(L_NOTICE, XBATCH_FAIL, REMhost, buff); ExitWithStats(1); /* NOTREACHED */ case NNTP_CONT_XBATCH_VAL: if (!REMsendxbatch(ToServer, XBATCHbuffer, XBATCHsize)) ExitWithStats(1); /* NOTREACHED */ break; case NNTP_SYNTAX_VAL: case NNTP_BAD_COMMAND_VAL: (void)fprintf(stderr, "Server %s seems not understand XBATCH: %s\n", REMhost, buff); syslog(L_FATAL, XBATCH_FAIL, REMhost, buff); break; } } ExitWithStats(0); /* NOTREACHED */ return 0; } inn-1.7.2/backends/map.c0100644000175100001440000000331406443103542013323 0ustar mdusers/* $Revision: 1.4 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include #include "paths.h" #include "libinn.h" #include "macros.h" typedef struct _PAIR { char First; char *Key; char *Value; } PAIR; STATIC PAIR *MAPdata; STATIC PAIR *MAPend; /* ** Free the map. */ void MAPfree() { register PAIR *mp; for (mp = MAPdata; mp < MAPend; mp++) { DISPOSE(mp->Key); DISPOSE(mp->Value); } DISPOSE(MAPdata); MAPdata = NULL; } /* ** Read the map file. */ void MAPread(name) char *name; { register FILE *F; register int i; register PAIR *mp; register char *p; char buff[BUFSIZ]; if (MAPdata != NULL) MAPfree(); /* Open file, count lines. */ if ((F = fopen(name, "r")) == NULL) { (void)fprintf(stderr, "Can't open %s, %s\n", name, strerror(errno)); exit(1); } for (i = 0; fgets(buff, sizeof buff, F) != NULL; i++) continue; mp = MAPdata = NEW(PAIR, i + 1); /* Read each line; ignore blank and comment lines. */ (void)fseek(F, (OFFSET_T)0, SEEK_SET); while (fgets(buff, sizeof buff, F) != NULL) { if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; if (buff[0] == '\0' || buff[0] == COMMENT_CHAR || (p = strchr(buff, ':')) == NULL) continue; *p++ = '\0'; mp->First = buff[0]; mp->Key = COPY(buff); mp->Value = COPY(p); mp++; } (void)fclose(F); MAPend = mp; } /* ** Look up a name in the map, return original value if not found. */ char * MAPname(p) register char *p; { register PAIR *mp; register char c; for (c = *p, mp = MAPdata; mp < MAPend; mp++) if (c == mp->First && EQ(p, mp->Key)) return mp->Value; return p; } inn-1.7.2/backends/nntpget.c0100644000175100001440000002657506443103542014243 0ustar mdusers/* $Revision: 1.10 $ ** Connect to a remote site, and get news from it to offer to our local ** server. Read list on stdin, or get it via NEWNEWS command. Writes ** list of articles still needed to stdout. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include #include "paths.h" #include "libinn.h" #include "dbz.h" #include "nntp.h" #include "macros.h" /* ** All information about a site we are connected to. */ typedef struct _SITE { char *Name; int Rfd; int Wfd; char Buffer[BUFSIZ]; char *bp; int Count; } SITE; /* ** Global variables. */ STATIC struct iovec SITEvec[2]; STATIC char SITEv1[] = "\r\n"; STATIC char READER[] = "mode reader"; STATIC unsigned long STATgot; STATIC unsigned long STAToffered; STATIC unsigned long STATsent; STATIC unsigned long STATrejected; /* ** Read a line of input, with timeout. */ STATIC BOOL SITEread(sp, start) SITE *sp; char *start; { register char *p; register char *end; struct timeval t; FDSET rmask; int i; char c; for (p = start, end = &start[NNTP_STRLEN - 1]; ; ) { if (sp->Count == 0) { /* Fill the buffer. */ Again: FD_ZERO(&rmask); FD_SET(sp->Rfd, &rmask); t.tv_sec = DEFAULT_TIMEOUT; t.tv_usec = 0; i = select(sp->Rfd + 1, &rmask, (FDSET *)NULL, (FDSET *)NULL, &t); if (i < 0) { if (errno == EINTR) goto Again; return FALSE; } if (i == 0 || !FD_ISSET(sp->Rfd, &rmask) || (sp->Count = read(sp->Rfd, sp->Buffer, sizeof sp->Buffer)) < 0) return FALSE; if (sp->Count == 0) return FALSE; sp->bp = sp->Buffer; } /* Process next character. */ sp->Count--; c = *sp->bp++; if (c == '\n') break; if (p < end) *p++ = c; } /* If last two characters are \r\n, kill the \r as well as the \n. */ if (p > start && p < end && p[-1] == '\r') p--; *p = '\0'; return TRUE; } /* ** Send a line to the server, adding \r\n. Don't need to do dot-escape ** since it's only for sending DATA to local site, and the data we got from ** the remote site already is escaped. */ STATIC BOOL SITEwrite(sp, p, i) SITE *sp; char *p; int i; { SITEvec[0].iov_base = p; SITEvec[0].iov_len = i; return xwritev(sp->Wfd, SITEvec, 2) >= 0; } STATIC SITE * SITEconnect(host) char *host; { FILE *From; FILE *To; SITE *sp; int i; /* Connect and identify ourselves. */ if (host) i = NNTPconnect(host, &From, &To, (char *)NULL); else { host = GetConfigValue(_CONF_SERVER); i = NNTPlocalopen(&From, &To, (char *)NULL); } if (i < 0) { (void)fprintf(stderr, "Can't connect to \"%s\", %s\n", host, strerror(errno)); exit(1); } if (NNTPsendpassword(host, From, To) < 0) { (void)fprintf(stderr, "Can't authenticate with %s, %s\n", host, strerror(errno)); /* Don't send quit; we want the remote to print a message. */ exit(1); } /* Build the structure. */ sp = NEW(SITE, 1); sp->Name = host; sp->Rfd = fileno(From); sp->Wfd = fileno(To); sp->bp = sp->Buffer; sp->Count = 0; return sp; } /* ** Send "quit" to a site, and get its reply. */ STATIC void SITEquit(sp) SITE *sp; { char buff[NNTP_STRLEN]; (void)SITEwrite(sp, "quit", 4); (void)SITEread(sp, buff); } STATIC BOOL HIShaveit(mesgid) char *mesgid; { register char *p; datum key; datum value; char buff[NNTP_STRLEN]; (void)strcpy(buff, mesgid); for (p = key.dptr = buff; *p; p++) if (*p == HIS_FIELDSEP || *p == '\n') *p = HIS_BADCHAR; key.dsize = p - key.dptr + 1; value = dbzfetch(key); return value.dptr != NULL ? TRUE : FALSE; } STATIC NORETURN Usage(p) char *p; { (void)fprintf(stderr, "Usage error: %s\n", p); (void)fprintf(stderr, "Usage: nntpget [ -d dist -n grps [-f file | -t time -u file]] host\n"); exit(1); } int main(ac, av) int ac; char *av[]; { char buff[NNTP_STRLEN]; char mesgid[NNTP_STRLEN]; char tbuff[SMBUF]; char temp[BUFSIZ]; STRING Groups; char *distributions; char *Since; int i; struct tm *gt; struct stat Sb; SITE *Remote; SITE *Local; FILE *F; BOOL Offer; BOOL Error; BOOL Verbose = FALSE; char *Update; char *p; /* Set defaults. */ distributions = NULL; Groups = NULL; Since = NULL; Offer = FALSE; Update = NULL; (void)umask(NEWSUMASK); /* Parse JCL. */ while ((i = getopt(ac, av, "d:f:n:t:ovu:")) != EOF) switch (i) { default: Usage("Bad flag"); /* NOTREACHED */ case 'd': distributions = optarg; break; case 'u': Update = optarg; /* FALLTHROUGH */ case 'f': if (Since) Usage("Only one -f -t or -u flag"); if (stat(optarg, &Sb) < 0) { (void)fprintf(stderr, "Can't stat \"%s\", %s\n", optarg, strerror(errno)); exit(1); } gt = gmtime(&Sb.st_mtime); (void)sprintf(tbuff, "%02d%02d%02d %02d%02d%02d GMT", gt->tm_year, gt->tm_mon + 1, gt->tm_mday, gt->tm_hour, gt->tm_min, gt->tm_sec); Since = tbuff; break; case 'n': Groups = optarg; break; case 'o': /* Open the history file. */ if (dbminit(_PATH_HISTORY) < 0) { (void)fprintf(stderr, "Can't open history, %s\n", strerror(errno)); exit(1); } Offer = TRUE; break; case 't': if (Since) Usage("Only one -t or -f flag"); Since = optarg; break; case 'v': Verbose = TRUE; break; } ac -= optind; av += optind; if (ac != 1) Usage("No host given"); /* Set up the scatter/gather vectors used by SITEwrite. */ SITEvec[1].iov_base = SITEv1; SITEvec[1].iov_len = STRLEN(SITEv1); /* Connect to the remote server. */ if ((Remote = SITEconnect(av[0])) == NULL) { (void)fprintf(stderr, "Can't connect to \"%s\", %s\n", av[0], strerror(errno)); exit(1); } if (!SITEwrite(Remote, READER, (int)STRLEN(READER)) || !SITEread(Remote, buff)) { (void)fprintf(stderr, "Can't start reading, %s\n", strerror(errno)); exit(1); } if (Since == NULL) { F = stdin; temp[0] = '\0'; if (distributions || Groups) Usage("No -d or -n when reading stdin"); } else { /* Ask the server for a list of what's new. */ if (Groups == NULL) Groups = "*"; if (distributions) (void)sprintf(buff, "NEWNEWS %s %s <%s>", Groups, Since, distributions); else (void)sprintf(buff, "NEWNEWS %s %s", Groups, Since); if (!SITEwrite(Remote, buff, (int)strlen(buff)) || !SITEread(Remote, buff)) { (void)fprintf(stderr, "Can't start list, %s\n", strerror(errno)); exit(1); } if (buff[0] != NNTP_CLASS_OK) { (void)fprintf(stderr, "Protocol error from \"%s\", got \"%s\"\n", Remote->Name, buff); SITEquit(Remote); exit(1); } /* Create a temporary file. */ p = getenv("TMPDIR"); (void)sprintf(temp, "%s/nntpgetXXXXXX", p ? p : _PATH_TMP); (void)mktemp(temp); if ((F = fopen(temp, "w+")) == NULL) { (void)fprintf(stderr, "Can't open \"%s\", %s\n", temp, strerror(errno)); exit(1); } /* Read and store the Message-ID list. */ for ( ; ; ) { if (!SITEread(Remote, buff)) { (void)fprintf(stderr, "Can't read from \"%s\", %s\n", Remote->Name, strerror(errno)); (void)fclose(F); SITEquit(Remote); exit(1); } if (EQ(buff, ".")) break; if (Offer && HIShaveit(buff)) continue; if (fprintf(F, "%s\n", buff) == EOF || ferror(F)) { (void)fprintf(stderr, "Can't write \"%s\", %s\n", temp, strerror(errno)); (void)fclose(F); SITEquit(Remote); exit(1); } } if (fflush(F) == EOF) { (void)fprintf(stderr, "Can't flush \"%s\", %s\n", temp, strerror(errno)); (void)fclose(F); SITEquit(Remote); exit(1); } (void)fseek(F, (OFFSET_T)0, SEEK_SET); } if (Offer) { /* Connect to the local server. */ if ((Local = SITEconnect((char *)NULL)) == NULL) { (void)fprintf(stderr, "Can't connect to local server, %s\n", strerror(errno)); (void)fclose(F); exit(1); } } /* Loop through the list of Message-ID's. */ while (fgets(mesgid, sizeof mesgid, F) != NULL) { STATgot++; if ((p = strchr(mesgid, '\n')) != NULL) *p = '\0'; if (Offer) { /* See if the local server wants it. */ STAToffered++; (void)sprintf(buff, "ihave %s", mesgid); if (!SITEwrite(Local, buff, (int)strlen(buff)) || !SITEread(Local, buff)) { (void)fprintf(stderr, "Can't offer \"%s\", %s\n.", mesgid, strerror(errno)); break; } if (atoi(buff) != NNTP_SENDIT_VAL) continue; } /* Try to get the article. */ (void)sprintf(buff, "article %s", mesgid); if (!SITEwrite(Remote, buff, (int)strlen(buff)) || !SITEread(Remote, buff)) { (void)fprintf(stderr, "Can't get \"%s\", %s\n", mesgid, strerror(errno)); (void)printf("%s\n", mesgid); break; } if (atoi(buff) != NNTP_ARTICLE_FOLLOWS_VAL) { if (Offer) { (void)SITEwrite(Local, ".", 1); if (!SITEread(Local, buff)) { (void)fprintf(stderr, "No reply after \"%s\", %s\n", mesgid, strerror(errno)); break; } } continue; } if (Verbose) (void)fprintf(stderr, "%s...\n", mesgid); /* Read each line in the article and write it. */ for (Error = FALSE; ; ) { if (!SITEread(Remote, buff)) { (void)fprintf(stderr, "Can't read \"%s\" from \"%s\", %s\n", mesgid, Remote->Name, strerror(errno)); Error = TRUE; break; } if (Offer) { if (!SITEwrite(Local, buff, (int)strlen(buff))) { (void)fprintf(stderr, "Can't send \"%s\", %s\n", mesgid, strerror(errno)); Error = TRUE; break; } } else (void)printf("%s\n", buff); if (EQ(buff, ".")) break; } if (Error) { (void)printf("%s\n", mesgid); break; } STATsent++; /* How did the local server respond? */ if (Offer) { if (!SITEread(Local, buff)) { (void)fprintf(stderr, "No reply after \"%s\", %s\n", mesgid, strerror(errno)); (void)printf("%s\n", mesgid); break; } i = atoi(buff); if (i == NNTP_TOOKIT_VAL) continue; if (i == NNTP_RESENDIT_VAL) { (void)printf("%s\n", mesgid); break; } (void)fprintf(stderr, "%s to \"%s\"\n", buff, mesgid); STATrejected++; } } /* Write rest of the list, close the input. */ if (!feof(F)) while (fgets(mesgid, sizeof mesgid, F) != NULL) { if ((p = strchr(mesgid, '\n')) != NULL) *p = '\0'; (void)printf("%s\n", mesgid); STATgot++; } (void)fclose(F); /* Remove our temp file. */ if (temp[0] && unlink(temp) < 0) (void)fprintf(stderr, "Can't remove \"%s\", %s\n", temp, strerror(errno)); /* All done. */ SITEquit(Remote); if (Offer) SITEquit(Local); /* Update timestamp file? */ if (Update) { if ((F = fopen(Update, "w")) == NULL) { (void)fprintf(stderr, "Can't update %s, %s\n", Update, strerror(errno)); exit(1); } (void)fprintf(F, "got %ld offered %ld sent %ld rejected %ld\n", STATgot, STAToffered, STATsent, STATrejected); if (ferror(F) || fclose(F) == EOF) { (void)fprintf(stderr, "Can't update %s, %s\n", Update, strerror(errno)); exit(1); } } exit(0); /* NOTREACHED */ } inn-1.7.2/backends/shlock.c0100644000175100001440000001056306443103542014035 0ustar mdusers/* $Revision: 1.8 $ ** ** Produce reliable locks for shell scripts, by Peter Honeyman as told ** to Rich $alz. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include STATIC BOOL BinaryLock; STATIC char CANTUNLINK[] = "Can't unlink \"%s\", %s\n"; STATIC char CANTOPEN[] = "Can't open \"%s\", %s\n"; /* ** See if the process named in an existing lock still exists by ** sending it a null signal. */ STATIC BOOL ValidLock(name, JustChecking) char *name; BOOL JustChecking; { register int fd; register int i; PID_T pid; char buff[BUFSIZ]; /* Open the file. */ if ((fd = open(name, O_RDONLY)) < 0) { if (JustChecking) return FALSE; (void)fprintf(stderr, CANTOPEN, name, strerror(errno)); return TRUE; } /* Read the PID that is written there. */ if (BinaryLock) { if (read(fd, (char *)&pid, sizeof pid) != sizeof pid) { (void)close(fd); return FALSE; } } else { if ((i = read(fd, buff, sizeof buff - 1)) <= 0) { (void)close(fd); return FALSE; } buff[i] = '\0'; pid = (PID_T) atol(buff); } (void)close(fd); if (pid <= 0) return FALSE; /* Send the signal. */ if (kill(pid, 0) < 0 && errno == ESRCH) return FALSE; /* Either the kill worked, or we're optimistic about the error code. */ return TRUE; } /* ** Unlink a file, print a message on error, and exit. */ STATIC NORETURN UnlinkAndExit(name, x) char *name; int x; { if (unlink(name) < 0) (void)fprintf(stderr, CANTUNLINK, name, strerror(errno)); exit(x); } /* ** Print a usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage: shlock [-u|-b] -f file -p pid\n"); exit(1); /* NOTREACHED */ } int main(ac, av) int ac; char *av[]; { register int i; register char *p; register int fd; char tmp[BUFSIZ]; char buff[BUFSIZ]; char *name; PID_T pid; BOOL ok; BOOL JustChecking; /* Set defaults. */ pid = 0; name = NULL; JustChecking = FALSE; (void)umask(NEWSUMASK); /* Parse JCL. */ while ((i = getopt(ac, av, "bcup:f:")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'b': case 'u': BinaryLock = TRUE; break; case 'c': JustChecking = TRUE; break; case 'p': pid = (PID_T) atol(optarg); break; case 'f': name = optarg; break; } ac -= optind; av += optind; if (ac || pid == 0 || name == NULL) Usage(); /* Create the temp file in the same directory as the destination. */ if ((p = strrchr(name, '/')) != NULL) { *p = '\0'; (void)sprintf(tmp, "%s/shlock%ld", name, (long)getpid()); *p = '/'; } else (void)sprintf(tmp, "shlock%ld", (long)getpid()); /* Loop until we can open the file. */ while ((fd = open(tmp, O_RDWR | O_CREAT | O_EXCL, 0644)) < 0) switch (errno) { default: /* Unknown error -- give up. */ (void)fprintf(stderr, CANTOPEN, tmp, strerror(errno)); exit(1); case EEXIST: /* If we can remove the old temporary, retry the open. */ if (unlink(tmp) < 0) { (void)fprintf(stderr, CANTUNLINK, tmp, strerror(errno)); exit(1); } break; } /* Write the process ID. */ if (BinaryLock) ok = write(fd, (POINTER)&pid, (SIZE_T)sizeof pid) == sizeof pid; else { (void)sprintf(buff, "%ld\n", (long) pid); i = strlen(buff); ok = write(fd, (POINTER)buff, (SIZE_T)i) == i; } if (!ok) { (void)fprintf(stderr, "Can't write PID to \"%s\", %s\n", tmp, strerror(errno)); (void)close(fd); UnlinkAndExit(tmp, 1); } (void)close(fd); /* Handle the "-c" flag. */ if (JustChecking) { if (ValidLock(name, TRUE)) UnlinkAndExit(tmp, 1); UnlinkAndExit(tmp, 0); } /* Try to link the temporary to the lockfile. */ while (link(tmp, name) < 0) switch (errno) { default: /* Unknown error -- give up. */ (void)fprintf(stderr, "Can't link \"%s\" to \"%s\", %s\n", tmp, name, strerror(errno)); UnlinkAndExit(tmp, 1); /* NOTREACHED */ case EEXIST: /* File exists; if lock is valid, give up. */ if (ValidLock(name, FALSE)) UnlinkAndExit(tmp, 1); if (unlink(name) < 0) { (void)fprintf(stderr, CANTUNLINK, name, strerror(errno)); UnlinkAndExit(tmp, 1); } } UnlinkAndExit(tmp, 0); /* NOTREACHED */ } inn-1.7.2/backends/actsyncd.sh0100644000175100001440000001712006443103542014546 0ustar mdusers#!/bin/sh # @(#) $Id: actsyncd.sh,v 1.12 1996/11/19 13:51:00 brister Exp $ # @(#) Under RCS control in /usr/local/news/src/inn/local/RCS/actsyncd.sh,v # # actsyncd - actsync daemon # # usage: # actsyncd [-x] config_file [debug_level [debug_outfmt]] # # -x xexec instead of reload # config_file name of file used to determine how to run actsync # debug_level force no action and use -v debug_level # debug_outfmt change -o a1 output to -o debug_outfmt for debug # By: Landon Curt Noll chongo@toad.com (chongo was here /\../\) # # Copyright (c) Landon Curt Noll, 1993. # All rights reserved. # # Permission to use and modify is hereby granted so long as this # notice remains. Use at your own risk. No warranty is implied. # preset vars # # =()<. @<_PATH_SHELLVARS>@>()= . /var/news/etc/innshellvars # Our lock file LOCK=${LOCKS}/LOCK.actsyncd # where actsync is located ACTSYNC=${NEWSBIN}/actsync # timeout for ctlinnd TIMEOUT=120 # exit value of actsync if unable to get an active file NOSYNC=127 # where ctlinnd lives CTLINND="${NEWSBIN}/ctlinnd" # by default we xexec instead of reloading XEXEC= export XEXEC # parse args # if [ $# -gt 1 ]; then if [ X"-x" = X"$1" ]; then XEXEC=true shift elif [ X"-r" = X"$1" ]; then # backward compatibility XEXEC= shift fi fi case $# in 1) cfg="$1"; DEBUG=; DEBUG_FMT=; ;; 2) cfg="$1"; DEBUG="$2"; DEBUG_FMT=; ;; 3) cfg="$1"; DEBUG="$2"; DEBUG_FMT="$3"; ;; *) echo "usage: $0 [-x] config_file [debug_level [debug_outfmt]]" 1>&2; exit 1 ;; esac if [ ! -s "$cfg" ]; then echo "$0: config_file not found or empty: $ign" 1>&2 exit 2 fi # parse config_file # host="`sed -n -e 's/#.*//' -e 's/^host=[ ]*//p' $cfg | tail -1`" if [ -z "$host" ]; then echo "$0: no host specified in $cfg" 1>&2 exit 3 fi flags="`sed -n -e 's/#.*//' -e 's/^flags=[ ]*//p' $cfg | tail -1`" if [ -z "$flags" ]; then echo "$0: no flags specified in $cfg" 1>&2 exit 4 fi ign="`sed -n -e 's/#.*//' -e 's/^ignore_file=[ ]*//p' $cfg | tail -1`" if [ -z "$ign" ]; then echo "$0: no ignore file specified in $cfg" 1>&2 exit 5 fi spool="`sed -n -e 's/#.*//' -e 's/^spool=[ ]*//p' $cfg | tail -1`" if [ -z "$spool" ]; then echo "$0: no spool directory specified in $cfg" 1>&2 exit 6 fi if [ ! -s "$ign" ]; then echo "$0: ignore_file not found or empty: $ign" 1>&2 exit 7 fi # force -S spool_dir mode (overrides any -S arg in the command line) # flags="$flags -S $spool" # force -o a1 mode (overrides any -o argument in the command line) # if [ -z "$DEBUG" ]; then # standard actsyncd output mode flags="$flags -o a1" # DEBUG processing, ig debug_level was given # else # force -v level as needed flags="$flags -v $DEBUG" # force -o level but reject -o x modes if [ ! -z "$DEBUG_FMT" ]; then case "$DEBUG_FMT" in x*) echo "$0: do not use any of the -o x debug_outfmt modes!" 1>&2; exit 8 ;; *) flags="$flags -o $DEBUG_FMT" ;; esac fi # execute actsync directly echo "DEBUG: will execute $ACTSYNC -i $ign $flags $host" 1>&2 eval "$ACTSYNC -i $ign $flags $host" status="$?" echo "DEBUG: exit status $status" 1>&2 exit "$status" fi # Lock out others # trap 'rm -f ${LOCK}; exit 1' 0 1 2 3 15 shlock -p $$ -f ${LOCK} || { echo "$0: Locked by `cat ${LOCK}`" 1>&2 exit 9 } # setup # activenew="${NEWSLIB}/active.new.$$" out="${TMPDIR}/.sync.$$" trap "rm -f $activenew $out ${LOCK}; exit" 0 1 2 3 15 rm -f "$out" touch "$out" chmod 0644 "$out" # try to sync # # Try to sync off of the host. If unable to connect/sync then retry # up to 9 more times waiting 6 minutes between each try. # echo "=-= `date` for $host" >>$out 2>&1 for loop in 1 2 3 4 5 6 7 8 9 10; do # pause the server # echo "=-= `date` for $host pause innd" >>$out 2>&1 ${CTLINND} pause "actsyncd" >>$out if [ $? -ne 0 ]; then echo "FATAL: `date` for $host cannot pause innd" >>$out sed -e 's/^/ /' < "$out" exit 10 fi # form the new active file # echo "rm -f $activenew" >>$out rm -f "$activenew" >>$out 2>&1 echo "touch $activenew" >>$out touch "$activenew" >>$out 2>&1 echo "chmod 0644 $activenew" >>$out chmod 0644 "$activenew" >>$out 2>&1 echo "$ACTSYNC -i $ign $flags $host" >>$out eval "$ACTSYNC -i $ign $flags $host >$activenew 2>>$out" status=$? if [ "$status" -ne "$NOSYNC" ]; then # detect bad status # if [ "$status" -ne 0 ]; then echo "FATAL: `date` for $host exit $status" >>$out ${CTLINND} go "actsyncd" >>$out sed -e 's/^/ /' < "$out" exit "$status" fi # detect empty output # if [ ! -s "$activenew" ]; then echo "FATAL: `date` for $host empty or missing $activenew" >>$out ${CTLINND} go "actsyncd" >>$out sed -e 's/^/ /' < "$out" exit 11 fi # form active.times lines for new newsgroups # # determine seconds since the Epoch (1 Jan 1970 0:00:00 UTC) EP_FMT='X%S + \( X%M \* 60 \) + \( X%H \* 3600 \) + \( X%j \* 86400 \) + \( \( X%y - 70 \) \* 31536000 \) + \( \( \( X%y - 73 \) / 4 \) \* 86400 \)' NOW=`eval expr \`TZ=UTC date "+$EP_FMT" | sed -e 's/X00* /0 /' -e 's/X0*/0/g'\`` if [ -z "${NOW}" ]; then echo "FATAL: `date` for $host secs output is empty" >>$out ${CTLINND} go "actsyncd" >>$out sed -e 's/^/ /' < "$out" exit 12 fi echo "=-= `date` for $host, forming active.times" >>$out eval "$ACTSYNC -i $ign $flags -o c -v 0 -q 12 ${ACTIVE} $activenew 2>>$out" | \ grep '^ctlinnd newgroup ' | \ awk '{print $3, NOW, "actsyncd";}' NOW=$NOW - >> ${ACTIVETIMES} # move the active file into place # wc "${ACTIVE}.old" "${ACTIVE}" "$activenew" | sed -e 's/^ *//' >>$out echo "rm -f ${ACTIVE}.old" >>$out rm -f "${ACTIVE}.old" >>$out 2>&1 echo "ln ${ACTIVE} ${ACTIVE}.old" >>$out ln "${ACTIVE}" "${ACTIVE}.old" >>$out 2>&1 echo "mv -f $activenew ${ACTIVE}" >>$out mv -f "$activenew" "${ACTIVE}" >>$out 2>&1 # reload the new active or reexec the server if needed # if [ -z "$XEXEC" ]; then # reload the modified active file # echo "=-= `date` for $host, reload active" >>$out ${CTLINND} reload active actsyncd >>$out 2>&1 if [ $? -ne 0 ]; then echo "FATAL: `date` for $host cannot reload active" >>$out sed -e 's/^/ /' < "$out" exit 13 fi # active file has been updated successfully, resume server # echo "=-= `date` for $host, go innd" >>$out ${CTLINND} go "actsyncd" >>$out if [ $? -ne 0 ]; then echo "FATAL: `date` for $host cannot go innd" >>$out sed -e 's/^/ /' < "$out" exit 14 fi else # just re-exec the server and let the new server read new active # echo "=-= `date` for $host, xexec" >>$out ${CTLINND} xexec '' >>$out 2>&1 if [ $? -ne 0 ]; then echo "FATAL: `date` for $host cannot xexec, server dead" >>$out sed -e 's/^/ /' < "$out" exit 15 fi # see if the server has reloaded # sleep 30 ${CTLINND} mode >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "FATAL: `date` for $host did not resume after xexec" >>$out sed -e 's/^/ /' < "$out" exit 16 fi fi # normal exit - all done # echo "=-= `date` for $host, end" >>$out sed -e 's/^/ /' < "$out" exit "$status" fi # failed to form the active file, resume server # echo "=-= `date` for $host failed to connect/sync, retrying" >>$out ${CTLINND} go "actsyncd" >>$out if [ $? -ne 0 ]; then echo "FATAL: `date` for $host cannot go innd" >>$out sed -e 's/^/ /' < "$out" exit 17 fi # wait 6 minutes # sleep 360 done # give up # echo "FATAL: `date` for $host failed to connect/sync 10 times" >>$out 2>&1 sed -e 's/^/ /' < "$out" exit "$status" inn-1.7.2/backends/sendxbatches.sh0100644000175100001440000000160706443103542015414 0ustar mdusers#!/bin/sh # $Id: sendxbatches.sh,v 1.2 1996/09/06 06:57:41 brister Exp $ # By petri@ibr.cs.tu-bs.de with mods by libove@jerry.alf.dec.com # # Script to send xbatches for a site, wrapped around innxbatch # Invocation: sendxbatches.sh ... # ## TODO: - we should check the amount of queued batches for the site, ## to prevent disk overflow due to unreachable sites. if [ $# -lt 3 ] then echo "usage: $0 " exit 1 fi ## =()<. @<_PATH_SHELLVARS>@>()= . /var/news/etc/innshellvars LOCK=${LOCKS}/LOCK.sendxbatches shlock -p $$ -f ${LOCK} if [ $? -ne 0 ] then echo Locked by `cat ${LOCK}` exit 1 fi trap 'rm -f ${LOCK} ; exit 1' 1 2 3 15 site="$1" host="$2" shift; shift ctlinnd -s flush "$site" if [ $? -ne 0 ] then echo "ctlinnd flush $site failed." exit 1 fi sleep 5 $NEWSBIN/innxbatch -D -v "$host" $* inn-1.7.2/backends/filechan.c0100644000175100001440000000610506443103542014320 0ustar mdusers/* $Revision: 1.13 $ ** ** An InterNetNews channel process that splits a funnel entry into ** separate files. Originally from Robert Elz . */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #include #include "paths.h" #include "libinn.h" #include "macros.h" extern void MAPread(); extern char *MAPname(); int main(ac, av) int ac; char *av[]; { char buff[2048]; register char *p; register char *next; register int i; register int fd; int Fields; STRING Directory; BOOL Map; FILE *F; struct stat Sb; UID_T uid; GID_T gid; UID_T myuid; /* Set defaults. */ Fields = 1; Directory = _PATH_BATCHDIR; Map = FALSE; myuid = geteuid(); (void)umask(NEWSUMASK); /* Parse JCL. */ while ((i = getopt(ac, av, "d:f:m:p:")) != EOF) switch (i) { default: (void)fprintf(stderr, "Usage error.\n"); exit(1); case 'd': Directory = optarg; break; case 'f': Fields = atoi(optarg); break; case 'm': Map = TRUE; MAPread(optarg); break; case 'p': if ((F = fopen(optarg, "w")) == NULL) { (void)fprintf(stderr, "filechan cant fopen %s %s\n", optarg, strerror(errno)); exit(1); } (void)fprintf(F, "%ld\n", (long)getpid()); if (ferror(F) || fclose(F) == EOF) { (void)fprintf(stderr, "filechan cant fclose %s %s\n", optarg, strerror(errno)); exit(1); } break; } /* Move, and get owner of current directory. */ if (chdir(Directory) < 0) { (void)fprintf(stderr, "Can't chdir to %s, %s\n", Directory, strerror(errno)); exit(1); } if (stat(".", &Sb) < 0) { (void)fprintf(stderr, "Can't stat %s, %s\n", Directory, strerror(errno)); exit(1); } uid = Sb.st_uid; gid = Sb.st_gid; /* Read input. */ while (fgets(buff, sizeof buff, stdin) != NULL) { if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; /* Skip the right number of leading fields. */ for (i = Fields, p = buff; *p; p++) if (*p == ' ' && --i <= 0) break; if (*p == '\0') /* Nothing to write. Probably shouldn't happen. */ continue; /* Add a newline, get the length of all leading fields. */ *p++ = '\n'; i = p - buff; /* Rest of the line is space-separated list of filenames. */ for (; *p; p = next) { /* Skip whitespace, get next word. */ while (*p == ' ') p++; for (next = p; *next && *next != ' '; next++) continue; if (*next) *next++ = '\0'; if (Map) p = MAPname(p); fd = open(p, O_CREAT | O_WRONLY | O_APPEND, BATCHFILE_MODE); if (fd >= 0) { /* Try to lock it and set the ownership right. */ (void)LockFile(fd, TRUE); if (myuid == 0 && uid != 0) (void)chown(p, uid, gid); /* Just in case, seek to the end. */ (void)lseek(fd, (OFFSET_T) 0, SEEK_END); errno = 0; if (write(fd, (POINTER)buff, (SIZE_T)i) != i) { perror("write"); exit(1); } (void)close(fd); } } } exit(0); /* NOTREACHED */ } inn-1.7.2/backends/cvtbatch.c0100644000175100001440000000606606443103542014353 0ustar mdusers/* $Revision: 1.4 $ ** ** Read file list on standard input and spew out batchfiles. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include "paths.h" #include "qio.h" #include "libinn.h" #include "macros.h" /* ** Print a usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "convertbatch usage_error.\n"); exit(1); } int main(ac, av) int ac; char *av[]; { static char SPOOL[] = _PATH_SPOOL; static char HDR[] = "Message-ID:"; int i; register QIOSTATE *qp; register QIOSTATE *artp; register char *line; register char *text; register char *format; register char *p; register BOOL Dirty; struct stat Sb; /* Parse JCL. */ format = "nm"; while ((i = getopt(ac, av, "w:")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'w': for (p = format = optarg; *p; p++) { switch (*p) { case FEED_BYTESIZE: case FEED_FULLNAME: case FEED_MESSAGEID: case FEED_NAME: continue; } (void)fprintf(stderr, "Ignoring \"%c\" in -w flag.\n", *p); } } ac -= optind; av += optind; if (ac) Usage(); if (chdir(SPOOL) < 0) { (void)fprintf(stderr, "batchconvert cant chdir %s, %s\n", SPOOL, strerror(errno)); exit(1); } /* Loop over all input. */ qp = QIOfdopen((int)fileno(stdin), 0); while ((line = QIOread(qp)) != NULL) { if (line[0] == '/' && line[STRLEN(SPOOL)] == '/' && EQn(line, SPOOL, STRLEN(SPOOL))) line += STRLEN(SPOOL) + 1; for (p = line; *p; p++) if (ISWHITE(*p)) { *p = '\0'; break; } if ((artp = QIOopen(line, 0)) == NULL) /* Non-existant article. */ continue; /* Read article, looking for Message-ID header. */ while ((text = QIOread(artp)) != NULL) { if (*text == '\0') break; if (*text == 'M' && EQn(text, HDR, STRLEN(HDR))) break; if ((*text == 'M' || *text == 'm') && caseEQn(text, HDR, STRLEN(HDR))) break; } if (text == NULL || *text == '\0') { QIOclose(artp); continue; } /* Skip to value of header. */ for (text += STRLEN(HDR); ISWHITE(*text); text++) continue; if (*text == '\0') { QIOclose(artp); continue; } /* Write the desired info. */ for (Dirty = FALSE, p = format; *p; p++) { switch (*p) { default: continue; case FEED_BYTESIZE: if (Dirty) (void)putchar(' '); if (stat(line, &Sb) < 0) (void)printf("0"); else (void)printf("%ld", Sb.st_size); break; case FEED_FULLNAME: if (Dirty) (void)putchar(' '); (void)printf("%s/%s", SPOOL, line); break; case FEED_MESSAGEID: if (Dirty) (void)putchar(' '); (void)printf("%s", text); break; case FEED_NAME: if (Dirty) (void)putchar(' '); (void)printf("%s", line); break; } Dirty = TRUE; } if (Dirty) (void)putchar('\n'); QIOclose(artp); } exit(0); /* NOTREACHED */ } inn-1.7.2/backends/batcher.c0100644000175100001440000002714106443103542014162 0ustar mdusers/* $Revision: 1.19 $ ** ** Read batchfiles on standard input and spew out batches. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include "paths.h" #include "libinn.h" #include "logging.h" #include "macros.h" /* ** Global variables. */ STATIC BOOL BATCHopen; STATIC BOOL STATprint; STATIC double STATbegin; STATIC double STATend; STATIC char *Host; STATIC char *InitialString; STATIC char *Input; STATIC char *Processor; STATIC int ArtsInBatch; STATIC int ArtsWritten; STATIC int BATCHcount; STATIC int MaxBatches; STATIC int BATCHstatus; STATIC long BytesInBatch = 60 * 1024; STATIC long BytesWritten; STATIC long MaxArts; STATIC long MaxBytes; STATIC SIGVAR GotInterrupt; STATIC STRING Separator = "#! rnews %ld"; /* ** Start a batch process. */ STATIC FILE * BATCHstart() { FILE *F; char buff[SMBUF]; if (Processor && *Processor) { (void)sprintf(buff, Processor, Host); F = popen(buff, "w"); if (F == NULL) return NULL; } else F = stdout; BATCHopen = TRUE; BATCHcount++; return F; } /* ** Close a batch, return exit status. */ STATIC int BATCHclose(F) FILE *F; { BATCHopen = FALSE; if (F == stdout) return fflush(stdout) == EOF ? 1 : 0; return pclose(F); } /* ** Update the batch file and exit. */ STATIC NORETURN RequeueAndExit(Cookie, line, BytesInArt) OFFSET_T Cookie; char *line; long BytesInArt; { static char LINE1[] = "batcher %s times user %.3f system %.3f elapsed %.3f"; static char LINE2[] ="batcher %s stats batches %d articles %d bytes %ld"; static char NOWRITE[] = "batcher %s cant write spool %s\n"; static char BATCHDIR[] = _PATH_BATCHDIR; char temp[BUFSIZ]; char buff[BUFSIZ]; int i; FILE *F; TIMEINFO Now; double usertime; double systime; /* Do statistics. */ (void)GetTimeInfo(&Now); STATend = TIMEINFOasDOUBLE(Now); if (GetResourceUsage(&usertime, &systime) < 0) { usertime = 0; systime = 0; } if (STATprint) { (void)printf(LINE1, Host, usertime, systime, STATend - STATbegin); (void)printf("\n"); (void)printf(LINE2, Host, BATCHcount, ArtsWritten, BytesWritten); (void)printf("\n"); } (void)openlog("batcher", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG); syslog(L_NOTICE, LINE1, Host, usertime, systime, STATend - STATbegin); syslog(L_NOTICE, LINE2, Host, BATCHcount, ArtsWritten, BytesWritten); /* Last batch exit okay? */ if (BATCHstatus == 0) { if (feof(stdin)) { /* Yes, and we're all done -- remove input and exit. */ (void)fclose(stdin); if (Input) (void)unlink(Input); exit(0); } /* Don't seek back -- batch was fine. */ Cookie = -1; } /* Make an appropriate spool file. */ if (Input == NULL) (void)sprintf(temp, "%s/%s", BATCHDIR, Host); else (void)sprintf(temp, "%s.bch", Input); if ((F = xfopena(temp)) == NULL) { (void)fprintf(stderr, "batcher %s cant open %s %s\n", Host, temp, strerror(errno)); exit(1); } /* If we can back up to where the batch started, do so. */ i = 0; if (Cookie != -1 && fseek(stdin, Cookie, SEEK_SET) == -1) { (void)fprintf(stderr, "batcher %s cant seek %s\n", Host, strerror(errno)); i = 1; } /* Write the line we had; if the fseek worked, this will be an * extra line, but that's okay. */ if (line && fprintf(F, "%s %ld\n", line, BytesInArt) == EOF) { (void)fprintf(stderr, NOWRITE, Host, strerror(errno)); i = 1; } /* Write rest of stdin to spool. */ while (fgets(buff, sizeof buff, stdin) != NULL) if (fputs(buff, F) == EOF) { (void)fprintf(stderr, NOWRITE, Host, strerror(errno)); i = 1; break; } if (fclose(F) == EOF) { (void)fprintf(stderr, "batcher %s cant close spool %s\n", Host, strerror(errno)); i = 1; } /* If we had a named input file, try to rename the spool. */ if (Input != NULL && rename(temp, Input) < 0) { (void)fprintf(stderr, "batcher %s cant rename spool %s\n", Host, strerror(errno)); i = 1; } exit(i); /* NOTREACHED */ } /* ** Mark that we got interrupted. */ STATIC SIGHANDLER CATCHinterrupt(s) int s; { GotInterrupt = TRUE; /* Let two interrupts kill us. */ (void)signal(s, SIG_DFL); } /* ** Print a usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "batcher usage_error.\n"); exit(1); } int main(ac, av) int ac; char *av[]; { static char SKIPPING[] = "batcher %s skipping \"%.40s...\" %s\n"; static char SPOOL[] = _PATH_SPOOL; static char BATCHDIR[] = _PATH_BATCHDIR; BOOL Redirect; FILE *F; STRING AltSpool; TIMEINFO Now; char *p; char *data; char line[BUFSIZ]; char buff[BUFSIZ]; long BytesInArt; long BytesInCB; OFFSET_T Cookie; SIZE_T datasize; int i; int artfd; int ArtsInCB; int length; struct stat Sb; /* Set defaults. */ AltSpool = NULL; Redirect = TRUE; (void)umask(NEWSUMASK); /* Parse JCL. */ while ((i = getopt(ac, av, "a:A:b:B:i:N:p:rs:S:v")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'a': ArtsInBatch = atoi(optarg); break; case 'A': MaxArts = atol(optarg); break; case 'b': BytesInBatch = atol(optarg); break; case 'B': MaxBytes = atol(optarg); break; case 'i': InitialString = optarg; break; case 'N': MaxBatches = atoi(optarg); break; case 'p': Processor = optarg; break; case 'r': Redirect = FALSE; break; case 's': Separator = optarg; break; case 'S': AltSpool = optarg; break; case 'v': STATprint = TRUE; break; } if (MaxArts && ArtsInBatch == 0) ArtsInBatch = MaxArts; if (MaxBytes && BytesInBatch == 0) BytesInBatch = MaxBytes; /* Parse arguments. */ ac -= optind; av += optind; if (ac != 1 && ac != 2) Usage(); Host = av[0]; if ((Input = av[1]) != NULL) { if (Input[0] != '/') { Input = NEW(char, STRLEN(BATCHDIR) + 1 + strlen(av[1]) + 1); (void)sprintf(Input, "%s/%s", BATCHDIR, av[1]); } if (freopen(Input, "r", stdin) == NULL) { (void)fprintf(stderr, "batcher %s cant open %s %s\n", Host, Input, strerror(errno)); exit(1); } } if (Redirect) (void)freopen(_PATH_ERRLOG, "a", stderr); /* Go to where the articles are. */ if (chdir(SPOOL) < 0) { (void)fprintf(stderr, "batcher %s cant cd %s %s\n", Host, SPOOL, strerror(errno)); exit(1); } /* Set initial counters, etc. */ datasize = 8 * 1024; data = NEW(char, datasize); BytesInCB = 0; ArtsInCB = 0; Cookie = -1; GotInterrupt = FALSE; (void)signal(SIGHUP, CATCHinterrupt); (void)signal(SIGINT, CATCHinterrupt); (void)signal(SIGTERM, CATCHinterrupt); /* (void)signal(SIGPIPE, CATCHinterrupt); */ (void)GetTimeInfo(&Now); STATbegin = TIMEINFOasDOUBLE(Now); F = NULL; while (fgets(line, sizeof line, stdin) != NULL) { /* Record line length in case we do an ftell. Not portable to * systems with non-Unix file formats. */ length = strlen(line); /* Get lines like "name size" */ if ((p = strchr(line, '\n')) == NULL) { (void)fprintf(stderr, SKIPPING, Host, line, "too long"); continue; } *p = '\0'; if (line[0] == '\0' || line[0] == COMMENT_CHAR) continue; if ((p = strchr(line, ' ')) != NULL) { *p++ = '\0'; /* Try to be forgiving of bad input. */ BytesInArt = CTYPE(isdigit, *p) ? atol(p) : -1; } else BytesInArt = -1; /* Strip of leading spool pathname. */ if (line[0] == '/' && line[STRLEN(SPOOL)] == '/' && EQn(line, SPOOL, STRLEN(SPOOL))) p = line + STRLEN(SPOOL) + 1; else p = line; /* Open the file. */ if ((artfd = open(p, O_RDONLY)) < 0) { if (errno != ENOENT) (void)fprintf(stderr, SKIPPING, Host, p, strerror(errno)); if (AltSpool == NULL) continue; (void)sprintf(buff, "%s/%s", AltSpool, p); if ((artfd = open(buff, O_RDONLY)) < 0) { if (errno != ENOENT) (void)fprintf(stderr, SKIPPING, Host, buff, strerror(errno)); continue; } } /* If we need to, get its size. */ if (BytesInArt <= 0) { if (fstat(artfd, &Sb) < 0) { (void)fprintf(stderr, SKIPPING, Host, line, strerror(errno)); (void)close(artfd); continue; } if (!S_ISREG(Sb.st_mode)) { (void)fprintf(stderr, SKIPPING, Host, line, "not a file"); (void)close(artfd); continue; } BytesInArt = Sb.st_size; } /* Have an open article, do we need to open a batch? This code * is here (rather then up before the while loop) so that we * can avoid sending an empty batch. The goto makes the code * a bit more clear. */ if (F == NULL) { if (GotInterrupt) { (void)close(artfd); RequeueAndExit(Cookie, (char *)NULL, 0L); } if ((F = BATCHstart()) == NULL) { (void)fprintf(stderr, "batcher %s cant startbatch %d %s\n", Host, BATCHcount, strerror(errno)); (void)close(artfd); break; } if (InitialString && *InitialString) { (void)fprintf(F, "%s\n", InitialString); BytesInCB += strlen(InitialString) + 1; BytesWritten += strlen(InitialString) + 1; } Cookie = ftell(stdin) - length; goto SendIt; } /* We're writing a batch, see if adding the current article * would exceed the limits. */ if ((ArtsInBatch > 0 && ArtsInCB + 1 >= ArtsInBatch) || (BytesInBatch > 0 && BytesInCB + BytesInArt >= BytesInBatch)) { if ((BATCHstatus = BATCHclose(F)) != 0) { if (BATCHstatus == -1) (void)fprintf(stderr, "batcher %s cant closebatch %d %s\n", Host, BATCHcount, strerror(errno)); else (void)fprintf(stderr, "batcher %s batch %d exit %d\n", Host, BATCHcount, BATCHstatus); (void)close(artfd); break; } ArtsInCB = 0; BytesInCB = 0; /* See if we can start a new batch. */ if ((MaxBatches > 0 && BATCHcount >= MaxBatches) || (MaxBytes > 0 && BytesWritten + BytesInArt >= MaxBytes) || (MaxArts > 0 && ArtsWritten + 1 >= MaxArts)) { (void)close(artfd); break; } if (GotInterrupt) { (void)close(artfd); RequeueAndExit(Cookie, line, BytesInArt); } if ((F = BATCHstart()) == NULL) { (void)fprintf(stderr, "batcher %s cant startbatch %d %s\n", Host, BATCHcount, strerror(errno)); (void)close(artfd); break; } Cookie = ftell(stdin) - length; } SendIt: /* Now we can start to send the article! */ if (Separator && *Separator) { (void)sprintf(buff, Separator, BytesInArt); BytesInCB += strlen(buff) + 1; BytesWritten += strlen(buff) + 1; if (fprintf(F, "%s\n", buff) == EOF || ferror(F)) { (void)fprintf(stderr, "batcher %s cant write separator %s\n", Host, strerror(errno)); (void)close(artfd); break; } } /* Write the article. In case of interrupts, retry the read but * not the fwrite because we can't check that reliably and * portably. */ while ((i = read(artfd, (POINTER)data, datasize)) > 0 || errno == EINTR) if (fwrite((POINTER)data, (SIZE_T)1, (SIZE_T)i, F) != i) break; if (ferror(F)) { (void)fprintf(stderr, "batcher %s cant write article %s\n", Host, strerror(errno)); (void)close(artfd); break; } (void)close(artfd); /* Update the counts. */ BytesInCB += BytesInArt; BytesWritten += BytesInArt; ArtsInCB++; ArtsWritten++; if (GotInterrupt) { BATCHstatus = BATCHclose(F); RequeueAndExit(Cookie, line, BytesInArt); } } if (BATCHopen) BATCHstatus = BATCHclose(F); RequeueAndExit(Cookie, (char *)NULL, 0L); /* NOTREACHED */ } inn-1.7.2/backends/actsync.c0100644000175100001440000026716006443103542014225 0ustar mdusers/* @(#) $Id: actsync.c,v 1.23 1996/12/16 20:51:30 brister Exp $ */ /* @(#) Under RCS control in /usr/local/news/src/inn/local/RCS/actsync.c,v */ /* * actsync - sync or merge two active files * * usage: * actsync [-b hostid][-d hostid][-g max][-i ignore_file][-I][-k][-l hostid] * [-m][-n name][-o fmt][-p %][-q hostid][-s size][-S spool_dir] * [-t hostid][-T][-v verbose_lvl][-z sec] * [host1] host2 * * -b hostid ignore *.bork.bork.bork groups from: (def: -b 0) * 0 from neither host * 1 from host1 * 2 from host2 * 12 from host1 and host2 * 21 from host1 and host2 * -d hostid ignore groups with all numeric components (def: -d 0) * -g max ignore group >max levels (0=dont ignore) (def: -g 0) * -i ignore_file file with list/types of groups to ignore (def: no file) * -I hostid ignore_file applies only to hostid (def: -I 12) * -k keep host1 groups with errors (def: remove) * -l hostid flag =group problems as errors (def: -l 12) * -m merge, keep group not on host2 (def: sync) * -n name name given to ctlinnd newgroup commands (def: actsync) * -o fmt type of output: (def: -o c) * a output groups in active format * a1 like 'a', but output ignored non-err host1 grps * ak like 'a', keep host2 hi/low values on new groups * aK like 'a', use host2 hi/low values always * c output in ctlinnd change commands * x no output, safely exec ctlinnd commands * xi no output, safely exec commands interactively * -p % min % host1 lines unchanged allowed (def: -p 96) * -q hostid silence errors from a host (see -b) (def: -q 0) * -s size ignore names longer than size (0=no lim) (def: -s 0) * -S spool_dir scan spool_dir for hi & low water marks (def: dont) * -t hostid ignore bad top level groups from:(see -b) (def: -t 2) * -T no new hierarchies (requires -S dir) (def: allow) * -v verbose_lvl verbosity level (def: -v 0) * 0 no debug or status reports * 1 summary if work done * 2 summary & actions (if exec output) only if done * 3 summary & actions (if exec output) * 4 debug output plus all -v 3 messages * -z sec sleep sec seconds per exec if -o x (def: -z 4) * host1 host to be changed (def: local server) * host2 reference host used in merge */ /* * By: Landon Curt Noll chongo@toad.com (chongo was here /\../\) * * Copyright (c) Landon Curt Noll, 1996. * All rights reserved. * * Permission to use and modify is hereby granted so long as this * notice remains. Use at your own risk. No warranty is implied. */ #include "configdata.h" #include #include #include #include #include #include #include #include #include #include #include #include "clibrary.h" #include "mydir.h" #include "libinn.h" #include "qio.h" #include "paths.h" #include "macros.h" /* * HiLowWater - Given an newsgroup name determine the hi and low water marks * * Given: * name name of newsgroup (in . notation) * hi where to place the hi water mark value * low where to place the low water mark value * oldhi current hi water mark, or -1 to force to compute * oldlow current low water mark, or -1 to force to compute * * Returns: * TRUE newsgroup directory was found with files in it * FALSE newsgroup directiry was not found, or did not contain * and files with all numeric (non-leading 0) names * * NOTE: This routine assumes that the current directory is $SPOOL. */ BOOL HiLowWater(name, hi, low, oldhi, oldlow) char *name; long *hi; long *low; long oldhi; long oldlow; { int dir_len; /* length of newsgroup name */ int file_len; /* length of the filename in the dir */ char dir[BUFSIZ]; /* name of directory to probe */ char path[BUFSIZ+SMBUF]; /* spool relative path of a file */ DIR *dp; /* directory 'read descriptor' */ DIRENTRY *ep; /* entry read from a directory */ long num; /* numeric value of a filename */ long himark; /* current hi water mark found */ long lowmark; /* current low water mark found */ BOOL found_art; /* TRUE => found an article */ struct stat statbuf; /* stat of the file in the directory */ char *p; char *q; /* * firewall */ if (hi == NULL || low == NULL || name == NULL) { /* error - bogus args ... assume FALSE */ return FALSE; } dir_len = strlen(name); if (dir_len == 0 || dir_len >= BUFSIZ) { /* newsgroup name length is bad, so punt on the search */ return FALSE; } /* * assume current hi and low values unless we find otherwise * * force low > 0 && hi >= low-1 */ if (oldlow > 0) { *low = oldlow; lowmark = oldlow; if (oldhi < oldlow-1) { oldhi = oldlow-1; } } else { *low = 1; lowmark = 0x7fffffff; } if (oldhi >= 0) { *hi = oldhi; himark = oldhi; } else { *hi = 0; himark = 0; } /* * Turn group name into directory name */ for (p=name, q=dir; *p; ++p, ++q) { if (*p == '.') { *q = '/'; } else { *q = *p; } } *q = '\0'; /* * attempt to open the directory */ dp = opendir(dir); if (dp == NULL) { /* cannot scan the directory, assume not found or non-accessable */ return FALSE; } /* * scan the directory for all numeric non-leading zero entries * looking for the lowest and highest values */ found_art = FALSE; while ((ep = readdir(dp)) != NULL) { /* * ignore if it it does not begin with [1-9] */ p = ep->d_name; if (!CTYPE(isdigit, *p) || *p == '0') { /* first char is not [1-9], ignore */ continue; } /* * ignore if contains a non-digit elsewhere in the name */ for (++p; *p; ++p) { if (!CTYPE(isdigit, *p)) { break; } } if (*p) { /* found a non-digit, ignore this entry */ continue; } /* * convert numeric file name to a digit */ num = atol(ep->d_name); /* * look for a new low water mark * * Ignore this entry if it is not a file. */ if (num < lowmark) { /* * ignore if this entry is not a file * * If the numeric name is too long, assume we have a file */ file_len = strlen(ep->d_name); if (dir_len+1+file_len < BUFSIZ+SMBUF) { /* * form the filename */ strncpy(path, dir, dir_len); path[dir_len] = '/'; strncpy(path+dir_len+1, ep->d_name, file_len); path[dir_len+1+file_len] = '\0'; /* * skip if fie is not found or if it is not a regular file */ if (stat(path, &statbuf) < 0 || !S_ISREG(statbuf.st_mode)) { continue; } } /* * we have a new low water mark */ lowmark = num; } /* * note that we saw a numeric non-learing 0 file */ found_art = TRUE; /* * look for a new hi water mark */ if (num > himark) { himark = num; } } /* * if lowmark was never set, set it to 1 */ if (!found_art) { lowmark = himark+1; } /* * We know that lowmark is > 0, so now we will force hi >= low-1 */ if (himark < lowmark-1) { himark = lowmark-1; } /* * note new marks */ *hi = himark; *low = lowmark; /* found new marks */ return found_art; } /* * pat - internal ignore/check pattern * * A pattern, derived from an ignore file, will determine if a group * is will be checked if it is on both hosts or ignored altogether. * * The type related to the 4th field of an active file. Types may * currently be one of [ymjnx=]. If '=' is one of the types, an * optional equivalence pattern may be given in the 'epat' element. * * For example, to ignore "foo.bar.*", if it is junked or equated to * a group of the form "alt.*.foo.bar.*": * * x.pat = "foo.bar.*"; * x.type = "j="; * x.epat = "alt.*.foo.bar.*"; * x.ignore = 1; * * To further check "foo.bar.mod" if it is moderated: * * x.pat = "foo.bar.mod"; * x.type = "m"; * x.epat = NULL; * x.ignore = 0; * * The 'i' value means ignore, 'c' value means 'compare'. The last pattern * that matches a group determines the fate of the group. By default all * groups are included. */ struct pat { char *pat; /* newsgroup pattern */ int type_match; /* 1 => match only if group type matches */ int y_type; /* 1 => match if a 'y' type group */ int m_type; /* 1 => match if a 'm' type group */ int n_type; /* 1 => match if a 'n' type group */ int j_type; /* 1 => match if a 'j' type group */ int x_type; /* 1 => match if a 'x' type group */ int eq_type; /* 1 => match if a 'eq' type group */ char *epat; /* =pattern to match, if non-NULL and = is in type */ int ignore; /* 0 => check matching group, 1 => ignore it */ }; /* internal representation of an active line */ struct grp { int ignore; /* ignore reason, 0 => not ignore (see below) */ int hostid; /* HOSTID this group is from */ int linenum; /* >0 => active line number, <=0 => not a line */ int output; /* 1 => output to produce the merged active file */ int remove; /* 1 => remove this group */ char *name; /* newsgroup name */ char *hi; /* high article string */ char *low; /* low article string */ char *type; /* newsgroup type string */ char *outhi; /* output high article string */ char *outlow; /* output low article string */ char *outtype; /* output newsgroup type string */ }; /* structure used in the process of looking for =group type problems */ struct eqgrp { int skip; /* 1 => skip this entry */ struct grp *g; /* =group that is being examined */ char *eq; /* current equivalence name */ }; /* * These ignore reasons are listed in order severity; from mild to severe. */ #define NOT_IGNORED 0x0000 /* newsgroup has not been ignored */ #define CHECK_IGNORE 0x0001 /* ignore file ignores this entry */ #define CHECK_TYPE 0x0002 /* group type is ignored */ #define CHECK_BORK 0x0004 /* group is a *.bork.bork.bork group */ #define CHECK_HIER 0x0008 /* -T && new group's hierarchy does not exist */ #define ERROR_LONGLOOP 0x0010 /* =name refers to long =grp chain or cycle */ #define ERROR_EQLOOP 0x0020 /* =name refers to itself in some way */ #define ERROR_NONEQ 0x0040 /* =name does not refer to a valid group */ #define ERROR_DUP 0x0080 /* newsgroup is a duplicate of another */ #define ERROR_EQNAME 0x0100 /* =name is a bad group name */ #define ERROR_BADTYPE 0x0200 /* newsgroup type is invalid */ #define ERROR_BADNAME 0x0400 /* newsgroup name is invalid */ #define ERROR_FORMAT 0x0800 /* entry line is malformed */ #define IS_IGNORE(ign) ((ign) & (CHECK_IGNORE|CHECK_TYPE|CHECK_BORK|CHECK_HIER)) #define IS_ERROR(ign) ((ign) & ~(CHECK_IGNORE|CHECK_TYPE|CHECK_BORK|CHECK_HIER)) #define NOHOST 0 /* neither host1 nor host2 */ #define HOSTID1 1 /* entry from the first host */ #define HOSTID2 2 /* entry from the second host */ #define CHUNK 5000 /* number of elements to alloc at a time */ #define TYPES "ymjnx=" /* group types (1st char of 4th active fld) */ #define TYPECNT (sizeof(TYPES)-1) #define DEF_HI "0000000000" /* default hi string value for new groups */ #define DEF_LOW "0000000001" /* default low string value for new groups */ #define WATER_LEN 10 /* string length of hi/low water mark */ #define DEF_NAME "actsync" /* default name to use for ctlinnd newgroup */ #define MIN_UNCHG (double)96.0 /* min % of host1 lines unchanged allowed */ /* * path to ctlinnd command */ /* =()<#define CTLINND_PATH "@<_PATH_NEWSBIN>@/ctlinnd">()= */ #define CTLINND_PATH "/usr/news/bin/ctlinnd" #define DEV_NULL "/dev/null" /* path to the bit bucket */ #define CTLINND_NAME "ctlinnd" /* basename of ctlinnd command */ #define CTLINND_TIME_OUT "-t30" /* seconds to wait before timeout */ #define READ_SIDE 0 /* read side of a pipe */ #define WRITE_SIDE 1 /* write side of a pipe */ #define EQ_LOOP 16 /* give up if =eq loop/chain is this long */ #define NOT_REACHED 127 /* exit value if unable to get active files */ #define NEWGRP_EMPTY 0 /* no new group dir was found */ #define NEWGRP_NOCHG 1 /* new group dir found but no hi/low change */ #define NEWGRP_CHG 2 /* new group dir found but no hi/low change */ #if !defined(DONT_USE_UNION_WAIT) #if !defined(WEXITSTATUS) #define WEXITSTATUS(status) ((status).w_retcode) #endif #if !defined(WTERMSIG) #define WTERMSIG(status) ((status).w_termsig) #endif #endif /* -b macros */ #define BORK_CHECK(hostid) \ ((hostid == HOSTID1 && bork_host1_flag) || \ (hostid == HOSTID2 && bork_host2_flag)) /* -d macros */ #define NUM_CHECK(hostid) \ ((hostid == HOSTID1 && num_host1_flag) || \ (hostid == HOSTID2 && num_host2_flag)) /* -t macros */ #define TOP_CHECK(hostid) \ ((hostid == HOSTID1 && t_host1_flag) || \ (hostid == HOSTID2 && t_host2_flag)) /* -o output types */ #define OUTPUT_ACTIVE 1 /* output in active file format */ #define OUTPUT_CTLINND 2 /* output in ctlinnd change commands */ #define OUTPUT_EXEC 3 /* no output, safely exec commands */ #define OUTPUT_IEXEC 4 /* no output, exec commands interactively */ /* -q macros */ #define QUIET(hostid) \ ((hostid == HOSTID1 && quiet_host1) || (hostid == HOSTID2 && quiet_host2)) /* -v verbosity level */ #define VER_MIN 0 /* minimum -v level */ #define VER_NONE 0 /* no -v output */ #define VER_SUMM_IF_WORK 1 /* output summary if actions were performed */ #define VER_REPT_IF_WORK 2 /* output summary & actions only if performed */ #define VER_REPORT 3 /* output summary & actions performed */ #define VER_FULL 4 /* output all summary, actins and debug */ #define VER_MAX 4 /* maximum -v level */ #define D_IF_SUMM (v_flag >= VER_SUMM_IF_WORK) /* TRUE => give summary always */ #define D_REPORT (v_flag >= VER_REPT_IF_WORK) /* TRUE => give reports */ #define D_BUG (v_flag == VER_FULL) /* TRUE => debug processing */ #define D_SUMMARY (v_flag >= VER_REPORT) /* TRUE => give summary always */ /* flag and arg related defaults */ char *program; /* our name */ int bork_host1_flag = 0; /* 1 => -b 1 or -b 12 or -b 21 given */ int bork_host2_flag = 0; /* 1 => -b 2 or -b 12 or -b 21 given */ int num_host1_flag = 0; /* 1 => -d 1 or -d 12 or -d 21 given */ int num_host2_flag = 0; /* 1 => -d 2 or -d 12 or -d 21 given */ char *ign_file = NULL; /* default ignore file */ int ign_host1_flag = 1; /* 1 => -i ign_file applies to host1 */ int ign_host2_flag = 1; /* 1 => -i ign_file applies to host2 */ int g_flag = 0; /* ignore grps deeper than > g_flag, 0=>dont */ int k_flag = 0; /* 1 => -k given */ int l_host1_flag = HOSTID1; /* HOSTID1 => host1 =group error detection */ int l_host2_flag = HOSTID2; /* HOSTID2 => host2 =group error detection */ int m_flag = 0; /* 1 => merge active files, don't sync */ char *new_name = DEF_NAME; /* ctlinnd newgroup name */ int o_flag = OUTPUT_CTLINND; /* default output type */ double p_flag = MIN_UNCHG; /* min % host1 lines allowed to be unchanged */ int host1_errs = 0; /* errors found in host1 active file */ int host2_errs = 0; /* errors found in host2 active file */ int quiet_host1 = 0; /* 1 => -q 1 or -q 12 or -q 21 given */ int quiet_host2 = 0; /* 1 => -q 2 or -q 12 or -q 21 given */ int s_flag = 0; /* max group size (length), 0 => do not check */ char *spool = NULL; /* non-NULL => scan spool_dir for hi & low */ int t_host1_flag = 0; /* 1 => -t 1 or -t 12 or -t 21 given */ int t_host2_flag = 1; /* 1 => -t 2 or -d 12 or -t 21 given */ int no_new_hier = 0; /* 1 => -T; no new hierarchies */ int host2_hilow_newgrp = 0; /* 1 => use host2 hi/low on new groups */ int host2_hilow_all = 0; /* 1 => use host2 hi/low on all groups */ int host1_ign_print = 0; /* 1 => print host1 ignored groups too */ int v_flag = 0; /* default verbosity level */ int z_flag = 4; /* sleep z_flag sec per exec if -o x */ /* forward declarations */ static struct grp *get_active(); /* get an active file from a remote host */ static int bad_grpname(); /* test if string is a valid group name */ static struct pat *get_ignore(); /* read in an ignore file */ static void ignore(); /* ignore newsgroups given an ignore list */ static void usage(); /* print a usage message and exit */ static int merge_cmp(); /* qsort compare for active file merge */ static void merge_grps(); /* merge groups from active files */ static int active_cmp(); /* qsort compare for active file output */ static void output_grps(); /* output the merged groups */ static void process_args(); /* process command line arguments */ static void error_mark(); /* mark for removal, error grps from host */ static int eq_merge_cmp(); /* qsort compare for =type grp processing */ static int mark_eq_probs(); /* mark =type problems from a host */ static int exec_cmd(); /* exec a ctlinnd command */ static int scan_spool_dir(); /* scan spool dir for existing articles */ static int new_top_hier(); /* see if we have a new top level */ int main(argc, argv) int argc; /* arg count */ char *argv[]; /* the args */ { struct grp *grp; /* struct grp array for host1 & host2 */ struct pat *ignor; /* ignore list from ignore file */ int grplen; /* length of host1/host2 group array */ int iglen; /* length of ignore list */ char *host1; /* host to change */ char *host2; /* comparison host */ /* process args */ process_args(argc, argv, &host1, &host2); /* obtain the active files */ grp = get_active(host1, HOSTID1, &grplen, NULL, &host1_errs); grp = get_active(host2, HOSTID2, &grplen, grp, &host2_errs); /* ignore groups from both active files, if -i */ if (ign_file != NULL) { /* read in the ignore file */ ignor = get_ignore(ign_file, &iglen); /* ignore groups */ ignore(grp, grplen, ignor, iglen); } /* compare groups from both hosts */ merge_grps(grp, grplen, host1, host2); /* if -S, cd to that spool dir for later hi/low water checking */ if (spool != NULL) { if (chdir(spool) < 0) { fprintf(stderr, "%s: cannot cd to %s\n", program, spool); exit(1); } if (D_BUG) { fprintf(stderr, "%s: cd %s\n", program, spool); } } /* mark for removal, error groups from host1 if -e */ if (! k_flag) { /* mark error groups for removal */ error_mark(grp, grplen, HOSTID1); } /* output result of merge */ output_grps(grp, grplen); /* all done */ exit(0); } /* * process_args - process the command line arguments * * given: * argc arg count * argv the args * host1 name of first host (may be 2nd if -R) * host2 name of second host2 *may be 1st if -R) */ static void process_args(argc, argv, host1, host2) int argc; /* arg count */ char *argv[]; /* the arg array */ char **host1; /* where to place name of host1 */ char **host2; /* where to place name of host2 */ { char *def_serv = NULL; /* name of default server */ int i; /* parse args */ program = argv[0]; while ((i = getopt(argc,argv,"b:d:g:i:I:kl:mn:o:p:q:s:S:t:Tv:z:")) != EOF) { switch (i) { case 'b': /* -b {0|1|2|12|21} */ switch (atoi(optarg)) { case 0: bork_host1_flag = 0; bork_host2_flag = 0; break; case 1: bork_host1_flag = 1; break; case 2: bork_host2_flag = 1; break; case 12: case 21: bork_host1_flag = 1; bork_host2_flag = 1; break; default: fprintf(stderr, "%s: -b option must be 0, 1, 2, 12 or 21\n", program); usage(); /* NOTREACHED */ } break; case 'd': /* -d {0|1|2|12|21} */ switch (atoi(optarg)) { case 0: num_host1_flag = 0; num_host2_flag = 0; break; case 1: num_host1_flag = 1; break; case 2: num_host2_flag = 1; break; case 12: case 21: num_host1_flag = 1; num_host2_flag = 1; break; default: fprintf(stderr, "%s: -d option must be 0, 1, 2, 12 or 21\n", program); usage(); /* NOTREACHED */ } break; case 'g': /* -g max */ g_flag = atoi(optarg); break; case 'i': /* -i ignore_file */ ign_file = optarg; break; case 'I': /* -I {0|1|2|12|21} */ switch (atoi(optarg)) { case 0: ign_host1_flag = 0; ign_host2_flag = 0; break; case 1: ign_host1_flag = 1; ign_host2_flag = 0; break; case 2: ign_host1_flag = 0; ign_host2_flag = 1; break; case 12: case 21: ign_host1_flag = 1; ign_host2_flag = 1; break; default: fprintf(stderr, "%s: -I option must be 0, 1, 2, 12 or 21\n", program); usage(); /* NOTREACHED */ } break; case 'k': /* -k */ k_flag = 1; break; case 'l': /* -l {0|1|2|12|21} */ switch (atoi(optarg)) { case 0: l_host1_flag = NOHOST; l_host2_flag = NOHOST; break; case 1: l_host1_flag = HOSTID1; l_host2_flag = NOHOST; break; case 2: l_host1_flag = NOHOST; l_host2_flag = HOSTID2; break; case 12: case 21: l_host1_flag = HOSTID1; l_host2_flag = HOSTID2; break; default: fprintf(stderr, "%s: -l option must be 0, 1, 2, 12 or 21\n", program); usage(); /* NOTREACHED */ } break; case 'm': /* -m */ m_flag = 1; break; case 'n': /* -n name */ new_name = optarg; break; case 'o': /* -o out_type */ switch (optarg[0]) { case 'a': o_flag = OUTPUT_ACTIVE; switch (optarg[1]) { case '1': switch(optarg[2]) { case 'K': /* -o a1K */ host1_ign_print = 1; host2_hilow_all = 1; host2_hilow_newgrp = 1; break; case 'k': /* -o a1k */ host1_ign_print = 1; host2_hilow_newgrp = 1; break; default: /* -o a1 */ host1_ign_print = 1; break; } break; case 'K': switch(optarg[2]) { case '1': /* -o aK1 */ host1_ign_print = 1; host2_hilow_all = 1; host2_hilow_newgrp = 1; break; default: /* -o aK */ host2_hilow_all = 1; host2_hilow_newgrp = 1; break; }; break; case 'k': switch(optarg[2]) { case '1': /* -o ak1 */ host1_ign_print = 1; host2_hilow_newgrp = 1; break; default: /* -o ak */ host2_hilow_newgrp = 1; break; }; break; case '\0': /* -o a */ break; default: fprintf(stderr, "%s: -o type must be: a, a1, ak, aK, ak1, aK1\n", program); usage(); /* NOTREACHED */ } break; case 'c': o_flag = OUTPUT_CTLINND; break; case 'x': if (optarg[1] == 'i') { o_flag = OUTPUT_IEXEC; } else { o_flag = OUTPUT_EXEC; } break; default: fprintf(stderr, "%s: -o type must be: a, a1, ak, aK, ak1, aK1, c, x or xi\n", program); usage(); /* NOTREACHED */ } break; case 'p': /* -p %_min_host1_change */ /* parse % into [0,100] */ p_flag = atof(optarg); if (p_flag > (double)100.0) { p_flag = (double)100.0; } else if (p_flag < (double)0.0) { p_flag = (double)0.0; } break; case 'q': /* -q {0|1|2|12|21} */ switch (atoi(optarg)) { case 0: quiet_host1 = 0; quiet_host2 = 0; break; case 1: quiet_host1 = 1; break; case 2: quiet_host2 = 1; break; case 12: case 21: quiet_host1 = 1; quiet_host2 = 1; break; default: fprintf(stderr, "%s: -q option must be 0, 1, 2, 12 or 21\n", program); usage(); /* NOTREACHED */ } break; case 's': /* -s size */ s_flag = atoi(optarg); break; case 'S': /* -S spool_dir */ spool = optarg; break; case 't': /* -t {0|1|2|12|21} */ switch (atoi(optarg)) { case 0: t_host1_flag = NOHOST; t_host2_flag = NOHOST; break; case 1: t_host1_flag = HOSTID1; t_host2_flag = NOHOST; break; case 2: t_host1_flag = NOHOST; t_host2_flag = HOSTID2; break; case 12: case 21: t_host1_flag = HOSTID1; t_host2_flag = HOSTID2; break; default: fprintf(stderr, "%s: -t option must be 0, 1, 2, 12 or 21\n", program); usage(); /* NOTREACHED */ } break; case 'T': /* -T */ no_new_hier = 1; break; case 'v': /* -v verbose_lvl */ v_flag = atoi(optarg); if (v_flag < VER_MIN || v_flag > VER_MAX) { fprintf(stderr, "%s: -v level must be >= %d and <= %d\n", program, VER_MIN, VER_MAX); usage(); /* NOTREACHED */ } break; case 'z': /* -z sec */ z_flag = atoi(optarg); break; default: fprintf(stderr, "%s: unknown flag\n", program); usage(); /* NOTREACHED */ } } /* process the remaining args */ argc -= optind; argv += optind; *host1 = NULL; switch (argc) { case 1: /* assume host1 is the local server */ *host2 = argv[0]; break; case 2: *host1 = argv[0]; *host2 = argv[1]; break; default: fprintf(stderr, "%s: expected 1 or 2 host args, found: %d\n", program, argc); usage(); /* NOTREACHED */ } /* -T requires -S */ if (no_new_hier && spool == NULL) { fprintf(stderr, "%s: -T requires -S spool_dir\n", program); usage(); /* NOTREACHED */ } /* determine default host name if needed */ if (*host1 == NULL || strcmp(*host1, "-") == 0) { def_serv = GetConfigValue(_CONF_SERVER); *host1 = def_serv; } if (*host2 == NULL || strcmp(*host2, "-") == 0) { def_serv = GetConfigValue(_CONF_SERVER); *host2 = def_serv; } if (*host1 == NULL || *host2 == NULL) { fprintf(stderr, "%s: unable to determine default server name\n", program); exit(2); } if (D_BUG && def_serv != NULL) { fprintf(stderr, "%s: STATUS: using default server: %s\n", program, def_serv); } /* processing done */ return; } /* * usage - print usage message and exit */ static void usage() { (void) fprintf(stderr, "usage: %s [-b hostid][-d hostid][-i ignore_file][-I hostid][-k]\n", program); (void) fprintf(stderr, "\t[-l hostid][-m][-n name][-o fmt][-p min_%%_unchg][-q hostid]\n"); (void) fprintf(stderr, "\t[-s size][-S spool_dir][-t hostid][-T][-v verbose_lvl][-z sec]\n"); (void) fprintf(stderr, "\t[host1] host2\n\n"); (void) fprintf(stderr, " -b hostid\tignore *.bork.bork.bork groups from:\t(def: -b 0)\n"); (void) fprintf(stderr, "\t0\t from neither host\n"); (void) fprintf(stderr, "\t1\t from host1\n"); (void) fprintf(stderr, "\t2\t from host2\n"); (void) fprintf(stderr, "\t12\t from host1 and host2\n"); (void) fprintf(stderr, "\t21\t from host1 and host2\n"); (void) fprintf(stderr, " -d hostid\tignore grps with all numeric components (def: -d 0)\n"); (void) fprintf(stderr, " -g max\tignore group >max levels (0=don't)\t(def: -g 0)\n"); (void) fprintf(stderr, " -i ignore_file\tfile with groups to ignore\t(def: no file)\n"); (void) fprintf(stderr, " -I hostid\tignore_file applies only to hostid\t(def: -I 12)\n"); (void) fprintf(stderr, " -k\t\tkeep host1 groups with errors\t\t(def: remove)\n"); (void) fprintf(stderr, " -l hostid\tflag =group problems as errors\t\t(def: -l 12)\n"); (void) fprintf(stderr, " -m\t\tmerge, keep group not on host2\t\t(def: sync)\n"); (void) fprintf(stderr, " -n name\tname given to ctlinnd newgroup cmds\t(def: actsync)\n"); (void) fprintf(stderr, " -o fmt\ttype of output:\t\t\t\t(def: -o c)\n"); (void) fprintf(stderr, "\ta\t output groups in active format\n"); (void) fprintf(stderr, "\ta1\t like 'a', but output ignored non-err host1 grps\n"); (void) fprintf(stderr, "\tak\t like 'a', keep host2 hi/low values on new groups\n"); (void) fprintf(stderr, "\taK\t like 'a', use host2 hi/low values always\n"); (void) fprintf(stderr, "\tc\t output in ctlinnd change commands\n"); (void) fprintf(stderr, "\tx\t no output, safely exec ctlinnd commands\n"); (void) fprintf(stderr, "\txi\t no output, safely exec commands interactively\n"); (void) fprintf(stderr, " -p %%\t\tmin %% host1 lines unchanged allowed\t (def: -p 96)\n"); (void) fprintf(stderr, " -q hostid\tsilence errors from a host (see -b)\t (def: -q 0)\n"); (void) fprintf(stderr, " -s size\tignore names > than size (0=no lim)\t (def: -s 0)\n"); (void) fprintf(stderr, " -S spool_dir\tscan spool_dir for hi & low water marks\t(def: dont)\n"); (void) fprintf(stderr, " -t hostid\tignore bad top level grps from: (see -b) (def: -t 2)\n"); (void) fprintf(stderr, " -T\t\tno new hierarchies (needs -S dir)\t (def: allow)\n"); (void) fprintf(stderr, " -v verbose_lvl\tverbosity level\t\t\t (def: -v 0)\n"); (void) fprintf(stderr, "\t0\t no debug or status reports\n"); (void) fprintf(stderr, "\t1\t summary if work done\n"); (void) fprintf(stderr, "\t2\t summary & actions (if exec output) only if done\n"); (void) fprintf(stderr, "\t3\t summary & actions (if exec output)\n"); (void) fprintf(stderr, "\t4\t debug output plus all -v 3 messages\n"); (void) fprintf(stderr, " -z sec\tsleep sec seconds per exec if -o x\t\t(def: -z 4)\n"); (void) fprintf(stderr, " host1\thost to be changed\t\t\t(def: local server)\n"); (void) fprintf(stderr, " host2\treference host used in merge\n"); exit(3); } /* * get_active - get an active file from a host * * given: * host host to contact or file to read, NULL => local server * hostid HOST_ID of host * len pointer to length of grp return array * grp existing host array to add, or NULL * errs count of lines that were found to have some error * * returns; * Pointer to an array of grp structures describing each active entry. * Does not return on fatal error. * * If host starts with a '/' or '.', then it is assumed to be a local file. * In that case, the local file is opened and read. */ static struct grp * get_active(host, hostid, len, grp, errs) char *host; /* the host to contact */ int hostid; /* HOST_ID of host */ int *len; /* length of returned grp array in elements */ struct grp* grp; /* existing group array or NULL */ int *errs; /* line error count */ { FILE *active; /* stream for fetched active data */ FILE *FromServer; /* stream from server */ FILE *ToServer; /* stream to server */ QIOSTATE *qp; /* QIO active state */ char buff[QIO_BUFFER+1]; /* QIO buffer */ char *line; /* the line just read */ struct grp *ret; /* array of groups to return */ struct grp *cur; /* current grp entry being formed */ int max; /* max length of ret */ int cnt; /* number of entries read */ int ucnt; /* number of entries to be used */ int namelen; /* length of newsgroup name */ int is_file; /* 1 => host is actually a filename */ int num_check; /* TRUE => check for all numeric components */ char *p; int i; /* firewall */ if (len == NULL) { fprintf(stderr, "%s: internal error #1, len is NULL\n", program); exit(4); } if (errs == NULL) { fprintf(stderr, "%s: internal error #2, errs is NULL\n", program); exit(5); } if (D_BUG) { fprintf(stderr, "%s: STATUS: obtaining active file from %s\n", program, host); } /* setup return array if needed */ if (grp == NULL) { ret = (struct grp *) malloc(CHUNK * sizeof(struct grp)); if (ret == NULL) { fprintf(stderr, "%s: malloc of %d grp elements failed\n", program, CHUNK); exit(6); } max = CHUNK; *len = 0; /* or prep to use the existing array */ } else { ret = grp; max = ((*len + CHUNK-1)/CHUNK)*CHUNK; } /* check for host being a filename */ if (host != NULL && (host[0] == '/' || host[0] == '.')) { /* note that host is actually a file */ is_file = 1; /* setup to read the local file quickly */ if ((qp = QIOopen(host, QIO_BUFFER)) == NULL) { (void) fprintf(stderr, "%s: can't read active file, %s\n", program, strerror(errno)); exit(NOT_REACHED); } /* case: host is a hostname or NULL (default server) */ } else { /* note that host is actually a hostname or NULL */ is_file = 0; /* open a connection to the server */ buff[0] = '\0'; if (NNTPconnect(host, &FromServer, &ToServer, buff) < 0) { (void) fprintf(stderr, "can't connect to server, %s\n", buff[0] ? buff : strerror(errno)); exit(NOT_REACHED); } /* get the active data from the server */ active = CAlistopen(FromServer, ToServer, NULL); if (active == NULL) { (void) fprintf(stderr, "%s: can't retrieve data, %s\n", program, strerror(errno)); (void) fclose(FromServer); (void) fclose(ToServer); exit(7); } /* setup to read the retrieved data quickly */ if ((qp = QIOfdopen((int)fileno(active), QIO_BUFFER)) == NULL) { (void) fprintf(stderr, "%s: can't read temp file, %s\n", program, strerror(errno)); (void) fclose(FromServer); (void) fclose(ToServer); exit(8); } } /* scan server's output, processing appropriate lines */ num_check = NUM_CHECK(hostid); for (cnt=0, ucnt=0; (line = QIOread(qp)) != NULL; ++(*len), ++cnt) { /* expand return array if needed */ if (*len >= max) { max += CHUNK; ret = (struct grp *) realloc(ret, sizeof(struct grp)*max); if (ret == NULL) { fprintf(stderr, "%s: unable to realloc %d grp elements\n", program, max); exit(9); } } /* setup the next return element */ cur = &ret[*len]; cur->ignore = NOT_IGNORED; cur->hostid = hostid; cur->linenum = cnt+1; cur->output = 0; cur->remove = 0; cur->name = NULL; cur->hi = NULL; cur->low = NULL; cur->type = NULL; cur->outhi = NULL; cur->outlow = NULL; cur->outtype = NULL; /* obtain a copy of the current line */ cur->name = (char *) malloc(QIOlength(qp)+1); if (cur->name == NULL) { fprintf(stderr, "%s: unable to malloc %d char line buffer\n", program, QIOlength(qp)+1); exit(10); } strncpy(cur->name, line, QIOlength(qp)); cur->name[QIOlength(qp)] = '\0'; /* get the group name */ if ((p = strchr(cur->name, ' ')) == NULL) { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: line %d from %s is malformed, skipping line\n", program, cnt+1, host); } /* don't form an entry for this group */ --(*len); continue; } *p = '\0'; namelen = p - cur->name; /* find the other 3 fields, ignore if not found */ cur->hi = p+1; if ((p = strchr(p + 1, ' ')) == NULL) { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: skipping malformed line %d (field 2) from %s\n", program, cnt+1, host); } /* don't form an entry for this group */ --(*len); continue; } *p = '\0'; cur->low = p+1; if ((p = strchr(p + 1, ' ')) == NULL) { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: skipping malformed line %d (field 3) from %s\n", program, cnt+1, host); } /* don't form an entry for this group */ --(*len); continue; } *p = '\0'; cur->type = p+1; if ((p = strchr(p + 1, ' ')) != NULL) { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: skipping line %d from %s, it has more than 4 fields\n", program, cnt+1, host); } /* don't form an entry for this group */ --(*len); continue; } /* check for bad group name */ if (bad_grpname(cur->name, num_check)) { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: line %d <%s> from %s has a bad newsgroup name\n", program, cnt+1, cur->name, host); } cur->ignore |= ERROR_BADNAME; continue; } /* check for long name if requested */ if (s_flag > 0 && strlen(cur->name) > s_flag) { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: line %d <%s> from %s has a name that is too long\n", program, cnt+1, cur->name, host); } cur->ignore |= ERROR_BADNAME; continue; } /* look for only a bad top level element if the proper -t was given */ if (TOP_CHECK(hostid)) { /* look for a '.' in the name */ if (strcmp(cur->name, "junk") != 0 && strcmp(cur->name, "control") != 0 && strcmp(cur->name, "to") != 0 && strcmp(cur->name, "test") != 0 && strcmp(cur->name, "general") != 0 && strchr(cur->name, '.') == NULL) { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: line %d <%s> from %s is an invalid top level name\n", program, cnt+1, cur->name, host); } cur->ignore |= ERROR_BADNAME; continue; } } /* look for *.bork.bork.bork groups if the proper -b was given */ if (BORK_CHECK(cur->hostid)) { int elmlen; /* length of element */ char *q; /* beyond end of element */ /* scan the name backwards */ q = &(cur->name[namelen]); for (p = &(cur->name[namelen-1]); p >= cur->name; --p) { /* if '.', see if this is a bork element */ if (*p == '.') { /* see if the bork element is short enough */ elmlen = q-p; if (3*elmlen <= q-cur->name) { /* look for a triple match */ if (strncmp(p,p-elmlen,elmlen) == 0 && strncmp(p,p-(elmlen*2),elmlen) == 0) { /* found a *.bork.bork.bork group */ cur->ignore |= CHECK_BORK; break; } } /* note the end of a new element */ q = p; } } } /* * check for bad chars in the hi water mark */ for (p=cur->hi, i=0; *p && isascii(*p) && isdigit(*p); ++p, ++i) { } if (*p) { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: line %d <%s> from %s has non-digits in hi water\n", program, cnt+1, cur->name, cur->hi); } cur->ignore |= ERROR_FORMAT; continue; } /* * check for excessive hi water length */ if (i > WATER_LEN) { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: line %d <%s> from %s hi water len: %d < %d\n", program, cnt+1, cur->name, cur->hi, i, WATER_LEN); } cur->ignore |= ERROR_FORMAT; continue; } /* * if the hi water length is too small, malloc and resize */ if (i != WATER_LEN) { p = malloc(WATER_LEN+1); if (p == NULL) { fprintf(stderr, "%s: unable to malloc %d char hi water string\n", program, WATER_LEN+1); exit(11); } memcpy(p, cur->hi, ((i > WATER_LEN) ? WATER_LEN : i)+1); } /* * check for bad chars in the low water mark */ for (p=cur->low, i=0; *p && isascii(*p) && isdigit(*p); ++p, ++i) { } if (*p) { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: line %d <%s> from %s has non-digits in low water\n", program, cnt+1, cur->name, cur->low); } cur->ignore |= ERROR_FORMAT; continue; } /* * check for excessive low water length */ if (i > WATER_LEN) { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: line %d <%s> from %s low water len: %d < %d\n", program, cnt+1, cur->name, cur->hi, i, WATER_LEN); } cur->ignore |= ERROR_FORMAT; continue; } /* * if the low water length is too small, malloc and resize */ if (i != WATER_LEN) { p = malloc(WATER_LEN+1); if (p == NULL) { fprintf(stderr, "%s: unable to malloc %d char low water string\n", program, WATER_LEN+1); exit(12); } memcpy(p, cur->low, ((i > WATER_LEN) ? WATER_LEN : i)+1); } /* check for a bad group type */ switch (cur->type[0]) { case 'y': case 'm': case 'j': case 'n': case 'x': if (cur->type[1] != '\0') { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: line %d <%s> from %s has a bad newsgroup type\n", program, cnt+1, cur->name, host); } cur->ignore |= ERROR_BADTYPE; } break; case '=': if (cur->type[1] == '\0') { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: line %d <%s> from %s has an empty =group name\n", program, cnt+1, cur->name, host); } cur->ignore |= ERROR_BADTYPE; } break; default: if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: line %d <%s> from %s has an unknown newsgroup type\n", program, cnt+1, cur->name, host); } cur->ignore |= ERROR_BADTYPE; break; } if (cur->ignore & ERROR_BADTYPE) { continue; } /* if an = type, check for bad = name */ if (cur->type[0] == '=' && bad_grpname(&(cur->type[1]), num_check)) { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: line %d <%s> from %s is equivalenced to a bad name: <%s>\n", program, cnt+1, cur->name, host, (cur->type) ? cur->type : "NULL"); } cur->ignore |= ERROR_EQNAME; continue; } /* if an = type, check for long = name if requested */ if (cur->type[0] == '=' && s_flag > 0 && strlen(&(cur->type[1])) > s_flag) { if (!QUIET(hostid)) { (void) fprintf(stderr, "%s: line %d <%s> from %s is equivalenced to a long name: <%s>\n", program, cnt+1, cur->name, host, (cur->type) ? cur->type : "NULL"); } cur->ignore |= ERROR_EQNAME; continue; } /* count this entry which will be used */ ++ucnt; } if (D_BUG) { fprintf(stderr, "%s: STATUS: read %d groups, will merge %d groups from %s\n", program, cnt, ucnt, host); } /* count the errors */ *errs = cnt - ucnt; if (D_BUG) { fprintf(stderr, "%s: STATUS: found %d line errors from %s\n", program, *errs, host); } /* determine why we stopped */ if (QIOerror(qp)) { (void) fprintf(stderr, "%s: can't read temp file for %s at line %d, %s\n", program, host, cnt, strerror(errno)); exit(13); } else if (QIOtoolong(qp)) { (void) fprintf(stderr, "%s: line %d from host %s is too long\n", program, cnt, host); exit(14); } /* all done */ if (is_file) { QIOclose(qp); } else { CAclose(); (void)fprintf(ToServer, "quit\r\n"); (void)fclose(ToServer); (void)fgets(buff, sizeof buff, FromServer); (void)fclose(FromServer); } return ret; } /* * bad_grpname - test if the string is a valid group name * * Newsgroup names must consist of only alphanumeric chars and * characters from the following regular expression: * * [.+-_] * * One cannot have two '.'s in a row. The first character must be * alphanumeric. The character following a '.' must be alphanumeric. * The name cannot end in a '.' character. * * If we are checking for all numeric compnents, (see num_chk) then * a component cannot be all numeric. I.e,. there must be a non-numeric * character in the name, there must be a non-numeric character between * the start and the first '.', there must be a non-numeric character * between two '.'s anmd there must be a non-numeric character between * the last '.' and the end. * * given: * name newsgroup name to check * num_chk TRUE => all numeric newsgroups components are invalid * FALSE => do not check for numeric newsgroups * * returns: * 0 group is ok * 1 group is bad */ static int bad_grpname(name, num_chk) char *name; /* newsgroup name to check */ int num_chk; /* TRUE => check for numeric newsgroup */ { char *p; int non_num; /* TRUE => found a non-numeric, non-. character */ int level; /* group levels (.'s) */ /* firewall */ if (name == NULL) { return 1; } /* must start with a alpha numeric ascii character */ if (!isascii(name[0])) { return 1; } /* set non_num as needed */ if (isalpha(name[0])) { non_num = TRUE; } else if (isdigit(name[0])) { non_num = FALSE; } else { return 1; } /* scan each char */ level = 0; for (p=name+1; *p; ++p) { /* name must contain ASCII chars */ if (!isascii(*p)) { return 1; } /* alpha chars are ok */ if (isalpha(*p)) { non_num = TRUE; continue; } /* numeric chars are ok */ if (isdigit(*p)) { continue; } /* +, - and _ are ok */ if (*p == '+' || *p == '-' || *p == '_') { non_num = TRUE; continue; } /* check for the '.' case */ if (*p == '.') { /* * look for groups that are too deep, if requested by -g */ if (g_flag > 0 && ++level > g_flag) { /* we are too deep */ return 1; } /* * A '.' is ok as long as the next character is alphanumeric. * This imples that '.' cannot before a previous '.' and * that it cannot be at the end. * * If we are checking for all numeric compnents, then * '.' is ok if we saw a non-numeric char before the * last '.', or before the beginning if no previous '.' * has been seen. */ if ((!num_chk || non_num) && isascii(*(p+1)) && isalnum(*(p+1))) { ++p; /* '.' is ok, and so is the next char */ if (isdigit(*p)) { /* reset non_num as needed */ non_num = FALSE; } else { non_num = TRUE; } continue; } } /* this character must be invalid */ return 1; } if (num_chk && !non_num) { /* last component is all numeric */ return 1; } /* the name must be ok */ return 0; } /* * get_ignore - get the ignore list from an ignore file * * given: * filename name of the ignore file to read * *len pointer to length of ignore return array * * returns: * returns a malloced ignore pattern array, changes len * * An ignore file is of the form: * * # this is a comment which is ignored * # comments begin at the first # character * # comments may follow text on the same line * * # blank lines are ignored too * * # lines are [ic] pattern [ type] ... * i foo.* # ignore foo.* groups, * c foo.bar m # but check foo.bar if moderated * c foo.keep.* # and check foo.keep.* * i foo.keep.* j =alt.* # except when foo.keep.* is junked * # or equivalenced to an alt.* group * * The 'i' value means ignore, 'c' value means 'compare'. The last pattern * that matches a group determines the fate of the group. By default all * groups are included. * * NOTE: Only one '=name' is allowed per line. * "=" is considered to be equivalent to "=*". */ static struct pat * get_ignore(filename, len) char *filename; /* name of the ignore file to read */ int *len; /* length of return array */ { QIOSTATE *qp; /* QIO ignore file state */ char *line; /* the line just read */ struct pat *ret; /* array of ignore patterns to return */ struct pat *cur; /* current pattern entry being formed */ int max; /* max length (in elements) of ret */ int linenum; /* current line number */ char *p; int i; /* firewall */ if (filename == NULL) { fprintf(stderr, "%s: internal error #3, filename is NULL\n", program); exit(15); } if (len == NULL) { fprintf(stderr, "%s: internal error #4, len is NULL\n", program); exit(16); } if (D_BUG) { fprintf(stderr, "%s: STATUS: reading ignore file: %s\n", program, filename); } /* setup return array */ ret = (struct pat *) malloc(CHUNK * sizeof(struct grp)); if (ret == NULL) { fprintf(stderr, "%s: malloc of %d grp elements failed\n", program, CHUNK); exit(17); } max = CHUNK; /* setup to read the ignore file data quickly */ if ((qp = QIOopen(filename, QIO_BUFFER)) == NULL) { (void) fprintf(stderr, "%s: can't read ignore file: %s\n", program, filename); exit(18); } /* scan server's output, displaying appropriate lines */ *len = 0; for (linenum = 1; (line = QIOread(qp)) != NULL; ++linenum) { /* expand return array if needed */ if (*len >= max) { max += CHUNK; ret = (struct pat *) realloc(ret, sizeof(struct pat)*max); if (ret == NULL) { fprintf(stderr, "%s: unable to realloc %d pat elements\n", program, max); exit(19); } } /* remove any trailing comments */ p = strchr(line, '#'); if (p != NULL) { *p = '\0'; } /* remove any trailing spaces and tabs */ for (p = &line[strlen(line)-1]; p >= line && (*p == ' ' || *p == '\t'); --p) { *p = '\0'; } /* ignore line if the remainder of the line is empty */ if (line[0] == '\0') { continue; } /* ensure that the line starts with an i or c token */ if ((line[0] != 'i' && line[0] != 'c') || (line[1] != ' ' && line[1] != '\t')) { fprintf(stderr, "%s: first token is not i or c in line %d of %s\n", program, linenum, filename); exit(20); } /* ensure that the second newsgroup pattern token follows */ p = strtok(line+2, " \t"); if (p == NULL) { fprintf(stderr, "%s: did not find 2nd field in line %d of %s\n", program, linenum, filename); exit(21); } /* setup the next return element */ cur = &ret[*len]; cur->pat = NULL; cur->type_match = 0; cur->y_type = 0; cur->m_type = 0; cur->n_type = 0; cur->j_type = 0; cur->x_type = 0; cur->eq_type = 0; cur->epat = NULL; cur->ignore = (line[0] == 'i'); /* obtain a copy of the newsgroup pattern token */ i = strlen(p); cur->pat = (char *) malloc(i+1); if (cur->pat == NULL) { fprintf(stderr, "%s: unable to malloc %d char line buffer\n", program, linenum+1); exit(22); } strncpy(cur->pat, p, i); cur->pat[i] = '\0'; /* process any other type tokens */ for (p=strtok(NULL, " \t"), i=3; p != NULL; p=strtok(NULL, " \t"), ++i) { /* ensure that this next token is a valid type */ switch (p[0]) { case 'y': case 'm': case 'j': case 'n': case 'x': if (p[1] != '\0') { fprintf(stderr, "%s: field %d on line %d of %s not a valid type\n", program, i, linenum, filename); fprintf(stderr, "%s: valid types are a char from [ymnjx=] or =name\n", program); exit(23); } break; case '=': break; default: fprintf(stderr, "%s: field %d on line %d of %s is not a valid type\n", program, i, linenum, filename); fprintf(stderr, "%s: valid types are a char from [ymnjx=] or =name\n", program); exit(24); } /* note that we have a type specific pattern */ cur->type_match = 1; /* ensure that type is not a duplicate */ if ((p[0] == 'y' && cur->y_type) || (p[0] == 'm' && cur->m_type) || (p[0] == 'n' && cur->n_type) || (p[0] == 'j' && cur->j_type) || (p[0] == 'x' && cur->x_type) || (p[0] == '=' && cur->eq_type)) { fprintf(stderr, "%s: only one %c type allowed per line\n", program, p[0]); fprintf(stderr, "%s: field %d on line %d of %s is a duplicate type\n", program, i, linenum, filename); exit(25); } /* note what we have seen */ switch (p[0]) { case 'y': cur->y_type = 1; break; case 'm': cur->m_type = 1; break; case 'j': cur->j_type = 1; break; case 'n': cur->n_type = 1; break; case 'x': cur->x_type = 1; break; case '=': cur->eq_type = 1; if (p[0] == '=' && p[1] != '\0') { /* obtain a copy of the newsgroup type token */ i = strlen(p+1); cur->epat = (char *) malloc(i+1); if (cur->epat == NULL) { fprintf(stderr, "%s: unable to malloc %d char type buffer\n", program, i+1); exit(26); } strncpy(cur->epat, p+1, i); cur->epat[i] = '\0'; } break; } /* object if too many fields */ if (i-3 > TYPECNT) { fprintf(stderr, "%s: too many fields on line %d of %s\n", program, linenum, filename); exit(27); } } /* count another pat element */ ++(*len); } /* return the pattern array */ return ret; } /* * ignore - ignore newsgroups given an ignore list * * given: * grp array of groups * grplen length of grp array in elements * igcl array of ignore * iglen length of igcl array in elements */ static void ignore(grp, grplen, igcl, iglen) struct grp *grp; /* array of groups */ int grplen; /* length of grp array in elements */ struct pat *igcl; /* array of ignore patterns */ int iglen; /* length of igcl array in elements */ { struct grp *gp; /* current group element being examined */ struct pat *pp; /* current pattern element being examined */ int g; /* current group index number */ int p; /* current pattern index number */ int ign; /* 1 => ignore this group, 0 => check it */ int icnt; /* groups ignored */ int ccnt; /* groups to be checked */ /* firewall */ if (grp == NULL) { fprintf(stderr, "%s: internal error #5, grp is NULL\n", program); exit(28); } if (igcl == NULL) { fprintf(stderr, "%s: internal error #6, igcl is NULL\n", program); exit(29); } if (D_BUG) { fprintf(stderr, "%s: STATUS: determining which groups to ignore\n", program); } /* if nothing to do, return quickly */ if (grplen <= 0 || iglen <= 0) { return; } /* examine each group */ icnt = 0; ccnt = 0; for (g=0; g < grplen; ++g) { /* check the group to examine */ gp = &grp[g]; if (gp->ignore) { /* already ignored no need to examine */ continue; } /* check group against all patterns */ ign = 0; for (p=0, pp=igcl; p < iglen; ++p, ++pp) { /* if pattern has a specific type, check it first */ if (pp->type_match) { /* specific type required, check for match */ switch (gp->type[0]) { case 'y': if (! pp->y_type) continue; /* pattern does not apply */ break; case 'm': if (! pp->m_type) continue; /* pattern does not apply */ break; case 'n': if (! pp->n_type) continue; /* pattern does not apply */ break; case 'j': if (! pp->j_type) continue; /* pattern does not apply */ break; case 'x': if (! pp->x_type) continue; /* pattern does not apply */ break; case '=': if (! pp->eq_type) continue; /* pattern does not apply */ if (pp->epat != NULL && !wildmat(&gp->type[1], pp->epat)) { /* equiv pattern doesn't match, patt does not apply */ continue; } break; } } /* perform a match on group name */ if (wildmat(gp->name, pp->pat)) { /* this pattern fully matches, use the ignore value */ ign = pp->ignore; } } /* if this group is to be ignored, note it */ if (ign) { switch (gp->hostid) { case HOSTID1: if (ign_host1_flag) { gp->ignore |= CHECK_IGNORE; ++icnt; } break; case HOSTID2: if (ign_host2_flag) { gp->ignore |= CHECK_IGNORE; ++icnt; } break; default: fprintf(stderr, "%s: newsgroup %s bad hostid: %d\n", program, gp->name, gp->hostid); exit(30); } } else { ++ccnt; } } if (D_BUG) { fprintf(stderr, "%s: STATUS: examined %d groups: %d ignored, %d to be checked\n", program, grplen, icnt, ccnt); } } /* * merge_cmp - qsort compare function for later group merge * * given: * a group a to compare * b group b to compare * * returns: * >0 a > b * 0 a == b elements match (fatal error if a and b are different) * <0 a < b * * To speed up group comparison, we compare by the following items listed * in order of sorting: * * group name * hostid (host1 ahead of host2) * linenum (active file line number) */ static int merge_cmp(arg_a, arg_b) const void *arg_a; /* first qsort compare arg */ const void *arg_b; /* first qsort compare arg */ { const struct grp *a = arg_a; /* group a to compare */ const struct grp *b = arg_b; /* group b to compare */ int i; /* firewall */ if (a == b) { /* we guess this could happen */ return(0); } /* compare group names */ i = strcmp(a->name, b->name); if (i != 0) { return i; } /* compare hostid's */ if (a->hostid != b->hostid) { if (a->hostid > b->hostid) { return 1; } else { return -1; } } /* compare active line numbers */ if (a->linenum != b->linenum) { if (a->linenum > b->linenum) { return 1; } else { return -1; } } /* two different elements match, this should not happen! */ fprintf(stderr, "%s: two internal grp elements match!\n", program); exit(31); /*NOTREACHED*/ } /* * merge_grps - compare groups from both hosts * * given: * grp array of groups * grplen length of grp array in elements * host1 name of host with HOSTID1 * host2 name of host with HOSTID2 * * This routine will select which groups to output form a merged active file. */ static void merge_grps(grp, grplen, host1, host2) struct grp *grp; /* array of groups */ int grplen; /* length of grp array in elements */ char *host1; /* name of host with HOSTID1 */ char *host2; /* name of host with HOSTID2 */ { int cur; /* current group index being examined */ int nxt; /* next group index being examined */ int outcnt; /* groups to output */ int rmcnt; /* groups to remove */ int h1_probs; /* =type problem groups from host1 */ int h2_probs; /* =type problem groups from host2 */ /* firewall */ if (grp == NULL) { fprintf(stderr, "%s: internal error #7, grp is NULL\n", program); exit(32); } /* sort groups for the merge */ if (D_BUG) { fprintf(stderr, "%s: STATUS: sorting groups\n", program); } qsort((char *)grp, grplen, sizeof(grp[0]), merge_cmp); /* mark =type problem groups from host2, if needed */ h2_probs = mark_eq_probs(grp, grplen, l_host2_flag, host1, host2); /* * We will walk thru the sorted group array, looking for pairs * among the groups that we have not already ignored. * * If a host has duplicate groups, then the duplicates will * be next to each other. * * If both hosts have the name group, they will be next to each other. */ if (D_BUG) { fprintf(stderr, "%s: STATUS: merging groups\n", program); } outcnt = 0; rmcnt = 0; for (cur=0; cur < grplen; cur=nxt) { /* determine the next group index */ nxt = cur+1; /* skip if this group is ignored */ if (grp[cur].ignore) { continue; } /* assert: cur is not ignored */ /* check for duplicate groups from the same host */ while (nxt < grplen) { /* mark the later as a duplicate */ if (grp[cur].hostid == grp[nxt].hostid && strcmp(grp[cur].name, grp[nxt].name) == 0) { grp[nxt].ignore |= ERROR_DUP; if (!QUIET(grp[cur].hostid)) { fprintf(stderr, "%s: lines %d and %d from %s refer to the same group\n", program, grp[cur].linenum, grp[nxt].linenum, ((grp[cur].hostid == HOSTID1) ? host1 : host2)); } ++nxt; } else { break; } } /* assert: cur is not ignored */ /* assert: cur & nxt are not the same group from the same host */ /* if nxt is ignored, look for the next non-ignored group */ while (grp[nxt].ignore && nxt < grplen) { ++nxt; } /* assert: cur is not ignored */ /* assert: nxt is not ignored or is beyond end */ /* assert: cur & nxt are not the same group from the same host */ /* case: cur and nxt are the same group */ if (nxt < grplen && strcmp(grp[cur].name, grp[nxt].name) == 0) { /* assert: cur is HOSTID1 */ if (grp[cur].hostid != HOSTID1) { fprintf(stderr, "%s: internal error #8, grp[%d].hostid:%d != %d\n", program, cur, grp[cur].hostid, HOSTID1); exit(33); } /* * Both hosts have the same group. Make host1 group type * match host2. (it may already) */ grp[cur].output = 1; grp[cur].outhi = (host2_hilow_all ? grp[nxt].hi : grp[cur].hi); grp[cur].outlow = (host2_hilow_all ? grp[nxt].low : grp[cur].low); grp[cur].outtype = grp[nxt].type; ++outcnt; /* do not process nxt, skip to the one beyond */ ++nxt; /* case: cur and nxt are different groups */ } else { /* * if cur is host2, then host1 doesn't have it, so output it */ if (grp[cur].hostid == HOSTID2) { grp[cur].output = 1; grp[cur].outhi = (host2_hilow_newgrp ? grp[cur].hi : DEF_HI); grp[cur].outlow = (host2_hilow_newgrp ? grp[cur].low : DEF_LOW); grp[cur].outtype = grp[cur].type; ++outcnt; /* * If cur is host1, then host2 doesn't have it. * Mark for removal if -m was not given. */ } else { grp[cur].output = 1; grp[cur].outhi = grp[cur].hi; grp[cur].outlow = grp[cur].low; grp[cur].outtype = grp[cur].type; if (! m_flag) { grp[cur].remove = 1; ++rmcnt; } } /* if no more groups to examine, we are done */ if (nxt >= grplen) { break; } } } /* mark =type problem groups from host1, if needed */ h1_probs = mark_eq_probs(grp, grplen, l_host1_flag, host1, host2); /* all done */ if (D_BUG) { fprintf(stderr, "%s: STATUS: sort-merge passed thru %d groups\n", program, outcnt); fprintf(stderr, "%s: STATUS: sort-merge marked %d groups for removal\n", program, rmcnt); fprintf(stderr, "%s: STATUS: marked %d =type error groups from host1\n", program, h1_probs); fprintf(stderr, "%s: STATUS: marked %d =type error groups from host2\n", program, h2_probs); } return; } /* * active_cmp - qsort compare function for active file style output * * given: * a group a to compare * b group b to compare * * returns: * >0 a > b * 0 a == b elements match (fatal error if a and b are different) * <0 a < b * * This sort will sort groups so that the lines that will we output * host1 lines followed by host2 lines. Thus, we will sort by * the following keys: * * hostid (host1 ahead of host2) * linenum (active file line number) */ static int active_cmp(arg_a, arg_b) const void *arg_a; /* first qsort compare arg */ const void *arg_b; /* first qsort compare arg */ { const struct grp *a = arg_a; /* group a to compare */ const struct grp *b = arg_b; /* group b to compare */ /* firewall */ if (a == b) { /* we guess this could happen */ return(0); } /* compare hostid's */ if (a->hostid != b->hostid) { if (a->hostid > b->hostid) { return 1; } else { return -1; } } /* compare active line numbers */ if (a->linenum != b->linenum) { if (a->linenum > b->linenum) { return 1; } else { return -1; } } /* two different elements match, this should not happen! */ fprintf(stderr, "%s: two internal grp elements match!\n", program); exit(34); /*NOTREACHED*/ } /* * output_grps - output the result of the merge * * given: * grp array of groups * grplen length of grp array in elements */ static void output_grps(grp, grplen) struct grp *grp; /* array of groups */ int grplen; /* length of grp array in elements */ { int add; /* number of groups added */ int change; /* number of groups changed */ int remove; /* number of groups removed */ int scan_ret; /* scan_spool_dir() return */ int no_new_dir; /* number of new groups with missing/empty dirs */ int new_dir; /* number of new groupsm, non-empty dir no water chg */ int water_change; /* number of new groups where hi&low water changed */ int work; /* adds + changes + removals */ int same; /* the number of groups the same */ int ignore; /* host1 newsgroups to ignore */ int not_done; /* exec errors and execs not performed */ int rm_cycle; /* 1 => removals only, 0 => adds & changes only */ int sleep_msg; /* 1 => -o x sleep message was given */ int top_ignore; /* number of groups ignored because of no top level */ int restore; /* host1 groups restored due to -o a1 */ double host1_same; /* % of host1 that is the same */ int i; /* firewall */ if (grp == NULL) { fprintf(stderr, "%s: internal error #9, grp is NULL\n", program); exit(35); } /* * If -a1 was given, mark for output any host1 newsgroup that was * simply ignored due to the -i ign_file. */ if (host1_ign_print) { restore = 0; for (i=0; i < grplen; ++i) { if (grp[i].hostid == HOSTID1 && (grp[i].ignore == CHECK_IGNORE || grp[i].ignore == CHECK_TYPE || grp[i].ignore == (CHECK_IGNORE|CHECK_TYPE))) { /* force group to output and not be ignored */ grp[i].ignore = 0; grp[i].output = 1; grp[i].remove = 0; grp[i].outhi = grp[i].hi; grp[i].outlow = grp[i].low; grp[i].outtype = grp[i].type; ++restore; } } if (D_BUG) { fprintf(stderr, "%s: STATUS: restored %d host1 groups\n", program, restore); } } /* * If -T, ignore new top level groups from host2 */ if (no_new_hier) { top_ignore = 0; for (i=0; i < grplen; ++i) { /* look at new newsgroups */ if (grp[i].hostid == HOSTID2 && grp[i].output != 0 && new_top_hier(grp[i].name)) { /* no top level ignore this new group */ grp[i].ignore |= CHECK_HIER; grp[i].output = 0; if (D_BUG) { fprintf(stderr, "%s: ignore new newsgroup: %s, new hierarchy\n", program, grp[i].name); } ++top_ignore; } } if (D_SUMMARY) { fprintf(stderr, "%s: STATUS: ignored %d new newsgroups due to new hierarchy\n", program, top_ignore); } } /* sort by active file order if active style output (-a) */ if (o_flag == OUTPUT_ACTIVE) { if (D_BUG) { fprintf(stderr, "%s: STATUS: sorting groups in output order\n", program); } qsort((char *)grp, grplen, sizeof(grp[0]), active_cmp); } /* * Determine the % of lines from host1 active file that remain unchanged * ignoring any low/high water mark changes. * * Determine the number of old groups that will remain the same * the number of new groups that will be added. */ add = 0; change = 0; remove = 0; same = 0; ignore = 0; no_new_dir = 0; new_dir = 0; water_change = 0; for (i=0; i < grplen; ++i) { /* skip non-output ... */ if (grp[i].output == 0) { if (grp[i].hostid == HOSTID1) { ++ignore; } continue; /* case: group needs removal */ } else if (grp[i].remove) { ++remove; /* case: group is from host2, so we need a newgroup */ } else if (grp[i].hostid == HOSTID2) { ++add; /* case: group is from host1, but the type changed */ } else if (grp[i].type != grp[i].outtype && strcmp(grp[i].type,grp[i].outtype) != 0) { ++change; /* case: group did not change */ } else { ++same; } } work = add+change+remove; if (same+work+host1_errs <= 0) { /* no lines, no work, no errors == nothing changed == 100% the same */ host1_same = (double)100.0; } else { /* calculate % unchanged */ host1_same = (double)100.0 * ((double)same / (double)(same+work+host1_errs)); } if (D_BUG) { fprintf(stderr, "%s: STATUS: same=%d add=%d, change=%d, remove=%d\n", program, same, add, change, remove); fprintf(stderr, "%s: STATUS: ignore=%d, work=%d, err=%d\n", program, ignore, work, host1_errs); fprintf(stderr, "%s: STATUS: same+work+err=%d, host1_same=%.2f%%\n", program, same+work+host1_errs, host1_same); } /* * Bail out if we too few lines in host1 active file (ignoring * low/high water mark changes) remaining unchanged. * * We define change as: * * line errors from host1 active file * newsgroups to be added to host1 * newsgroups to be removed from host1 * newsgroups to be change in host1 */ if (host1_same < p_flag) { fprintf(stderr, "%s: HALT: lines unchanged: %.2f%% < min change limit: %.2f%%\n", program, host1_same, p_flag); fprintf(stderr, "\tNo output or commands executed. Determine if the degree of\n"); fprintf(stderr, "\tchanges is ok and re-execute with a lower -p value or\n"); fprintf(stderr, "\tfixed the problem.\n"); exit(36); } /* * look at all groups * * If we are not producing active file output, we must do removals * before we do any adds and changes. * * We recalculate the work stats in finer detail as well as noting how * many actions were successful. */ add = 0; change = 0; remove = 0; same = 0; ignore = 0; work = 0; not_done = 0; sleep_msg = 0; rm_cycle = ((o_flag == OUTPUT_ACTIVE) ? 0 : 1); do { for (i=0; i < grplen; ++i) { /* if -o Ax, output ignored non-error groups too */ /* * skip non-output ... * * but if '-a' and active output mode, then don't skip ignored, * non-error, non-removed groups from host1 */ if (grp[i].output == 0) { if (grp[i].hostid == HOSTID1) { ++ignore; } continue; } /* case: output active lines */ if (o_flag == OUTPUT_ACTIVE) { /* case: group needs removal */ if (grp[i].remove) { ++remove; ++work; /* case: group will be kept */ } else { /* if -S spool and new group, reset hi & low water mark */ if (spool != NULL && grp[i].hostid == HOSTID2) { scan_ret = scan_spool_dir(grp+i); switch (scan_ret) { case NEWGRP_EMPTY: ++no_new_dir; break; case NEWGRP_NOCHG: ++new_dir; break; case NEWGRP_CHG: ++water_change; break; default: fprintf(stderr, "%s: internal error #10, %s:%d\n", "bad scan_spool_dir return", program, scan_ret); exit(37); } } /* output in active file format */ printf("%s %s %s %s\n", grp[i].name, grp[i].outhi, grp[i].outlow, grp[i].outtype); /* if -v level is high enough, do group accounting */ if (D_IF_SUMM) { /* case: group is from host2, so we need a newgroup */ if (grp[i].hostid == HOSTID2) { ++add; ++work; /* case: group is from host1, but the type changed */ } else if (grp[i].type != grp[i].outtype && strcmp(grp[i].type,grp[i].outtype) != 0) { ++change; ++work; /* case: group did not change */ } else { ++same; } } } /* case: output ctlinnd commands */ } else if (o_flag == OUTPUT_CTLINND) { /* case: group needs removal */ if (grp[i].remove) { /* output rmgroup */ if (rm_cycle) { printf("ctlinnd rmgroup %s\n", grp[i].name); ++remove; ++work; } /* case: group is from host2, so we need a newgroup */ } else if (grp[i].hostid == HOSTID2) { /* output newgroup */ if (! rm_cycle) { printf("ctlinnd newgroup %s %s %s\n", grp[i].name, grp[i].outtype, new_name); ++add; ++work; } /* case: group is from host1, but the type changed */ } else if (grp[i].type != grp[i].outtype && strcmp(grp[i].type,grp[i].outtype) != 0) { /* output changegroup */ if (! rm_cycle) { printf("ctlinnd changegroup %s %s\n", grp[i].name, grp[i].outtype); ++change; ++work; } /* case: group did not change */ } else { if (! rm_cycle) { ++same; } } /* case: exec ctlinnd commands */ } else if (o_flag == OUTPUT_EXEC || o_flag == OUTPUT_IEXEC) { /* warn about sleeping if needed and first time */ if (o_flag == OUTPUT_EXEC && z_flag > 0 && sleep_msg == 0) { if (D_SUMMARY) { fprintf(stderr, "%s: will sleep %d seconds before each fork/exec\n", program, z_flag); } sleep_msg = 1; } /* case: group needs removal */ if (grp[i].remove) { /* exec rmgroup */ if (rm_cycle) { if (D_REPORT && o_flag == OUTPUT_EXEC) { fprintf(stderr, "rmgroup %s\n", grp[i].name); } if (! exec_cmd(o_flag, "rmgroup", grp[i].name, NULL, NULL)) { ++not_done; } else { ++remove; ++work; } } /* case: group is from host2, so we need a newgroup */ } else if (grp[i].hostid == HOSTID2) { /* exec newgroup */ if (!rm_cycle) { if (D_REPORT && o_flag == OUTPUT_EXEC) { fprintf(stderr, "newgroup %s %s %s\n", grp[i].name, grp[i].outtype, new_name); } if (! exec_cmd(o_flag, "newgroup", grp[i].name, grp[i].outtype, new_name)) { ++not_done; } else { ++add; ++work; } } /* case: group is from host1, but the type changed */ } else if (grp[i].type != grp[i].outtype && strcmp(grp[i].type,grp[i].outtype) != 0) { /* exec changegroup */ if (!rm_cycle) { if (D_REPORT && o_flag == OUTPUT_EXEC) { fprintf(stderr, "changegroup %s %s\n", grp[i].name, grp[i].outtype); } if (! exec_cmd(o_flag, "changegroup", grp[i].name, grp[i].outtype, NULL)) { ++not_done; } else { ++change; ++work; } } /* case: group did not change */ } else { if (! rm_cycle) { ++same; } } } } } while (--rm_cycle >= 0); /* final accounting, if -v */ if (D_SUMMARY || (D_IF_SUMM && (work > 0 || not_done > 0))) { fprintf(stderr, "%s: STATUS: %d group(s)\n", program, add+remove+change+same); fprintf(stderr, "%s: STATUS: %d group(s)%s added\n", program, add, ((o_flag == OUTPUT_EXEC || o_flag == OUTPUT_IEXEC) ? "" : " to be")); fprintf(stderr, "%s: STATUS: %d group(s)%s removed\n", program, remove, ((o_flag == OUTPUT_EXEC || o_flag == OUTPUT_IEXEC) ? "" : " to be")); fprintf(stderr, "%s: STATUS: %d group(s)%s changed\n", program, change, ((o_flag == OUTPUT_EXEC || o_flag == OUTPUT_IEXEC) ? "" : " to be")); fprintf(stderr, "%s: STATUS: %d group(s) %s the same\n", program, same, ((o_flag == OUTPUT_EXEC || o_flag == OUTPUT_IEXEC) ? "remain" : "are")); fprintf(stderr, "%s: STATUS: %.2f%% of lines unchanged\n", program, host1_same); fprintf(stderr, "%s: STATUS: %d group(s) ignored\n", program, ignore); if (o_flag == OUTPUT_EXEC || o_flag == OUTPUT_IEXEC) { fprintf(stderr, "%s: STATUS: %d exec(s) not performed\n", program, not_done); } if (spool != NULL) { fprintf(stderr, "%s: STATUS: no/empty dir:%d, dir no hi/low chg:%d hi/low chg:%d\n", program, no_new_dir, new_dir, water_change); } } } /* * error_mark - mark for removal, error groups from a given host * * given: * grp array of groups * grplen length of grp array in elements * hostid host to mark error groups for removal */ static void error_mark(grp, grplen, hostid) struct grp *grp; /* array of groups */ int grplen; /* length of grp array in elements */ int hostid; /* host to mark error groups for removal */ { int i; int errcnt; /* firewall */ if (grp == NULL) { fprintf(stderr, "%s: internal error #11, grp is NULL\n", program); exit(38); } /* loop thru groups, looking for error groups from a given host */ errcnt = 0; for (i=0; i < grplen; ++i) { /* skip if not from hostid */ if (grp[i].hostid != hostid) { continue; } /* mark for removal if an error group not already removed */ if (IS_ERROR(grp[i].ignore)) { /* mark for removal */ if (grp[i].output != 1 || grp[i].remove != 1) { grp[i].output = 1; grp[i].remove = 1; } ++errcnt; } } /* all done */ if (D_SUMMARY || (D_IF_SUMM && errcnt > 0)) { fprintf(stderr, "%s: STATUS: marked %d error groups for removal\n", program, errcnt); } return; } /* * eq_merge_cmp - qsort compare function for =type group processing * * given: * a =group a to compare * b =group b to compare * * returns: * >0 a > b * 0 a == b elements match (fatal error if a and b are different) * <0 a < b * * To speed up group comparison, we compare by the following items listed * in order of sorting: * * skip (non-skipped groups after skipped ones) * group equiv name * group name * hostid (host1 ahead of host2) * linenum (active file line number) */ static int eq_merge_cmp(arg_a, arg_b) const void *arg_a; /* first qsort compare arg */ const void *arg_b; /* first qsort compare arg */ { const struct eqgrp *a = arg_a; /* group a to compare */ const struct eqgrp *b = arg_b; /* group b to compare */ int i; /* firewall */ if (a == b) { /* we guess this could happen */ return(0); } /* compare skip values */ if (a->skip != b->skip) { if (a->skip > b->skip) { /* a is skipped, b is not */ return 1; } else { /* b is skipped, a is not */ return -1; } } /* compare the names the groups are equivalenced to */ i = strcmp(a->eq, b->eq); if (i != 0) { return i; } /* compare the group names themselves */ i = strcmp(a->g->name, b->g->name); if (i != 0) { return i; } /* compare hostid's */ if (a->g->hostid != b->g->hostid) { if (a->g->hostid > b->g->hostid) { return 1; } else { return -1; } } /* compare active line numbers */ if (a->g->linenum != b->g->linenum) { if (a->g->linenum > b->g->linenum) { return 1; } else { return -1; } } /* two different elements match, this should not happen! */ fprintf(stderr, "%s: two internal eqgrp elements match!\n", program); exit(39); /*NOTREACHED*/ } /* * mark_eq_probs - mark =type groups from a given host that have problems * * given: * grp sorted array of groups * grplen length of grp array in elements * hostid host to mark error groups for removal, or NOHOST * host1 name of host with HOSTID1 * host2 name of host with HOSTID2 * * This function assumes that the grp array has been sorted by name. */ static int mark_eq_probs(grp, grplen, hostid, host1, host2) struct grp *grp; /* array of groups */ int grplen; /* length of grp array in elements */ int hostid; /* host to mark error groups for removal */ char *host1; /* name of host with HOSTID1 */ char *host2; /* name of host with HOSTID2 */ { struct eqgrp *eqgrp; /* =type pointer array */ int eq_cnt; /* number of =type groups from host */ int new_eq_cnt; /* number of =type groups remaining */ int missing; /* =type groups equiv to missing groups */ int cycled; /* =type groups equiv to themselves */ int chained; /* =type groups in long chain or loop */ int cmp; /* strcmp of two names */ int step; /* equiv loop step */ int i; int j; /* firewall */ if (grp == NULL) { fprintf(stderr, "%s: internal error #12, grp is NULL\n", program); exit(40); } if (hostid == NOHOST) { /* nothing to detect, nothing else to do */ return 0; } /* count the =type groups from hostid that are not in error */ eq_cnt = 0; for (i=0; i < grplen; ++i) { if (grp[i].hostid == hostid && ! IS_ERROR(grp[i].ignore) && grp[i].type != NULL && grp[i].type[0] == '=') { ++eq_cnt; } } if (D_BUG && hostid != NOHOST) { fprintf(stderr, "%s: STATUS: host%d has %d =type groups\n", program, hostid, eq_cnt); } /* if no groups, then there is nothing to do */ if (eq_cnt == 0) { return 0; } /* setup the =group record array */ eqgrp = (struct eqgrp *)malloc(eq_cnt * sizeof(eqgrp[0])); if (eqgrp == NULL) { fprintf(stderr, "%s: unable to malloc %d grp pointers\n", program, eq_cnt); exit(41); } for (i=0, j=0; i < grplen && j < eq_cnt; ++i) { if (grp[i].hostid == hostid && ! IS_ERROR(grp[i].ignore) && grp[i].type != NULL && grp[i].type[0] == '=') { /* initialize record */ eqgrp[j].skip = 0; eqgrp[j].g = &grp[i]; eqgrp[j].eq = &(grp[i].type[1]); ++j; } } /* * try to resolve =type groups in at least EQ_LOOP equiv links */ new_eq_cnt = eq_cnt; missing = 0; cycled = 0; for (step=0; step < EQ_LOOP && new_eq_cnt >= 0; ++step) { /* sort the =group record array */ qsort((char *)eqgrp, eq_cnt, sizeof(eqgrp[0]), eq_merge_cmp); /* look for the groups to which =type group point at */ eq_cnt = new_eq_cnt; for (i=0, j=0; i < grplen && j < eq_cnt; ++i) { /* we will skip any group in error or from the wrong host */ if (grp[i].hostid != hostid || IS_ERROR(grp[i].ignore)) { continue; } /* we will skip any skipped eqgrp's */ if (eqgrp[j].skip) { /* try the same group against the next eqgrp */ --i; ++j; continue; } /* compare the =name of the eqgrp with the name of the grp */ cmp = strcmp(grp[i].name, eqgrp[j].eq); /* case: this group is pointed at by an eqgrp */ if (cmp == 0) { /* see if we have looped around to the original group name */ if (strcmp(grp[i].name, eqgrp[j].g->name) == 0) { /* note the detected loop */ if (! QUIET(hostid)) { fprintf(stderr, "%s: %s from %s line %d =loops around to itself\n", program, eqgrp[j].g->name, ((eqgrp[j].g->hostid == HOSTID1) ? host1 : host2), eqgrp[j].g->linenum); } eqgrp[j].g->ignore |= ERROR_EQLOOP; /* the =group is bad, so we don't need to bother with it */ eqgrp[j].skip = 1; --new_eq_cnt; ++cycled; --i; ++j; continue; } /* if =group refers to a valid group, we are done with it */ if (grp[i].type != NULL && grp[i].type[0] != '=') { eqgrp[j].skip = 1; --new_eq_cnt; /* otherwise note the equiv name */ } else { eqgrp[j].eq = &(grp[i].type[1]); } --i; ++j; /* case: we missed the =name */ } else if (cmp > 0) { /* mark the eqgrp in error */ eqgrp[j].g->ignore |= ERROR_NONEQ; if (! QUIET(hostid)) { fprintf(stderr, "%s: %s from %s line %d not equiv to a valid group\n", program, eqgrp[j].g->name, ((eqgrp[j].g->hostid == HOSTID1) ? host1 : host2), eqgrp[j].g->linenum); } /* =group is bad, so we don't need to bother with it anymore */ eqgrp[j].skip = 1; --new_eq_cnt; ++missing; ++j; } } /* any remaining non-skipped eqgrps are bad */ while (j < eq_cnt) { /* mark the eqgrp in error */ eqgrp[j].g->ignore |= ERROR_NONEQ; if (! QUIET(hostid)) { fprintf(stderr, "%s: %s from %s line %d isn't equiv to a valid group\n", program, eqgrp[j].g->name, ((hostid == HOSTID1) ? host1 : host2), eqgrp[j].g->linenum); } /* the =group is bad, so we don't need to bother with it anymore */ eqgrp[j].skip = 1; --new_eq_cnt; ++missing; ++j; } } /* note groups that are in a long chain or loop */ chained = new_eq_cnt; qsort((char *)eqgrp, eq_cnt, sizeof(eqgrp[0]), eq_merge_cmp); for (j=0; j < new_eq_cnt; ++j) { /* skip if already skipped */ if (eqgrp[j].skip == 1) { continue; } /* mark as a long loop group */ eqgrp[j].g->ignore |= ERROR_LONGLOOP; if (! QUIET(hostid)) { fprintf(stderr, "%s: %s from %s line %d in a long equiv chain or loop > %d\n", program, eqgrp[j].g->name, ((hostid == HOSTID1) ? host1 : host2), eqgrp[j].g->linenum, EQ_LOOP); } } /* all done */ if (D_BUG) { fprintf(stderr, "%s: %d =type groups from %s are not equiv to a valid group\n", program, missing, ((hostid == HOSTID1) ? host1 : host2)); fprintf(stderr, "%s: %d =type groups from %s are equiv to themselves\n", program, cycled, ((hostid == HOSTID1) ? host1 : host2)); fprintf(stderr, "%s: %d =type groups from %s are in a long chain or loop > %d\n", program, chained, ((hostid == HOSTID1) ? host1 : host2), EQ_LOOP); } free(eqgrp); return missing+cycled+chained; } /* * exec_cmd - exec a ctlinnd command in forked process * * given: * mode OUTPUT_EXEC or OUTPUT_IEXEC (interactive mode) * cmd "changegroup", "newgroup", "rmgroup" * grp name of group * type type of group or NULL * who newgroup creator or NULL * * returns: * 1 exec was performed * 0 exec was not performed */ static int exec_cmd(mode, cmd, grp, type, who) int mode; /* OUTPUT_EXEC or OUTPUT_IEXEC (interactive mode) */ char *cmd; /* changegroup, newgroup or rmgroup */ char *grp; /* name of group to change, add, remove */ char *type; /* type of group or NULL */ char *who; /* newgroup creator or NULL */ { FILE *ch_stream = NULL; /* stream from a child process */ char buf[BUFSIZ+1]; /* interactive buffer */ int pid; /* pid of child process */ int io[2]; /* pair of pipe descriptors */ #if defined(DONT_USE_UNION_WAIT) int status; /* wait status */ #else union wait status; /* wait status */ #endif int exitval; /* exit status of the child */ char *p; /* firewall */ if (cmd == NULL || grp == NULL) { fprintf(stderr, "%s: internal error #13, cmd or grp is NULL\n", program); exit(42); } /* if interactive, ask the question */ if (mode == OUTPUT_IEXEC) { /* ask the question */ fflush(stdin); fflush(stdout); fflush(stderr); if (type == NULL) { printf("%s %s [yn]? ", cmd, grp); } else if (who == NULL) { printf("%s %s %s [yn]? ", cmd, grp, type); } else { printf("%s %s %s %s [yn]? ", cmd, grp, type, who); } fflush(stdout); buf[0] = '\0'; buf[BUFSIZ] = '\0'; p = fgets(buf, BUFSIZ, stdin); if (p == NULL) { /* EOF/ERROR on interactive input, silently stop processing */ exit(43); } /* if non-empty line doesn't start with 'y' or 'Y', skip command */ if (buf[0] != 'y' && buf[0] != 'Y' && buf[0] != '\n') { /* indicate nothing was done */ return 0; } } /* build a pipe for output from child interactive mode */ if (mode == OUTPUT_IEXEC) { if (pipe(io) < 0) { perror(program); fprintf(stderr, "%s: pipe create failed\n", program); exit(44); } /* setup a fake pipe to /dev/null for non-interactive mode */ } else { io[READ_SIDE] = open(DEV_NULL, 0); if (io[READ_SIDE] < 0) { perror(program); fprintf(stderr, "%s: unable to open %s for reading\n", program, DEV_NULL); exit(45); } io[WRITE_SIDE] = open(DEV_NULL, 1); if (io[WRITE_SIDE] < 0) { perror(program); fprintf(stderr, "%s: unable to open %s for writing\n", program, DEV_NULL); exit(46); } } /* pause if in non-interactive mode so as to not busy-out the server */ if (mode == OUTPUT_EXEC && z_flag > 0) { if (D_BUG) { fprintf(stderr, "%s: sleeping %d seconds before fork/exec\n", program, z_flag); /* be sure they know what we are stalling */ fflush(stderr); } sleep(z_flag); } /* fork the child process */ fflush(stdout); fflush(stderr); pid = fork(); if (pid == -1) { perror(program); fprintf(stderr, "%s: fork failed\n", program); exit(47); } /* case: child process */ if (pid == 0) { /* * prep file descriptors */ fclose(stdin); close(io[READ_SIDE]); if (dup2(io[WRITE_SIDE], 1) < 0) { fprintf(stderr, "%s: child: dup of write I/O pipe to stdout failed\n", program); perror(program); exit(48); } if (dup2(io[WRITE_SIDE], 2) < 0) { fprintf(stderr, "%s: child: dup of write I/O pipe to stderr failed\n", program); perror(program); exit(49); } /* exec the ctlinnd command */ if (type == NULL) { execl(CTLINND_PATH, CTLINND_NAME, CTLINND_TIME_OUT, cmd, grp, NULL); } else if (who == NULL) { execl(CTLINND_PATH, CTLINND_NAME, CTLINND_TIME_OUT, cmd, grp, type, NULL); } else { execl(CTLINND_PATH, CTLINND_NAME, CTLINND_TIME_OUT, cmd, grp, type, who, NULL); } /* child exec failed */ perror("child process"); exit(50); /* case: parent process */ } else { /* prep file descriptors */ if (mode != OUTPUT_IEXEC) { close(io[READ_SIDE]); } close(io[WRITE_SIDE]); /* print a line from the child, if interactive */ if (mode == OUTPUT_IEXEC) { /* read what the child says */ buf[0] = '\0'; buf[BUFSIZ] = '\0'; ch_stream = fdopen(io[READ_SIDE], "r"); if (ch_stream == NULL) { fprintf(stderr, "%s: fdopen of pipe failed\n", program); exit(51); } p = fgets(buf, BUFSIZ, ch_stream); /* print what the child said, if anything */ if (p != NULL) { if (buf[strlen(buf)-1] == '\n') { fprintf(stderr, "\t%s", buf); } else { fprintf(stderr, "\t%s\n", buf); } } } /* look for abnormal child termination/status */ errno = 0; while (wait(&status) < 0) { if (errno == EINTR) { /* just an interrupt, try to wait again */ errno = 0; } else { perror(program); fprintf(stderr, "%s: wait returned -1\n", program); exit(52); } } if (mode == OUTPUT_IEXEC) { /* close the pipe now that we are done with reading it */ fclose(ch_stream); } if (WIFSTOPPED(status)) { fprintf(stderr, " %s %s %s%s%s%s%s stopped\n", CTLINND_NAME, cmd, grp, (type ? "" : " "), (type ? type : ""), (who ? "" : " "), (who ? who : "")); /* assume no work was done */ return 0; } if (WIFSIGNALED(status)) { fprintf(stderr, " %s %s %s%s%s%s%s killed by signal %d\n", CTLINND_NAME, cmd, grp, (type ? "" : " "), (type ? type : ""), (who ? "" : " "), (who ? who : ""), WTERMSIG(status)); /* assume no work was done */ return 0; } if (!WIFEXITED(status)) { fprintf(stderr, " %s %s %s%s%s%s%s returned unknown wait status: 0x%x\n", CTLINND_NAME, cmd, grp, (type ? "" : " "), (type ? type : ""), (who ? "" : " "), (who ? who : ""), status); /* assume no work was done */ return 0; } exitval = WEXITSTATUS(status); if (exitval != 0) { fprintf(stderr, " %s %s %s%s%s%s%s exited with status: %d\n", CTLINND_NAME, cmd, grp, (type ? "" : " "), (type ? type : ""), (who ? "" : " "), (who ? who : ""), exitval); /* assume no work was done */ return 0; } } /* all done */ return 1; } /* * scan_spool_dir - scan a spool directory for existing articles * * In order to avoid article number collisions, this function will * look under the spool directory for the related directory. If * this directory exists, then is it scanned for existing article * files. The hi and low water values will be set the the highest * and lowest all numeric filenames found directly under the * given directory. * * given: * grp pointer to a representation of an active line * * returns: * NEWGRP_EMPTY no dir under spool_dir was found, no change made * NEWGRP_NOCHG dir found, but no change to hi & low water was made * NEWGRP_CHG dir found, change to hi & low water was made * * NOTE: This function assumes that we are at the top of the news spool. */ static int scan_spool_dir(grp) struct grp *grp; { long oldhi; /* old (from merge) hi water mark */ long oldlow; /* old (from merge) low water mark */ long newhi; /* new hi water mark from merge AND spool */ long newlow; /* new low water mark from merge AND spool */ BOOL found; /* TRUE => the newsgroup dir already exists */ char *hi; /* changed hi water mark */ char *low; /* changed low water mark */ /* * firewall */ if (grp == NULL) { fprintf(stderr, "%s: internal error #14, grp is NULL\n", program); exit(53); } /* * convert hi and low fields into numeric values */ oldhi = atol(grp->outhi); oldlow = atol(grp->outlow); found = HiLowWater(grp->name, &newhi, &newlow, (long)-1, (long)-1); if (D_SUMMARY) { fprintf(stderr, "%s: new: %s, found %d, old hi/low: %ld %ld, new hi/low: %ld %ld\n", program, grp->name, found, oldhi, oldlow, newhi, newlow); } if (!found) { /* * we found no dir or it is empty so there is no reason * to change the hi & low water marks */ if (D_SUMMARY) { fprintf(stderr, "%s: new: %s dir not found or is empty\n", program, grp->name); } return NEWGRP_EMPTY; } /* * determine if there is no hi or low water mark changes */ if (newhi == oldhi && newlow == oldlow) { /* non-empty dir found, but no hi & low water change */ if (D_SUMMARY) { fprintf(stderr, "%s: new: %s, non-empty dir, no hi/low water change\n", program, grp->name); } return NEWGRP_NOCHG; } /* * form the new water marks */ if (newhi != oldhi) { hi = malloc(WATER_LEN+1); if (hi == NULL) { fprintf(stderr, "%s: unable to malloc %d octet hi water string\n", program, WATER_LEN+1); exit(54); } sprintf(hi, "%010ld", newhi); if (D_BUG) { fprintf(stderr, "%s: new: %s, dir found, oldhi:<%s> != newhi:<%s>\n", program, grp->name, grp->outhi, hi); } grp->outhi = hi; } if (newlow != oldlow) { low = malloc(WATER_LEN+1); if (low == NULL) { fprintf(stderr, "%s: unable to malloc %d octet low water string\n", program, WATER_LEN+1); exit(55); } sprintf(low, "%010ld", newlow); if (D_BUG) { fprintf(stderr, "%s: new: %s, dir found, oldlow:<%s> != newlow:<%s>\n", program, grp->name, grp->outlow, low); } grp->outlow = low; } /* * report the change */ return NEWGRP_CHG; } /* * new_top_hier - determine if the newsgroup represents a new hierarchy * * Determine of the newsgroup name is a new hierarchy. * * given: * name name of newsgroup to check * * returns: * FALSE hierarchy already exists * TRUE hierarchy does not exist, name represents a new hierarchy * * NOTE: This function assumes that we are at the top of the news spool. */ static int new_top_hier(name) char *name; { struct stat statbuf; /* stat of the hierarchy */ int result; /* return result */ char *dot; /* * temp change name to just the top level */ dot = strchr(name, '.'); if (dot != NULL) { *dot = '\0'; } /* * determine if we can find this top level hierarchy directory */ result = !(stat(name, &statbuf) >= 0 && S_ISDIR(statbuf.st_mode)); /* restore name */ if (dot != NULL) { *dot = '.'; } /* * return the result */ return result; } inn-1.7.2/backends/Makefile0100644000175100001440000002162206443103542014044 0ustar mdusers## $Revision: 1.28 $ SHELL = /bin/sh MAKE = make DESTDIR = D = $(DESTDIR) ## =()

@>()= P = ## =()@>()= CC = gcc ## =()@>()= DEFS = -I../include ## =()@>()= CFLAGS = $(DEFS) -g ## =()@>()= LDFLAGS = ## =()@>()= LINTFLAGS = -b -h -z $(DEFS) ## =()@>()= LINTFILTER = | sed -n -f ../sedf.sun ## =()@>()= CTAGS = ctags -t -w ## =()@>()= NEWSBIN = /usr/news/bin ## =()@ -G @@>()= OWNER = -O news -G news ## =()@>()= NNTPLIB = ## =()@>()= LIBS = -lutil LIBNEWS = ../libinn.a LINTLIB = ../llib-linn.ln SOURCES = archive.c batcher.c buffchan.c cvtbatch.c filechan.c \ innxmit.c innxbatch.c nntpget.c overchan.c shlock.c \ shrinkfile.c crosspost.c actsync.c ALL = archive batcher buffchan cvtbatch filechan \ innxmit innxbatch nntpget overchan shlock \ shrinkfile crosspost actsync actsyncd actmerge \ sendxbatches all: $(ALL) install: $D$(NEWSBIN)/archive $D$(NEWSBIN)/batcher \ $D$(NEWSBIN)/buffchan $D$(NEWSBIN)/cvtbatch \ $D$(NEWSBIN)/filechan $D$(NEWSBIN)/nntpget \ $D$(NEWSBIN)/innxmit $D$(NEWSBIN)/innxbatch \ $D$(NEWSBIN)/overchan \ $D$(NEWSBIN)/shlock $D$(NEWSBIN)/shrinkfile \ $D$(NEWSBIN)/crosspost \ $D$(NEWSBIN)/sendxbatches \ $D$(NEWSBIN)/actsync $D$(NEWSBIN)/actsyncd \ $D$(NEWSBIN)/actmerge clobber clean: rm -f *.o $(ALL) rm -f all install lint profiled tags ctags: $(SOURCES) $(CTAGS) $(SOURCES) ../lib/*.c ../include/*.h profiled: cp /dev/null profiled archive: $(P) archive.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ archive.o $(LIBNEWS) $(LIBS) batcher: $(P) batcher.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ batcher.o $(LIBNEWS) $(LIBS) buffchan: $(P) buffchan.o map.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ buffchan.o map.o $(LIBNEWS) $(LIBS) cvtbatch: $(P) cvtbatch.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ cvtbatch.o $(LIBNEWS) $(LIBS) filechan: $(P) filechan.o map.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ filechan.o map.o $(LIBNEWS) $(LIBS) nntpget: $(P) nntpget.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ nntpget.o $(LIBNEWS) $(LIBS) innxmit: $(P) innxmit.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ innxmit.o $(LIBNEWS) $(LIBS) innxbatch: $(P) innxbatch.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ innxbatch.o $(LIBNEWS) $(LIBS) sendxbatches: $(P) sendxbatches.sh rm -f $@ cp $? $@ chmod +x $@ overchan: $(P) overchan.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ overchan.o $(LIBNEWS) $(LIBS) crosspost: $(P) crosspost.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ crosspost.o $(LIBNEWS) $(LIBS) actsync: $(P) actsync.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ actsync.o $(LIBNEWS) $(LIBS) actsyncd: $(P) actsyncd.sh rm -f $@ cp $? $@ chmod +x $@ actmerge: $(P) actmerge.sh rm -f $@ cp $? $@ chmod +x $@ shlock: $(P) shlock.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ shlock.o $(LIBNEWS) $(LIBS) shrinkfile: $(P) shrinkfile.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ shrinkfile.o $(LIBNEWS) $(LIBS) lint: $(ALL) @rm -f lint -lint $(LINTFLAGS) actsync.c $(LINTLIB) $(LINTFILTER) >lint -lint $(LINTFLAGS) archive.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) batcher.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) buffchan.c map.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) cvtbatch.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) filechan.c map.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) nntpget.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) innxmit.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) innxbatch.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) overchan.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) crosspost.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) shlock.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) shrinkfile.c $(LINTLIB) $(LINTFILTER) >>lint $(LIBNEWS) $(LINTLIB): (cd ../lib ; $(MAKE) install) ## Low-level install actions. $D$(NEWSBIN)/archive: archive $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/batcher: batcher $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/buffchan: buffchan $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/cvtbatch: cvtbatch $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/filechan: filechan $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/nntpget: nntpget $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/innxmit: innxmit $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/innxbatch: innxbatch $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/sendxbatches: sendxbatches $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/crosspost: crosspost $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/overchan: overchan $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/shlock: shlock $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/shrinkfile: shrinkfile $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/actsync: actsync $(SHELL) ../installit.sh $(OWNER) -m 0550 -b .OLD $? $@ $D$(NEWSBIN)/actsyncd: actsyncd $(SHELL) ../installit.sh $(OWNER) -m 0550 -b .OLD $? $@ $D$(NEWSBIN)/actmerge: actmerge $(SHELL) ../installit.sh $(OWNER) -m 0550 -b .OLD $? $@ ## Dependencies. Default list, below, is probably good enough. depend: Makefile $(SOURCES) makedepend $(DEFS) $(SOURCES) # DO NOT DELETE THIS LINE -- make depend depends on it. actsync.o: ../include/clibrary.h actsync.o: ../include/configdata.h actsync.o: ../include/configdata.h actsync.o: ../include/libinn.h actsync.o: ../include/libinn.h actsync.o: ../include/macros.h actsync.o: ../include/macros.h actsync.o: ../include/mydir.h actsync.o: ../include/paths.h actsync.o: ../include/qio.h archive.o: ../include/clibrary.h archive.o: ../include/configdata.h archive.o: ../include/configdata.h archive.o: ../include/libinn.h archive.o: ../include/libinn.h archive.o: ../include/macros.h archive.o: ../include/paths.h archive.o: ../include/qio.h batcher.o: ../include/clibrary.h batcher.o: ../include/configdata.h batcher.o: ../include/configdata.h batcher.o: ../include/libinn.h batcher.o: ../include/libinn.h batcher.o: ../include/logging.h batcher.o: ../include/macros.h batcher.o: ../include/paths.h buffchan.o: ../include/clibrary.h buffchan.o: ../include/configdata.h buffchan.o: ../include/configdata.h buffchan.o: ../include/libinn.h buffchan.o: ../include/libinn.h buffchan.o: ../include/macros.h buffchan.o: ../include/paths.h buffchan.o: ../include/qio.h crosspost.o: ../include/clibrary.h crosspost.o: ../include/configdata.h crosspost.o: ../include/configdata.h crosspost.o: ../include/libinn.h crosspost.o: ../include/libinn.h crosspost.o: ../include/macros.h crosspost.o: ../include/paths.h crosspost.o: ../include/qio.h crosspost.o: ../include/qio.h cvtbatch.o: ../include/clibrary.h cvtbatch.o: ../include/configdata.h cvtbatch.o: ../include/configdata.h cvtbatch.o: ../include/libinn.h cvtbatch.o: ../include/macros.h cvtbatch.o: ../include/paths.h cvtbatch.o: ../include/qio.h cvtbatch.o: ../include/qio.h filechan.o: ../include/clibrary.h filechan.o: ../include/configdata.h filechan.o: ../include/configdata.h filechan.o: ../include/libinn.h filechan.o: ../include/libinn.h filechan.o: ../include/macros.h filechan.o: ../include/paths.h innxbatch.o: ../include/clibrary.h innxbatch.o: ../include/configdata.h innxbatch.o: ../include/configdata.h innxbatch.o: ../include/libinn.h innxbatch.o: ../include/logging.h innxbatch.o: ../include/logging.h innxbatch.o: ../include/macros.h innxbatch.o: ../include/nntp.h innxmit.o: ../include/clibrary.h innxmit.o: ../include/configdata.h innxmit.o: ../include/configdata.h innxmit.o: ../include/dbz.h innxmit.o: ../include/libinn.h innxmit.o: ../include/logging.h innxmit.o: ../include/macros.h innxmit.o: ../include/nntp.h innxmit.o: ../include/paths.h innxmit.o: ../include/paths.h innxmit.o: ../include/qio.h innxmit.o: ../include/qio.h nntpget.o: ../include/clibrary.h nntpget.o: ../include/configdata.h nntpget.o: ../include/configdata.h nntpget.o: ../include/dbz.h nntpget.o: ../include/libinn.h nntpget.o: ../include/libinn.h nntpget.o: ../include/macros.h nntpget.o: ../include/macros.h nntpget.o: ../include/nntp.h nntpget.o: ../include/paths.h overchan.o: ../include/clibrary.h overchan.o: ../include/configdata.h overchan.o: ../include/configdata.h overchan.o: ../include/libinn.h overchan.o: ../include/macros.h overchan.o: ../include/macros.h overchan.o: ../include/paths.h overchan.o: ../include/qio.h shlock.o: ../include/clibrary.h shlock.o: ../include/configdata.h shlock.o: ../include/configdata.h shrinkfile.o: ../include/clibrary.h shrinkfile.o: ../include/configdata.h shrinkfile.o: ../include/configdata.h shrinkfile.o: ../include/libinn.h shrinkfile.o: ../include/libinn.h shrinkfile.o: ../include/macros.h inn-1.7.2/backends/rcompress.c0100644000175100001440000001124306443103542014563 0ustar mdusers/* $Revision: 1.9 $ ** ** TCP forwarder. Connect to a server on a host. Send our stdin to the ** server, and send server's output down our stdout. Low-cost version ** of rsh. Can also be spawned out of inetd, e.g., to do forwarding. ** Descended from code written by Jim Thompson . ** For example, when doing an "rcompress", add this to /etc/services: ** compress 2001/tcp ** and add this to /etc/inetd.conf on the server: ** compress stream tcp nowait root /usr/ucb/compress in.compressd -c */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #include #define BUFFER_SIZE 8192 /* #define DEFAULT_HOST "news.foo.com" #define DEFAULT_SERVICE "nntp" #define DEFAULT_INETLOSS 1 */ #define DEFAULT_HOST "geraldo" #define DEFAULT_SERVICE "compress" #define DEFAULT_INETLOSS 0 extern int optind; extern char *optarg; extern char *malloc(); extern char *memcpy(); extern char *memset(); extern unsigned long inet_addr(); extern struct servent *getservbyname(); extern struct hostent *gethostbyname(); extern void exit(); extern void perror(); /* ** Open a socket to the specified service. */ int OpenConnection(host, service) char *host; char *service; { char **ap; char *fakelist[2]; register int i; struct servent *sp; struct hostent *hp; struct hostent fakehp; struct in_addr quadaddr; struct sockaddr_in server; if ((sp = getservbyname(service, "tcp")) == NULL) { perror("Unknown service"); return -1; } /* Get the host's address. */ quadaddr.s_addr = inet_addr(host); if (quadaddr.s_addr != (unsigned int) -1) { /* Host was specified as a dotted-quad internet address. Fill in * the parts of the hostent struct that we need. */ fakehp.h_length = sizeof quadaddr; fakehp.h_addrtype = AF_INET; hp = &fakehp; fakelist[0] = (char *)&quadaddr; fakelist[1] = NULL; ap = fakelist; } else if ((hp = gethostbyname(host)) != NULL) { /* Symbolic host name. */ #if defined(h_addr) ap = hp->h_addr_list; #else /* Fake up an address list for old systems. */ fakelist[0] = (char *)hp->h_addr; fakelist[1] = NULL; ap = fakelist; #endif /* defined(h_addr) */ } else { perror("Unknown host"); return -1; } /* Set up the socket address. */ (void)memset((char *)&server, 0, sizeof server); server.sin_family = hp->h_addrtype; server.sin_port = sp->s_port; /* Loop through the address list, trying to connect. */ for (; ap && *ap; ap++) { /* Make a socket and try to connect. */ if ((i = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) break; (void)memcpy((char *)&server.sin_addr, (char *)*ap, (int)hp->h_length); if (connect(i, (struct sockaddr *)&server, sizeof server) == 0) return i; (void)close(i); } perror("Can't connect"); return -1; } /* ** Loop until the entire buffer is written. */ int xwrite(fd, p, i) register int fd; register char *p; register int i; { register int count; for ( ; i > 0; p += count, i -= count) if ((count = write(fd, p, i)) < 0) return -1; return 0; } int main(ac, av) int ac; char *av[]; { static char USAGE[] = "Usage error\n"; int s; int inetdloss; register int i; char *host; char *service; char *p; /* Set defaults. */ host = DEFAULT_HOST; service = DEFAULT_SERVICE; inetdloss = DEFAULT_INETLOSS; /* Parse JCL. */ while ((i = getopt(ac, av, "h:is:")) != EOF) switch (i) { default: (void)write(1, USAGE, sizeof USAGE - 1); exit(1); case 'h': host = optarg; break; case 'i': inetdloss = 1; break; case 's': service = optarg; break; } ac -= optind; if (ac) { (void)write(1, USAGE, sizeof USAGE - 1); exit(1); } if (inetdloss) { /* Work around broken inetd's. */ (void)close(1); (void)dup(0); } /* Get a connection. */ if ((s = OpenConnection(host, service)) < 0) exit(1); /* Get a buffer. */ if ((p = malloc(BUFFER_SIZE)) == NULL) { perror("can't allocate buffer"); exit(1); } switch (fork()) { case -1: perror("Can't fork"); exit(1); case 0: /* Child -- send server output to our stdout. */ while ((i = read(s, p, BUFFER_SIZE)) > 0) if (xwrite(1, p, i) < 0) { perror("Can't write to client"); break; } break; default: /* Parent -- send our stdin to server. */ while ((i = read(0, p, BUFFER_SIZE)) > 0) if (xwrite(s, p, i) < 0) { perror("Can't write to server"); break; } (void)shutdown(s, 1); break; } exit(0); /* NOTREACHED */ } inn-1.7.2/backends/innxmit.c0100644000175100001440000012250706443103542014242 0ustar mdusers/* $Revision: 1.23 $ ** ** Transmit articles to remote site. ** Modified for NNTP streaming: 3Jan96 Jerry Aguirre */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #include #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include #include "nntp.h" #include "paths.h" #include "logging.h" #include "libinn.h" #include "qio.h" #include "dbz.h" #include "macros.h" /* ** Supported encoding schemes. */ typedef enum _MIMEXFERTYPE { MTnotmime, MTquotedprintable, MTbase64 } MIMEXFERTYPE; #define OUTPUT_BUFFER_SIZE (16 * 1024) /* Streaming extensions to NNTP. This extension removes the lock-step ** limitation of conventional NNTP. Article transfer is several times ** faster. Negotiated and falls back to old mode if receiver refuses. */ /* max number of articles that can be streamed ahead */ #define STNBUF 32 /* Send "takethis" without "check" if this many articles were ** accepted in a row. */ #define STNC 16 /* typical number of articles to stream */ /* must be able to fopen this many articles */ #define STNBUFL (STNBUF/2) /* number of retries before requeueing to disk */ #define STNRETRY 5 struct stbufs { /* for each article we are procesing */ char *st_fname; /* file name */ char *st_id; /* message ID */ int st_retry; /* retry count */ int st_age; /* age count */ QIOSTATE *st_qp; /* IO to read article contents */ int st_hash; /* hash value to speed searches */ }; static struct stbufs stbuf[STNBUF]; /* we keep track of this many articles */ static int stnq; /* current number of active entries in stbuf */ static long stnofail; /* Count of consecutive successful sends */ static int TryStream = TRUE; /* Should attempt stream negotation? */ static int CanStream = FALSE; /* Result of stream negotation */ static int DoCheck = TRUE; /* Should check before takethis? */ static char modestream[] = "mode stream"; static long retries = 0; static int logRejects = TRUE ; /* syslog the 437 responses. */ /* ** Syslog formats - collected together so they remain consistent */ STATIC char STAT1[] = "%s stats offered %lu accepted %lu refused %lu rejected %lu"; STATIC char STAT2[] = "%s times user %.3f system %.3f elapsed %.3f"; STATIC char GOT_RESENDIT[] = "%s requeued %s %s"; STATIC char GOT_BADCOMMAND[] = "%s rejected %s %s"; STATIC char REJECTED[] = "%s rejected %s (%s) %s"; STATIC char CANT_CONNECT[] = "%s connect failed %s"; STATIC char CANT_AUTHENTICATE[] = "%s authenticate failed %s"; STATIC char IHAVE_FAIL[] = "%s ihave failed %s"; STATIC char CANT_FINDIT[] = "%s can't find %s"; STATIC char CANT_PARSEIT[] = "%s can't parse ID %s"; STATIC char UNEXPECTED[] = "%s unexpected response code %s"; /* ** Global variables. */ STATIC BOOL AlwaysRewrite; STATIC BOOL Debug; STATIC BOOL DoRequeue = TRUE; STATIC BOOL Purging; STATIC BOOL Slavish; STATIC BOOL STATprint; STATIC BOOL Mime; STATIC MIMEXFERTYPE MimeArticle = MTnotmime; STATIC char *BATCHname; STATIC char *BATCHtemp; STATIC char *REMhost; STATIC double STATbegin; STATIC double STATend; STATIC FILE *BATCHfp; STATIC int FromServer; STATIC int ToServer; STATIC QIOSTATE *BATCHqp; STATIC SIGVAR GotAlarm; STATIC SIGVAR GotInterrupt; STATIC SIGVAR JMPyes; STATIC jmp_buf JMPwhere; STATIC char *REMbuffer; STATIC char *REMbuffptr; STATIC char *REMbuffend; STATIC unsigned long STATaccepted; STATIC unsigned long STAToffered; STATIC unsigned long STATrefused; STATIC unsigned long STATrejected; STATIC char *AltSpool; STATIC char *AltPath; /* ** Find the history file entry for the Message-ID and return a file ** positioned at the third field. */ STATIC FILE * HistorySeek(MessageID) char *MessageID; { static char History[] = _PATH_HISTORY; static FILE *F; register char *p; register char *q; register int i; datum key; datum val; OFFSET_T offset; /* Open the history file. */ if (F == NULL) { if (dbminit(History) < 0) { (void)fprintf(stderr, "Can't set up \"%s\" database, %s\n", History, strerror(errno)); exit(1); } if ((F = fopen(History, "r")) == NULL) { (void)fprintf(stderr, "Can't open \"%s\" for reading, %s\n", History, strerror(errno)); exit(1); } } /* Do the lookup. */ key.dsize = strlen(MessageID) + 1; key.dptr = MessageID; val = dbzfetch(key); if (val.dptr == NULL || val.dsize != sizeof offset) return NULL; /* Get the seek offset, and seek. */ for (p = val.dptr, q = (char *)&offset, i = sizeof offset; --i >= 0; ) *q++ = *p++; if (fseek(F, offset, SEEK_SET) == -1) return NULL; return F; } /* ** Return TRUE if the history file has the article expired. */ STATIC BOOL Expired(MessageID) char *MessageID; { register int c; register int i; register FILE *F; if ((F = HistorySeek(MessageID)) == NULL) /* Assume the worst. */ return TRUE; /* Move to the filename fields. */ for (i = 2; (c = getc(F)) != EOF && c != '\n'; ) if (c == HIS_FIELDSEP && --i == 0) break; if (c != HIS_FIELDSEP) return TRUE; /* See if we get any filename before the end of the line. */ while ((c = getc(F)) != EOF && c != '\n') if (!ISWHITE(c)) /* Found non-whitespace; assume it's a filename. */ return FALSE; return TRUE; } /* ** Flush and reset the site's output buffer. Return FALSE on error. */ STATIC BOOL REMflush() { int i; if (REMbuffptr == REMbuffer) return TRUE; /* nothing buffered */ i = xwrite(ToServer, REMbuffer, (int)(REMbuffptr - REMbuffer)); REMbuffptr = REMbuffer; return i < 0 ? FALSE : TRUE; } /* ** Return index to entry matching this message ID. Else return -1. ** The hash is to speed up the search. ** the protocol. */ STATIC int stindex(MessageID, hash) char *MessageID; int hash; { register int i; for (i = 0; i < STNBUF; i++) { /* linear search for ID */ if ((stbuf[i].st_id) && (stbuf[i].st_id[0]) && (stbuf[i].st_hash == hash)) { register int n; if (strcasecmp(MessageID, stbuf[i].st_id)) continue; /* left of '@' is case sensitive */ for (n = 0; (MessageID[n] != '@') && (MessageID[n] != '\0'); n++) ; if (strncmp(MessageID, stbuf[i].st_id, n)) continue; else break; /* found a match */ } } if (i >= STNBUF) i = -1; /* no match found ? */ return (i); } /* stidhash(): calculate a hash value for message IDs to speed comparisons */ STATIC int stidhash(MessageID) char *MessageID; { register char *p; register int hash; hash = 0; for (p = MessageID + 1; *p && (*p != '>'); p++) { hash <<= 1; if (isascii(*p) && isupper(*p)) { hash += tolower(*p); } else { hash += *p; } } return hash; } /* stalloc(): save path, ID, and qp into one of the streaming mode entries */ STATIC int stalloc(Article, MessageID, qp, hash) char *Article; char *MessageID; QIOSTATE *qp; int hash; { register int i; for (i = 0; i < STNBUF; i++) { if ((!stbuf[i].st_fname) || (stbuf[i].st_fname[0] == '\0')) break; } if (i >= STNBUF) { /* stnq says not full but can not find unused */ syslog(L_ERROR, "stalloc: Internal error"); return (-1); } if ((int)strlen(Article) >= SPOOLNAMEBUFF) { syslog(L_ERROR, "stalloc: filename longer than %d", SPOOLNAMEBUFF); return (-1); } /* allocate buffers on first use. ** If filename ever is longer than SPOOLNAMEBUFF then code will abort. ** If ID is ever longer than NNTP_STRLEN then other code would break. */ if (!stbuf[i].st_fname) stbuf[i].st_fname = NEW(char, SPOOLNAMEBUFF); if (!stbuf[i].st_id) stbuf[i].st_id = NEW(char, NNTP_STRLEN); (void)strcpy(stbuf[i].st_fname, Article); (void)strcpy(stbuf[i].st_id, MessageID); stbuf[i].st_qp = qp; stbuf[i].st_hash = hash; stbuf[i].st_retry = 0; stbuf[i].st_age = 0; stnq++; return i; } /* strel(): release for reuse one of the streaming mode entries */ STATIC void strel(i) int i; { if (stbuf[i].st_qp) { QIOclose(stbuf[i].st_qp); stbuf[i].st_qp = 0; } if (stbuf[i].st_id) stbuf[i].st_id[0] = '\0'; if (stbuf[i].st_fname) stbuf[i].st_fname[0] = '\0'; stnq--; } /* ** Send a line to the server, adding the dot escape and \r\n. */ STATIC BOOL REMwrite(p, i, escdot) register char *p; register int i; register BOOL escdot; { static char HDR[] = "Content-Transfer-Encoding:"; static char COD[] = "Content-Transfer-Encoding: quoted-printable\r\n"; register char *dest; int size; /* Buffer too full? */ if (REMbuffend - REMbuffptr < i + 3) { if (!REMflush()) return FALSE; if (REMbuffend - REMbuffer < i + 3) { /* Line too long -- grow buffer. */ size = i * 2; RENEW(REMbuffer, char, size); REMbuffend = &REMbuffer[size]; } } if (MimeArticle != MTnotmime) if ((*p == 'C' && EQn(p, HDR, STRLEN(HDR))) || ((*p == 'C' || *p == 'c') && caseEQn(p, HDR, STRLEN(HDR)))) { (void)memcpy((POINTER)REMbuffptr, (POINTER)COD, STRLEN(COD)); REMbuffptr += STRLEN(COD); return TRUE; } /* Dot escape, text of the line, line terminator. */ if (escdot && (*p == '.')) *REMbuffptr++ = '.'; if (i > MEMCPY_THRESHOLD) { (void)memcpy((POINTER)REMbuffptr, (POINTER)p, (SIZE_T)i); REMbuffptr += i; } else { for (dest = REMbuffptr, i++; --i > 0; ) *dest++ = *p++; REMbuffptr = dest; } *REMbuffptr++ = '\r'; *REMbuffptr++ = '\n'; return TRUE; } /* ** Send a line to the server, adding the dot escape and \r\n. */ STATIC BOOL REMwriteQuoted(p, i) register char *p; register int i; { static char HEXDIGITS[] = "0123456789ABCDEF"; register char *dest; register int size; register int count; register int prev; /* Buffer too full? */ if (REMbuffend - REMbuffptr < i + 3) { if (!REMflush()) return FALSE; if (REMbuffend - REMbuffer < i + 3) { /* Line too long -- grow buffer. */ size = i * 2; RENEW(REMbuffer, char, size); REMbuffend = &REMbuffer[size]; } } for (count = 0, prev = 255, dest = REMbuffptr, i++; --i > 0; ) { if ((*p < 32 && *p != '\t') || *p == '=' || *p >= 127 || (count == 0 && *p =='.')) { *dest++ = '='; *dest++ = HEXDIGITS[*p >> 4]; *dest++ = HEXDIGITS[*p & 0x0F]; p++; count += 3; prev = 'A'; } else { prev = *dest++ = *p++; count++; } if (count > 72) { *dest++ = '='; *dest++ = '\r'; *dest++ = '\n'; count = 0; prev = '\n'; } } if (prev == ' ' || prev == '\t') *dest++ = '='; REMbuffptr = dest; *REMbuffptr++ = '\r'; *REMbuffptr++ = '\n'; return TRUE; } /* ** Print transfer statistics, clean up, and exit. */ STATIC NORETURN ExitWithStats(x) int x; { static char QUIT[] = "quit"; TIMEINFO Now; double usertime; double systime; if (!Purging) { (void)REMwrite(QUIT, STRLEN(QUIT), FALSE); (void)REMflush(); } (void)GetTimeInfo(&Now); STATend = TIMEINFOasDOUBLE(Now); if (GetResourceUsage(&usertime, &systime) < 0) { usertime = 0; systime = 0; } if (STATprint) { (void)printf(STAT1, REMhost, STAToffered, STATaccepted, STATrefused, STATrejected); (void)printf("\n"); (void)printf(STAT2, REMhost, usertime, systime, STATend - STATbegin); (void)printf("\n"); } syslog(L_NOTICE, STAT1, REMhost, STAToffered, STATaccepted, STATrefused, STATrejected); syslog(L_NOTICE, STAT2, REMhost, usertime, systime, STATend - STATbegin); if (retries) syslog(L_NOTICE, "%s %lu Streaming retries", REMhost, retries); if (BATCHfp != NULL && unlink(BATCHtemp) < 0 && errno != ENOENT) (void)fprintf(stderr, "Can't remove \"%s\", %s\n", BATCHtemp, strerror(errno)); (void)sleep(1); exit(x); /* NOTREACHED */ } /* ** Close the batchfile and the temporary file, and rename the temporary ** to be the batchfile. */ STATIC void CloseAndRename() { /* Close the files, rename the temporary. */ if (BATCHqp) { QIOclose(BATCHqp); BATCHqp = NULL; } if (ferror(BATCHfp) || fflush(BATCHfp) == EOF || fclose(BATCHfp) == EOF) { (void)unlink(BATCHtemp); (void)fprintf(stderr, "Can't close \"%s\", %s\n", BATCHtemp, strerror(errno)); ExitWithStats(1); } if (rename(BATCHtemp, BATCHname) < 0) { (void)fprintf(stderr, "Can't rename \"%s\", %s\n", BATCHtemp, strerror(errno)); ExitWithStats(1); } } /* ** Requeue an article, opening the temp file if we have to. If we get ** a file write error, exit so that the original input is left alone. */ STATIC void Requeue(Article, MessageID) char *Article; char *MessageID; { /* Temp file already open? */ if (BATCHfp == NULL) { (void)mktemp(BATCHtemp); if ((BATCHfp = fopen(BATCHtemp, "w")) == NULL) { (void)fprintf(stderr, "Can't open \"%s\", %s\n", BATCHtemp, strerror(errno)); ExitWithStats(1); } } /* Called only to get the file open? */ if (Article == NULL) return; if (MessageID != NULL) (void)fprintf(BATCHfp, "%s %s\n", Article, MessageID); else (void)fprintf(BATCHfp, "%s\n", Article); if (fflush(BATCHfp) == EOF || ferror(BATCHfp)) { (void)fprintf(stderr, "Can't requeue \"%s\", %s\n", Article, strerror(errno)); ExitWithStats(1); } } /* ** Requeue an article then copy the rest of the batch file out. */ STATIC void RequeueRestAndExit(Article, MessageID) char *Article; char *MessageID; { register char *p; if (!AlwaysRewrite && STATaccepted == 0 && STATrejected == 0 && STATrefused == 0) { (void)fprintf(stderr, "Nothing sent -- leaving batchfile alone.\n"); ExitWithStats(1); } (void)fprintf(stderr, "Rewriting batch file and exiting.\n"); if (CanStream) { /* streaming mode has a buffer of articles */ register int i; for (i = 0; i < STNBUF; i++) { /* requeue unacknowledged articles */ if ((stbuf[i].st_fname) && (stbuf[i].st_fname[0] != '\0')) { if (Debug) (void)fprintf(stderr, "stbuf[%d]= %s, %s\n", i, stbuf[i].st_fname, stbuf[i].st_id); Requeue(stbuf[i].st_fname, stbuf[i].st_id); if (Article == stbuf[i].st_fname) Article = NULL; strel(i); /* release entry */ } } } Requeue(Article, MessageID); for ( ; BATCHqp; ) { if ((p = QIOread(BATCHqp)) == NULL) { if (QIOtoolong(BATCHqp)) { (void)fprintf(stderr, "Skipping long line in \"%s\".\n", BATCHname); (void)QIOread(BATCHqp); continue; } if (QIOerror(BATCHqp)) { (void)fprintf(stderr, "Can't read \"%s\", %s\n", BATCHname, strerror(errno)); ExitWithStats(1); } /* Normal EOF. */ break; } if (fprintf(BATCHfp, "%s\n", p) == EOF || ferror(BATCHfp)) { (void)fprintf(stderr, "Can't requeue \"%s\", %s\n", p, strerror(errno)); ExitWithStats(1); } } CloseAndRename(); ExitWithStats(1); } /* ** Clean up the NNTP escapes from a line. */ STATIC char * REMclean(buff) char *buff; { char *p; if ((p = strchr(buff, '\r')) != NULL) *p = '\0'; if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; /* The dot-escape is only in text, not command responses. */ return buff; } /* ** Read a line of input, with timeout. Also handle \r\n-->\n mapping ** and the dot escape. Return TRUE if okay, *or we got interrupted.* */ STATIC BOOL REMread(start, size) char *start; int size; { static int count; static char buffer[BUFSIZ]; static char *bp; register char *p; register char *q; register char *end; struct timeval t; FDSET rmask; int i; char c; if (!REMflush()) return FALSE; for (p = start, end = &start[size - 1]; ; ) { if (count == 0) { /* Fill the buffer. */ Again: FD_ZERO(&rmask); FD_SET(FromServer, &rmask); t.tv_sec = 10 * 60; t.tv_usec = 0; i = select(FromServer + 1, &rmask, (FDSET *)NULL, (FDSET *)NULL, &t); if (GotInterrupt) return TRUE; if (i < 0) { if (errno == EINTR) goto Again; return FALSE; } if (i == 0 || !FD_ISSET(FromServer, &rmask)) return FALSE; count = read(FromServer, buffer, sizeof buffer); if (GotInterrupt) return TRUE; if (count <= 0) return FALSE; bp = buffer; } /* Process next character. */ count--; c = *bp++; if (c == '\n') break; if (p < end) *p++ = c; } /* We know we got \n; if previous char was \r, turn it into \n. */ if (p > start && p < end && p[-1] == '\r') p[-1] = '\n'; *p = '\0'; /* Handle the dot escape. */ if (*p == '.') { if (p[1] == '\n' && p[2] == '\0') /* EOF. */ return FALSE; for (q = &start[1]; (*p++ = *q++) != '\0'; ) continue; } return TRUE; } /* ** Handle the interrupt. */ static void Interrupted(Article, MessageID) char *Article; char *MessageID; { (void)fprintf(stderr, "Interrupted\n"); RequeueRestAndExit(Article, MessageID); } /* ** Send a whole article to the server. */ STATIC BOOL REMsendarticle(Article, MessageID, qp) char *Article; char *MessageID; register QIOSTATE *qp; { register char *p; register BOOL ok; register BOOL InHeaders; long length; char buff[NNTP_STRLEN]; length = 0; for (InHeaders = TRUE; ; ) { if ((p = QIOread(qp)) == NULL) { if (QIOtoolong(qp)) { (void)fprintf(stderr, "Line too long in \"%s\"\n", Article); (void)QIOread(qp); continue; } if (QIOerror(qp)) { (void)fprintf(stderr, "Can't read \"%s\", %s\n", Article, strerror(errno)); return FALSE; } /* Normal EOF. */ break; } if (*p == '\0') InHeaders = FALSE; if (InHeaders || MimeArticle == MTnotmime) { if (!REMwrite(p, QIOlength(qp), TRUE)) { (void)fprintf(stderr, "Can't send \"%s\", %s\n", Article, strerror(errno)); return FALSE; } length += QIOlength(qp); } else { switch (MimeArticle) { default: case MTbase64: ok = FALSE; break; case MTquotedprintable: ok = REMwriteQuoted(p, QIOlength(qp)); length += QIOlength(qp); break; } if (!ok) { (void)fprintf(stderr, "Can't send \"%s\", %s\n", Article, strerror(errno)); return FALSE; } } if (GotInterrupt) Interrupted(Article, MessageID); } /* Write the terminator. */ if (!REMwrite(".", 1, FALSE)) { (void)fprintf(stderr, "Can't send \"%s\", %s\n", Article, strerror(errno)); return FALSE; } if (Debug) (void)fprintf(stderr, "> [ article %ld ]%s\n", length, MimeArticle == MTnotmime ? "" : " (Mime: quoted-printable)"); if (GotInterrupt) Interrupted(Article, MessageID); if (Debug) (void)fprintf(stderr, "> .\n"); if (CanStream) return TRUE; /* streaming mode does not wait for ACK */ /* What did the remote site say? */ if (!REMread(buff, (int)sizeof buff)) { (void)fprintf(stderr, "No reply after sending \"%s\", %s\n", Article, strerror(errno)); return FALSE; } if (GotInterrupt) Interrupted(Article, MessageID); if (Debug) (void)fprintf(stderr, "< %s", buff); /* Parse the reply. */ switch (atoi(buff)) { default: (void)fprintf(stderr, "Unknown reply after \"%s\" -- %s", Article, buff); if (DoRequeue) Requeue(Article, MessageID); break; case NNTP_BAD_COMMAND_VAL: case NNTP_SYNTAX_VAL: case NNTP_ACCESS_VAL: /* The receiving server is likely confused...no point in continuing */ syslog(L_FATAL, GOT_BADCOMMAND, REMhost, MessageID, REMclean(buff)); RequeueRestAndExit(Article, MessageID); /* NOTREACHED */ case NNTP_RESENDIT_VAL: case NNTP_GOODBYE_VAL: #if 0 syslog(L_NOTICE, GOT_RESENDIT, REMhost, MessageID, REMclean(buff)); #endif Requeue(Article, MessageID); break; case NNTP_TOOKIT_VAL: STATaccepted++; break; case NNTP_REJECTIT_VAL: if (logRejects) syslog(L_NOTICE, REJECTED, REMhost, MessageID, Article, REMclean(buff)); STATrejected++; break; } /* Article sent, or we requeued it. */ return TRUE; } /* ** Get the Message-ID header from an open article. */ STATIC char * GetMessageID(qp) register QIOSTATE *qp; { static char HDR[] = "Message-ID:"; static char buff[DBZMAXKEY + 1]; register char *p; while ((p = QIOread(qp)) != NULL) if ((*p == 'M' && EQn(p, HDR, STRLEN(HDR))) || ((*p == 'M' || *p == 'm') && caseEQn(p, HDR, STRLEN(HDR)))) { /* Found the header -- skip whitespace. */ for (p += STRLEN(HDR); ISWHITE(*p); p++) continue; if (*p == '\0' || (int)strlen(p) > DBZMAXKEY) /* Header is empty or too long. */ break; (void)strcpy(buff, p); return buff; } return NULL; } /* ** Get the MIME Content headers from an open article. */ STATIC void GetMimeHeaders(qp, Encodingp, Typep) register QIOSTATE *qp; register char **Encodingp; register char **Typep; { static char ENC_HDR[] = "Content-Transfer-Encoding:"; static char TYPE_HDR[] = "Content-Type:"; static char Encoding[SMBUF + 1]; static char ContentType[SMBUF + 1]; register char *p; for (*Encodingp = *Typep = NULL; (p = QIOread(qp)) != NULL && *p; ) { if (*p != 'C' && *p != 'c') continue; if (caseEQn(p, ENC_HDR, STRLEN(ENC_HDR))) { for (p += STRLEN(ENC_HDR); ISWHITE(*p); p++) continue; if (*p == '\0' || (int)strlen(p) > sizeof Encoding) /* Header is empty or too long. */ continue; (void)strcpy(Encoding, p); *Encodingp = Encoding; if (*Typep) break; } else if (caseEQn(p, TYPE_HDR, STRLEN(TYPE_HDR))) { for (p += STRLEN(TYPE_HDR); ISWHITE(*p); p++) continue; if (*p == '\0' || (int)strlen(p) > sizeof ContentType) /* Header is empty or too long. */ break; (void)strcpy(ContentType, p); /* Strip off any subtype part. */ for (p = ContentType; *p; p++) if (*p == '/' || *p == ';') { *p = '\0'; break; } *Typep = ContentType; if (*Encodingp) break; } } } /* ** Mark that we got interrupted. */ STATIC SIGHANDLER CATCHinterrupt(s) int s; { GotInterrupt = TRUE; /* Let two interrupts kill us. */ (void)signal(s, SIG_DFL); } /* ** Mark that the alarm went off. */ /* ARGSUSED0 */ STATIC SIGHANDLER CATCHalarm(s) int s; { GotAlarm = TRUE; if (JMPyes) longjmp(JMPwhere, 1); } /* check articles in streaming NNTP mode ** return TRUE on failure. */ STATIC BOOL check(i) int i; /* index of stbuf to send check for */ { char buff[NNTP_STRLEN]; /* send "check " to the other system */ (void)sprintf(buff, "check %s", stbuf[i].st_id); if (!REMwrite(buff, (int)strlen(buff), FALSE)) { (void)fprintf(stderr, "Can't check article, %s\n", strerror(errno)); return TRUE; } STAToffered++; if (Debug) { if (stbuf[i].st_retry) (void)fprintf(stderr, "> %s (retry %d)\n", buff, stbuf[i].st_retry); else (void)fprintf(stderr, "> %s\n", buff); } if (GotInterrupt) Interrupted(stbuf[i].st_fname, stbuf[i].st_id); /* That all. Response is checked later by strlisten() */ return FALSE; } /* Send article in "takethis streaming NNTP mode. ** return TRUE on failure. */ STATIC BOOL takethis(i) int i; /* index to stbuf to be sent */ { char buff[NNTP_STRLEN]; if (!stbuf[i].st_qp) { /* should already be open but ... */ /* Open the article. */ if (!(stbuf[i].st_qp = QIOopen(stbuf[i].st_fname, QIO_BUFFER))) { /* can not open it. Should check AltPath */ if (AltPath && (*(stbuf[i].st_fname) != '/')) { (void)sprintf(AltPath, "%s/%s", AltSpool, stbuf[i].st_fname); stbuf[i].st_qp = QIOopen(AltPath, QIO_BUFFER); } if (!(stbuf[i].st_qp)) { strel(i); return FALSE; /* Not an error. Could be canceled or expired */ } } } /* send "takethis " to the other system */ (void)sprintf(buff, "takethis %s", stbuf[i].st_id); if (!REMwrite(buff, (int)strlen(buff), FALSE)) { (void)fprintf(stderr, "Can't send takethis , %s\n", strerror(errno)); return TRUE; } if (Debug) (void)fprintf(stderr, "> %s\n", buff); if (GotInterrupt) Interrupted((char *)0, (char *)0); if (!REMsendarticle(stbuf[i].st_fname, stbuf[i].st_id, stbuf[i].st_qp)) return TRUE; QIOclose(stbuf[i].st_qp); /* should not need file again */ stbuf[i].st_qp = 0; /* so close to free descriptor */ stbuf[i].st_age = 0; /* That all. Response is checked later by strlisten() */ return FALSE; } /* listen for responses. Process acknowledgments to remove items from ** the queue. Also sends the articles on request. Returns TRUE on error. ** return TRUE on failure. */ STATIC BOOL strlisten() { int resp; int i; char *id, *p; char buff[NNTP_STRLEN]; int hash; while(TRUE) { if (!REMread(buff, (int)sizeof buff)) { (void)fprintf(stderr, "No reply to check, %s\n", strerror(errno)); return TRUE; } if (GotInterrupt) Interrupted((char *)0, (char *)0); if (Debug) (void)fprintf(stderr, "< %s", buff); /* Parse the reply. */ resp = atoi(buff); /* Skip the 1XX informational messages */ if ((resp >= 100) && (resp < 200)) continue; switch (resp) { /* first time is to verify it */ case NNTP_ERR_GOTID_VAL: case NNTP_OK_SENDID_VAL: case NNTP_OK_RECID_VAL: case NNTP_ERR_FAILID_VAL: case NNTP_RESENDID_VAL: if ((id = strchr(buff, '<')) != NULL) { p = strchr(id, '>'); if (p) *(p+1) = '\0'; hash = stidhash(id); i = stindex(id, hash); /* find table entry */ if (i < 0) { /* should not happen */ syslog(L_NOTICE, CANT_FINDIT, REMhost, REMclean(buff)); return (TRUE); /* can't find it! */ } } else { syslog(L_NOTICE, CANT_PARSEIT, REMhost, REMclean(buff)); return (TRUE); } break; case NNTP_GOODBYE_VAL: /* Most likely out of space -- no point in continuing. */ syslog(L_NOTICE, IHAVE_FAIL, REMhost, REMclean(buff)); return TRUE; /* NOTREACHED */ default: syslog(L_NOTICE, UNEXPECTED, REMhost, REMclean(buff)); if (Debug) (void)fprintf(stderr, "Unknown reply \"%s\"", buff); return (TRUE); } switch (resp) { /* now we take some action */ case NNTP_RESENDID_VAL: /* remote wants it later */ /* try again now because time has passed */ if (stbuf[i].st_retry < STNRETRY) { if (check(i)) return TRUE; stbuf[i].st_retry++; stbuf[i].st_age = 0; } else { /* requeue to disk for later */ Requeue(stbuf[i].st_fname, stbuf[i].st_id); strel(i); /* release entry */ } break; case NNTP_ERR_GOTID_VAL: /* remote doesn't want it */ strel(i); /* release entry */ STATrefused++; stnofail = 0; break; case NNTP_OK_SENDID_VAL: /* remote wants article */ if (takethis(i)) return TRUE; stnofail++; break; case NNTP_OK_RECID_VAL: /* remote received it OK */ strel(i); /* release entry */ STATaccepted++; break; case NNTP_ERR_FAILID_VAL: strel(i); /* release entry */ STATrejected++; stnofail = 0; break; } break; } return (FALSE); } /* ** Print a usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage: innxmit [-a] [-c] [-d] [-M] [-p] [-r] [-s] [-S] [-t#] [-T#] host file\n"); exit(1); } int main(ac, av) int ac; char *av[]; { static char SPOOL[] = _PATH_SPOOL; static char BATCHDIR[] = _PATH_BATCHDIR; static char SKIPPING[] = "Skipping \"%s\" --%s?\n"; register int i; register char *p; register QIOSTATE *qp; TIMEINFO Now; FILE *From; FILE *To; char buff[8192+128]; char *Article; char *ContentEncoding; char *ContentType; char *MessageID; SIGHANDLER (*old)(); unsigned int ConnectTimeout; unsigned int TotalTimeout; extern char *nntp_port; /* Set defaults. */ ConnectTimeout = 0; TotalTimeout = 0; AltSpool = NULL; (void)umask(NEWSUMASK); /* Parse JCL. */ while ((i = getopt(ac, av, "lA:acdMprsSt:T:vP:")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'A': AltSpool = optarg; AltPath = NEW(char, SPOOLNAMEBUFF + strlen(AltSpool)); break; case 'P': nntp_port = COPY(optarg); break; case 'a': AlwaysRewrite = TRUE; break; case 'c': DoCheck = FALSE; break; case 'd': Debug = TRUE; break; case 'l': logRejects = FALSE ; break ; case 'M': Mime = TRUE; break; case 'p': AlwaysRewrite = TRUE; Purging = TRUE; break; case 'r': DoRequeue = FALSE; break; case 's': TryStream = FALSE; break; case 'S': Slavish = TRUE; TryStream = FALSE; /* streaming does not support xreplic */ break; case 't': ConnectTimeout = atoi(optarg); break; case 'T': TotalTimeout = atoi(optarg); break; case 'v': STATprint = TRUE; break; } ac -= optind; av += optind; /* Parse arguments; host and filename. */ if (ac != 2) Usage(); REMhost = av[0]; BATCHname = av[1]; if (chdir(SPOOL) < 0) { (void)fprintf(stderr, "Can't cd to \"%s\", %s\n", SPOOL, strerror(errno)); exit(1); } (void)openlog("innxmit", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG); /* Open the batch file and lock others out. */ if (BATCHname[0] != '/') { BATCHname = NEW(char, STRLEN(BATCHDIR) + 1 + strlen(av[1]) + 1); (void)sprintf(BATCHname, "%s/%s", BATCHDIR, av[1]); } if ((i = open(BATCHname, O_RDWR)) < 0 || (BATCHqp = QIOfdopen(i, QIO_BUFFER)) == NULL) { (void)fprintf(stderr, "Can't open \"%s\", %s\n", BATCHname, strerror(errno)); exit(1); } if (LockFile(QIOfileno(BATCHqp), TRUE) < 0) { #if defined(EWOULDBLOCK) if (errno == EWOULDBLOCK) exit(0); #endif /* defined(EWOULDBLOCK) */ (void)fprintf(stderr, "Can't lock \"%s\", %s\n", BATCHname, strerror(errno)); exit(1); } /* Get a temporary name in the same directory as the batch file. */ p = strrchr(BATCHname, '/'); BATCHtemp = NEW(char, strlen(BATCHname) + STRLEN("/bchXXXXXX") + 1); *p = '\0'; (void)sprintf(BATCHtemp, "%s/bchXXXXXX", BATCHname); *p = '/'; /* Set up buffer used by REMwrite. */ REMbuffer = NEW(char, OUTPUT_BUFFER_SIZE); REMbuffend = &REMbuffer[OUTPUT_BUFFER_SIZE]; REMbuffptr = REMbuffer; /* Start timing. */ if (GetTimeInfo(&Now) < 0) { (void)fprintf(stderr, "Can't get time, %s\n", strerror(errno)); exit(1); } STATbegin = TIMEINFOasDOUBLE(Now); if (!Purging) { /* Open a connection to the remote server. */ if (ConnectTimeout) { GotAlarm = FALSE; old = signal(SIGALRM, CATCHalarm); (void)alarm(ConnectTimeout); JMPyes = TRUE; if (setjmp(JMPwhere)) { (void)fprintf(stderr, "Can't connect to %s, timed out\n", REMhost); exit(1); } } if (NNTPconnect(REMhost, &From, &To, buff) < 0 || GotAlarm) { i = errno; (void)fprintf(stderr, "Can't connect to %s, %s\n", REMhost, buff[0] ? REMclean(buff) : strerror(errno)); if (GotAlarm) syslog(L_NOTICE, CANT_CONNECT, REMhost, "timeout"); else syslog(L_NOTICE, CANT_CONNECT, REMhost, buff[0] ? REMclean(buff) : strerror(i)); exit(1); } if (Debug) (void)fprintf(stderr, "< %s\n", REMclean(buff)); if (NNTPsendpassword(REMhost, From, To) < 0 || GotAlarm) { i = errno; (void)fprintf(stderr, "Can't authenticate with %s, %s\n", REMhost, strerror(errno)); syslog(L_ERROR, CANT_AUTHENTICATE, REMhost, GotAlarm ? "timeout" : strerror(i)); /* Don't send quit; we want the remote to print a message. */ exit(1); } if (ConnectTimeout) { (void)alarm(0); (void)signal(SIGALRM, old); JMPyes = FALSE; } /* We no longer need standard I/O. */ FromServer = fileno(From); ToServer = fileno(To); if (TryStream) { if (!REMwrite(modestream, (int)strlen(modestream), FALSE)) { (void)fprintf(stderr, "Can't negotiate %s, %s\n", modestream, strerror(errno)); } if (Debug) (void)fprintf(stderr, ">%s\n", modestream); /* Does he understand mode stream? */ if (!REMread(buff, (int)sizeof buff)) { (void)fprintf(stderr, "No reply to %s, %s\n", modestream, strerror(errno)); } else { if (Debug) (void)fprintf(stderr, "< %s", buff); /* Parse the reply. */ switch (atoi(buff)) { default: (void)fprintf(stderr, "Unknown reply to \"%s\" -- %s", modestream, buff); CanStream = FALSE; break; case NNTP_OK_STREAM_VAL: /* YES! */ CanStream = TRUE; break; case NNTP_AUTH_NEEDED_VAL: /* authentication refusal */ case NNTP_BAD_COMMAND_VAL: /* normal refusal */ CanStream = FALSE; break; } } if (CanStream) { int i; for (i = 0; i < STNBUF; i++) { /* reset buffers */ stbuf[i].st_fname = 0; stbuf[i].st_id = 0; stbuf[i].st_qp = 0; } stnq = 0; } } } /* Set up signal handlers. */ (void)signal(SIGHUP, CATCHinterrupt); (void)signal(SIGINT, CATCHinterrupt); (void)signal(SIGTERM, CATCHinterrupt); (void)signal(SIGPIPE, SIG_IGN); if (TotalTimeout) { (void)alarm(TotalTimeout); (void)signal(SIGALRM, CATCHalarm); } /* Main processing loop. */ GotInterrupt = FALSE; GotAlarm = FALSE; for (Article = NULL, MessageID = NULL; ; ) { if (GotAlarm) { (void)fprintf(stderr, "Timed out\n"); /* Don't resend the current article. */ RequeueRestAndExit((char *)NULL, (char *)NULL); } if (GotInterrupt) Interrupted(Article, MessageID); if ((Article = QIOread(BATCHqp)) == NULL) { if (QIOtoolong(BATCHqp)) { (void)fprintf(stderr, "Skipping long line in \"%s\"\n", BATCHname); (void)QIOread(BATCHqp); continue; } if (QIOerror(BATCHqp)) { (void)fprintf(stderr, "Can't read \"%s\", %s\n", BATCHname, strerror(errno)); ExitWithStats(1); } /* Normal EOF -- we're done. */ QIOclose(BATCHqp); BATCHqp = NULL; break; } /* Ignore blank lines. */ if (*Article == '\0') continue; /* Split the line into possibly two fields. */ if (Article[0] == '/' && Article[STRLEN(SPOOL)] == '/' && EQn(Article, SPOOL, STRLEN(SPOOL))) Article += STRLEN(SPOOL) + 1; if ((MessageID = strchr(Article, ' ')) != NULL) { *MessageID++ = '\0'; if (!Slavish) { if (*MessageID != '<' || (p = strrchr(MessageID, '>')) == NULL || *++p != '\0') { (void)fprintf(stderr, "Ignoring line \"%s %s...\"\n", Article, MessageID); continue; } } } if (*Article == '\0') { if (MessageID) (void)fprintf(stderr, "Empty filename for \"%s\" in \"%s\"\n", MessageID, BATCHname); else (void)fprintf(stderr, "Empty filename, no Message-ID in \"%s\"\n", BATCHname); /* We could do a history lookup. */ continue; } if (Purging && MessageID != NULL && !Expired(MessageID)) { Requeue(Article, MessageID); continue; } /* * If the command ("IHAVE" or "XREPLIC") plus the "message-id", * separating space and trailing CR-NL will exceed the maximum command * length permitted by the RFC (i.e. NNTP_STRLEN), then reject the * article and continue to avoid overrunning buffers and throwing the * server on the recieving end a blow from behind. This really comes * into play with XREPLIC feeds to slaved servers where cross-posting * really causes the "message-ID" to get too long really quickly. Note * that the value of 12 is the length of "XREPLIC " plus 2 for the * CR-NL, plus 2 for a safety buffer. */ if (MessageID != NULL && (strlen(MessageID) > NNTP_STRLEN - 12)) { (void)fprintf(stderr, "Dropping article in \"%s\" - long message id \"%s\"\n", BATCHname, MessageID); continue; } /* Open the article. */ if ((qp = QIOopen(Article, QIO_BUFFER)) == NULL && AltSpool && *Article != '/') { (void)sprintf(AltPath, "%s/%s", AltSpool, Article); qp = QIOopen(AltPath, QIO_BUFFER); } if (qp == NULL) { switch (errno) { default: (void)fprintf(stderr, "Requeue \"%s\", %s\n", Article, strerror(errno)); Requeue(Article, MessageID); break; case ENOENT: /* Cancelled or expired. We could look the file up * in the history database and see if it does exist. */ break; case ENOTDIR: (void)fprintf(stderr, SKIPPING, Article, "mangled"); break; } continue; } if (Purging) { QIOclose(qp); Requeue(Article, MessageID); continue; } /* Get the Message-ID from the article if we need to. */ if (MessageID == NULL) { if ((MessageID = GetMessageID(qp)) == NULL) { (void)fprintf(stderr, SKIPPING, Article, "no Message-ID"); QIOclose(qp); continue; } if (QIOrewind(qp) < 0) { (void)fprintf(stderr, "Can't rewind \"%s\", %s -- requeue\n", Article, strerror(errno)); QIOclose(qp); Requeue(Article, (char *)NULL); continue; } } if (Mime == TRUE) { MimeArticle = MTnotmime; GetMimeHeaders(qp, &ContentEncoding, &ContentType); if (QIOrewind(qp) < 0) { (void)fprintf(stderr, "Can't rewind \"%s\", %s -- requeue\n", Article, strerror(errno)); QIOclose(qp); Requeue(Article, (char *)NULL); continue; } if (ContentEncoding && (caseEQ(ContentEncoding, "binary") || caseEQ(ContentEncoding, "8bit"))) if (ContentType == NULL || caseEQ(ContentType, "text")) MimeArticle = MTquotedprintable; else /* Shouldbe MTbase64, but not implemented yet. */ MimeArticle = MTnotmime; } if (GotInterrupt) Interrupted(Article, MessageID); /* Offer the article. */ if (CanStream) { int i; int lim; int hash; hash = stidhash(MessageID); if (stindex(MessageID, hash) >= 0) { /* skip duplicates in queue */ if (Debug) (void)fprintf(stderr, "Skipping duplicate ID %s\n", MessageID); QIOclose(qp); continue; } /* This code tries to optimize by sending a burst of "check" * commands before flushing the buffer. This should result * in several being sent in one packet reducing the network * overhead. */ if (DoCheck && (stnofail < STNC)) lim = STNBUF; else lim = STNBUFL; if (stnq >= lim) { /* need to empty a buffer */ while (stnq >= STNBUFL) { /* or several */ if (strlisten()) { RequeueRestAndExit(Article, MessageID); } } } /* save new article in the buffer */ i = stalloc(Article, MessageID, qp, hash); if (i < 0) { QIOclose(qp); RequeueRestAndExit(Article, MessageID); } if (DoCheck && (stnofail < STNC)) { if (check(i)) { RequeueRestAndExit((char *)NULL, (char *)NULL); } } else { STAToffered++ ; if (takethis(i)) { RequeueRestAndExit((char *)NULL, (char *)NULL); } } /* check for need to resend any IDs */ for (i = 0; i < STNBUF; i++) { if ((stbuf[i].st_fname) && (stbuf[i].st_fname[0] != '\0')) { if (stbuf[i].st_age++ > stnq) { /* This should not happen but just in case ... */ if (stbuf[i].st_retry < STNRETRY) { if (check(i)) /* resend check */ RequeueRestAndExit((char *)NULL, (char *)NULL); retries++; stbuf[i].st_retry++; stbuf[i].st_age = 0; } else { /* requeue to disk for later */ Requeue(stbuf[i].st_fname, stbuf[i].st_id); strel(i); /* release entry */ } } } } continue; /* next article */ } (void)sprintf(buff, "%s %s", Slavish ? "xreplic" : "ihave", MessageID); if (!REMwrite(buff, (int)strlen(buff), FALSE)) { (void)fprintf(stderr, "Can't offer article, %s\n", strerror(errno)); QIOclose(qp); RequeueRestAndExit(Article, MessageID); } STAToffered++; if (Debug) (void)fprintf(stderr, "> %s\n", buff); if (GotInterrupt) Interrupted(Article, MessageID); /* Does he want it? */ if (!REMread(buff, (int)sizeof buff)) { (void)fprintf(stderr, "No reply to ihave, %s\n", strerror(errno)); QIOclose(qp); RequeueRestAndExit(Article, MessageID); } if (GotInterrupt) Interrupted(Article, MessageID); if (Debug) (void)fprintf(stderr, "< %s", buff); /* Parse the reply. */ switch (atoi(buff)) { default: (void)fprintf(stderr, "Unknown reply to \"%s\" -- %s", Article, buff); if (DoRequeue) Requeue(Article, MessageID); break; case NNTP_BAD_COMMAND_VAL: case NNTP_SYNTAX_VAL: case NNTP_ACCESS_VAL: /* The receiving server is likely confused...no point in continuing */ syslog(L_FATAL, GOT_BADCOMMAND, REMhost, MessageID, REMclean(buff)); RequeueRestAndExit(Article, MessageID); /* NOTREACHED */ case NNTP_AUTH_NEEDED_VAL: case NNTP_RESENDIT_VAL: case NNTP_GOODBYE_VAL: /* Most likely out of space -- no point in continuing. */ syslog(L_NOTICE, IHAVE_FAIL, REMhost, REMclean(buff)); RequeueRestAndExit(Article, MessageID); /* NOTREACHED */ case NNTP_SENDIT_VAL: if (!REMsendarticle(Article, MessageID, qp)) RequeueRestAndExit(Article, MessageID); break; case NNTP_HAVEIT_VAL: STATrefused++; break; #if defined(NNTP_SENDIT_LATER) case NNTP_SENDIT_LATER_VAL: Requeue(Article, MessageID); break; #endif /* defined(NNTP_SENDIT_LATER) */ } QIOclose(qp); } if (CanStream) { /* need to wait for rest of ACKs */ while (stnq > 0) { if (strlisten()) { RequeueRestAndExit((char *)NULL, (char *)NULL); } } } if (BATCHfp != NULL) /* We requeued something, so close the temp file. */ CloseAndRename(); else if (unlink(BATCHname) < 0 && errno != ENOENT) (void)fprintf(stderr, "Can't remove \"%s\", %s\n", BATCHtemp, strerror(errno)); ExitWithStats(0); /* NOTREACHED */ } inn-1.7.2/backends/buffchan.c0100644000175100001440000002547006443103542014331 0ustar mdusers/* $Revision: 1.10 $ ** ** Buffered file exploder for innd. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #include "paths.h" #include "libinn.h" #include "qio.h" #include "macros.h" extern void MAPread(); extern char *MAPname(); /* ** Hash functions for hashing sitenames. */ #define SITE_HASH(Name, p, j) \ for (p = Name, j = 0; *p; ) j = (j << 5) + j + *p++ #define SITE_SIZE 128 #define SITE_BUCKET(j) &SITEtable[j & (SITE_SIZE - 1)] /* ** Entry for a single active site. */ typedef struct _SITE { BOOL Dropped; STRING Name; int CloseLines; int FlushLines; time_t LastFlushed; time_t LastClosed; int CloseSeconds; int FlushSeconds; FILE *F; STRING Filename; char *Buffer; } SITE; /* ** Site hashtable bucket. */ typedef struct _SITEHASH { int Size; int Used; SITE *Sites; } SITEHASH; /* Global variables. */ STATIC char *Format; STATIC STRING Map; STATIC int BufferMode; STATIC int CloseEvery; STATIC int FlushEvery; STATIC int CloseSeconds; STATIC int FlushSeconds; STATIC SIGVAR GotInterrupt; STATIC SITEHASH SITEtable[SITE_SIZE]; STATIC TIMEINFO Now; #if defined(DONT_HAVE_FCHMOD) /* ** A dummy fchmod. */ /* ARGSUSED */ int fchmod(i) int i; { } #endif /* defined(DONT_HAVE_FCHMOD) */ /* ** Set up the site information. Basically creating empty buckets. */ STATIC void SITEsetup() { register SITEHASH *shp; for (shp = SITEtable; shp < ENDOF(SITEtable); shp++) { shp->Size = 3; shp->Sites = NEW(SITE, shp->Size); shp->Used = 0; } } /* ** Close a site */ STATIC void SITEclose(sp) register SITE *sp; { register FILE *F; if ((F = sp->F) != NULL) { if (fflush(F) == EOF || ferror(F) || fchmod((int)fileno(F), 0664) < 0 || fclose(F) == EOF) (void)fprintf(stderr, "buffchan %s cant close %s, %s\n", sp->Name, sp->Filename, strerror(errno)); sp->F = NULL; } } /* ** Close all open sites. */ STATIC void SITEcloseall() { register SITEHASH *shp; register SITE *sp; register int i; for (shp = SITEtable; shp < ENDOF(SITEtable); shp++) for (sp = shp->Sites, i = shp->Used; --i >= 0; sp++) SITEclose(sp); } /* ** Open the file for a site. */ STATIC void SITEopen(sp) register SITE *sp; { int e; if ((sp->F = xfopena(sp->Filename)) == NULL && ((e = errno) != EACCES || chmod(sp->Filename, 0644) < 0 || (sp->F = xfopena(sp->Filename)) == NULL)) { (void)fprintf(stderr, "buffchan %s cant fopen %s, %s\n", sp->Name, sp->Filename, strerror(e)); if ((sp->F = fopen("/dev/null", "w")) == NULL) { /* This really should not happen. */ (void)fprintf(stderr, "buffchan %s cant fopen %s, %s\n", sp->Name, "/dev/null", strerror(errno)); exit(1); } } else if (fchmod((int)fileno(sp->F), 0444) < 0) (void)fprintf(stderr, "buffchan %s cant fchmod %s %s\n", sp->Name, sp->Filename, strerror(errno)); if (BufferMode != '\0') setbuf(sp->F, sp->Buffer); /* Reset all counters. */ sp->FlushLines = 0; sp->CloseLines = 0; sp->LastFlushed = Now.time; sp->LastClosed = Now.time; sp->Dropped = FALSE; } /* ** Find a site, possibly create if not found. */ STATIC SITE * SITEfind(Name, CanCreate) char *Name; BOOL CanCreate; { register char *p; register int i; unsigned int j; register SITE *sp; SITEHASH *shp; char c; char buff[BUFSIZ]; /* Look for site in the hash table. */ /* SUPPRESS 6 *//* Over/underflow from plus expression */ SITE_HASH(Name, p, j); shp = SITE_BUCKET(j); for (c = *Name, sp = shp->Sites, i = shp->Used; --i >= 0; sp++) if (c == sp->Name[0] && caseEQ(Name, sp->Name)) return sp; if (!CanCreate) return NULL; /* Adding a new site -- grow hash bucket if we need to. */ if (shp->Used == shp->Size - 1) { shp->Size *= 2; RENEW(shp->Sites, SITE, shp->Size); } sp = &shp->Sites[shp->Used++]; /* Fill in the structure for the new site. */ sp->Name = COPY(Name); (void)sprintf(buff, (STRING)Format, Map ? MAPname(Name) : sp->Name); sp->Filename = COPY(buff); if (BufferMode == 'u') sp->Buffer = NULL; else if (BufferMode == 'b') sp->Buffer = NEW(char, BUFSIZ); SITEopen(sp); return sp; } /* ** Flush a site -- close and re-open the file. */ STATIC void SITEflush(sp) register SITE *sp; { register FILE *F; if ((F = sp->F) != NULL) { if (fflush(F) == EOF || ferror(F) || fchmod((int)fileno(F), 0664) < 0 || fclose(F) == EOF) (void)fprintf(stderr, "buffchan %s cant close %s, %s\n", sp->Name, sp->Filename, strerror(errno)); sp->F = NULL; } if (!sp->Dropped) SITEopen(sp); } /* ** Flush all open sites. */ STATIC void SITEflushall() { register SITEHASH *shp; register SITE *sp; register int i; for (shp = SITEtable; shp < ENDOF(SITEtable); shp++) for (sp = shp->Sites, i = shp->Used; --i >= 0; sp++) SITEflush(sp); } /* ** Write data to a site. */ STATIC void SITEwrite(name, text, len) register char *name; register char *text; register int len; { register SITE *sp; sp = SITEfind(name, TRUE); if (sp->F == NULL) SITEopen(sp); if (fwrite((POINTER)text, (SIZE_T)1, (SIZE_T)len, sp->F) != len) (void)fprintf(stderr, "buffchan %s cant write %s\n", sp->Name, strerror(errno)); /* Bump line count; see if time to close or flush. */ if (CloseEvery && ++(sp->CloseLines) >= CloseEvery) { SITEflush(sp); return; } if (CloseSeconds && sp->LastClosed + CloseSeconds < Now.time) { SITEflush(sp); return; } if (FlushEvery && ++(sp->FlushLines) >= FlushEvery) { if (fflush(sp->F) == EOF || ferror(sp->F)) (void)fprintf(stderr, "buffchan %s cant flush %s, %s\n", sp->Name, sp->Filename, strerror(errno)); sp->LastFlushed = Now.time; sp->FlushLines = 0; } else if (FlushSeconds && sp->LastFlushed + FlushSeconds < Now.time) { if (fflush(sp->F) == EOF || ferror(sp->F)) (void)fprintf(stderr, "buffchan %s cant flush %s, %s\n", sp->Name, sp->Filename, strerror(errno)); sp->LastFlushed = Now.time; sp->FlushLines = 0; } } /* ** Handle a command message. */ STATIC void Process(p) register char *p; { register SITE *sp; if (*p == 'b' && EQn(p, "begin", 5)) /* No-op. */ return; if (*p == 'f' && EQn(p, "flush", 5)) { for (p += 5; ISWHITE(*p); p++) continue; if (*p == '\0') SITEflushall(); else if ((sp = SITEfind(p, FALSE)) != NULL) SITEflush(sp); else /*(void)fprintf(stderr, "buffchan flush %s unknown site\n", p);*/ ; return; } if (*p == 'd' && EQn(p, "drop", 4)) { for (p += 4; ISWHITE(*p); p++) continue; if (*p == '\0') SITEcloseall(); else if ((sp = SITEfind(p, FALSE)) == NULL) (void)fprintf(stderr, "buffchan drop %s unknown site\n", p); else { SITEclose(sp); sp->Dropped = TRUE; } return; } if (*p == 'r' && EQn(p, "readmap", 7)) { MAPread(Map); return; } /* Other command messages -- ignored. */ (void)fprintf(stderr, "buffchan unknown message %s\n", p); } /* ** Print usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage error.\n"); exit(1); } /* ** Mark that we got a signal; let two signals kill us. */ STATIC SIGHANDLER CATCHinterrupt(s) int s; { GotInterrupt = TRUE; (void)signal(s, SIG_DFL); } int main(ac, av) int ac; char *av[]; { static char BATCHDIR[] = _PATH_BATCHDIR; register QIOSTATE *qp; register int i; register int Fields; register char *p; register char *next; register char *line; char *Directory; BOOL Redirect; FILE *F; /* Set defaults. */ Directory = NULL; Fields = 1; Format = NULL; Redirect = TRUE; GotInterrupt = FALSE; (void)umask(NEWSUMASK); (void)signal(SIGHUP, CATCHinterrupt); (void)signal(SIGINT, CATCHinterrupt); (void)signal(SIGQUIT, CATCHinterrupt); (void)signal(SIGPIPE, CATCHinterrupt); (void)signal(SIGTERM, CATCHinterrupt); (void)signal(SIGALRM, CATCHinterrupt); /* Parse JCL. */ while ((i = getopt(ac, av, "bc:C:d:f:l:L:m:p:rs:u")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'b': case 'u': BufferMode = i; break; case 'c': CloseEvery = atoi(optarg); break; case 'C': CloseSeconds = atoi(optarg); break; case 'd': Directory = optarg; if (Format == NULL) Format ="%s"; break; case 'f': Fields = atoi(optarg); break; case 'l': FlushEvery = atoi(optarg); break; case 'L': FlushSeconds = atoi(optarg); break; case 'm': Map = optarg; MAPread(Map); break; case 'p': if ((F = fopen(optarg, "w")) == NULL) { (void)fprintf(stderr, "buffchan cant fopen %s %s\n", optarg, strerror(errno)); exit(1); } (void)fprintf(F, "%ld\n", (long)getpid()); if (ferror(F) || fclose(F) == EOF) { (void)fprintf(stderr, "buffchan cant fclose %s %s\n", optarg, strerror(errno)); exit(1); } break; case 'r': Redirect = FALSE; break; case 's': Format = optarg; break; } ac -= optind; av += optind; if (ac) Usage(); /* Do some basic set-ups. */ if (Redirect) (void)freopen(_PATH_ERRLOG, "a", stderr); if (Format == NULL) { Format = NEW(char, STRLEN(BATCHDIR) + 1 + 2 + 1); (void)sprintf(Format, "%s/%%s", BATCHDIR); } if (Directory && chdir(Directory) < 0) { (void)fprintf(stderr, "buffchan cant chdir %s %s\n", Directory, strerror(errno)); exit(1); } SITEsetup(); /* Read input. */ for (qp = QIOfdopen((int)fileno(stdin), 0); !GotInterrupt ; ) { if ((line = QIOread(qp)) == NULL) { if (QIOerror(qp)) { (void)fprintf(stderr, "buffchan cant read %s\n", strerror(errno)); break; } if (QIOtoolong(qp)) { (void)fprintf(stderr, "buffchan long_line"); (void)QIOread(qp); continue; } /* Normal EOF. */ break; } /* Command? */ if (*line == EXP_CONTROL && *++line != EXP_CONTROL) { Process(line); continue; } /* Skip the right number of leading fields. */ for (i = Fields, p = line; *p; p++) if (*p == ' ' && --i <= 0) break; if (*p == '\0') /* Nothing to write. Probably shouldn't happen. */ continue; /* Add a newline, get the length of all leading fields. */ *p++ = '\n'; i = p - line; if (GetTimeInfo(&Now) < 0) { (void)fprintf(stderr, "buffchan cant gettime %s\n", strerror(errno)); break; } /* Rest of the line is space-separated list of filenames. */ for (; *p; p = next) { /* Skip whitespace, get next word. */ while (*p == ' ') p++; for (next = p; *next && *next != ' '; next++) continue; if (*next) *next++ = '\0'; SITEwrite(p, line, i); } } SITEcloseall(); exit(0); /* NOTREACHED */ } inn-1.7.2/backends/overchan.c0100644000175100001440000001426206443103542014357 0ustar mdusers/* $Revision: 1.6 $ ** ** Parse input to add to news overview database. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #include #include "libinn.h" #include "macros.h" #include "paths.h" #include "qio.h" STATIC BOOL InSpoolDir; /* ** Try to make one directory. Return FALSE on error. */ STATIC BOOL MakeDir(Name) char *Name; { struct stat Sb; if (mkdir(Name, GROUPDIR_MODE) >= 0) return TRUE; /* See if it failed because it already exists. */ return stat(Name, &Sb) >= 0 && S_ISDIR(Sb.st_mode); } /* ** Make overview directory if not in spool directory. Return 0 if ok, ** else -1. */ STATIC BOOL MakeOverDir(Name) register char *Name; { register char *p; BOOL made; if (InSpoolDir) return FALSE; /* Optimize common case -- parent almost always exists. */ if (MakeDir(Name)) return TRUE; /* Try to make each of comp and comp/foo in turn. */ for (p = Name; *p; p++) if (*p == '/') { *p = '\0'; made = MakeDir(Name); *p = '/'; if (!made) return FALSE; } return MakeDir(Name); } /* ** Get the lock for the group, then open the data file and append the ** new data. Return FALSE on error. */ STATIC BOOL WriteData(Dir, Art, Rest, Complain) char *Dir; char *Art; char *Rest; BOOL Complain; { static char TAB[] = "\t"; static char NL[] = "\n"; struct iovec iov[4]; register int fd; register int i; register BOOL ok; char file[SPOOLNAMEBUFF]; struct stat Sb; /* Build the I/O vector. */ i = 0; iov[i].iov_base = Art; iov[i++].iov_len = strlen(Art); iov[i].iov_base = TAB; iov[i++].iov_len = 1; iov[i].iov_base = Rest; iov[i++].iov_len = strlen(Rest); iov[i].iov_base = NL; iov[i++].iov_len = 1; /* Name the data file. */ (void)sprintf(file, "%s/%s", Dir, _PATH_OVERVIEW); /* Open and lock the file. */ for ( ; ; ) { if ((fd = open(file, O_WRONLY | O_CREAT | O_APPEND, ARTFILE_MODE)) < 0) { if (Complain && errno != ENOENT) (void)fprintf(stderr, "overchan cant open %s, %s\n", file, strerror(errno)); return FALSE; } if (LockFile(fd, FALSE) < 0) /* Wait for it. */ (void)LockFile(fd, TRUE); else { /* Got the lock; make sure the file is still there. */ if (fstat(fd, &Sb) < 0) { (void)fprintf(stderr, "overchan cant fstat %s, %s\n", file, strerror(errno)); (void)close(fd); return FALSE; } if (Sb.st_nlink > 0) break; } /* Close file -- expireover might have removed it -- and try again. */ (void)close(fd); } ok = TRUE; if (xwritev(fd, iov, i) < 0) { (void)fprintf(stderr, "overchan cant write %s %s\n", file, strerror(errno)); ok = FALSE; } /* Close up and return. */ if (close(fd) < 0) { (void)fprintf(stderr, "overchan cant close %s %s\n", file, strerror(errno)); ok = FALSE; } return ok; } /* ** Process the input. Data can come from innd: ** news/group/name/ [space news/group/]... \t data ** or from mkov: ** news/group/name \t number \t data */ STATIC void ProcessIncoming(INNinput, qp) BOOL INNinput; QIOSTATE *qp; { register char *Dir; register char *Art; register char *Rest; register char *p; for ( ; ; ) { /* Read the first line of data. */ if ((p = QIOread(qp)) == NULL) { if (QIOtoolong(qp)) { (void)fprintf(stderr, "overchan line too long\n"); continue; } break; } /* If doing mkov output, process that line and continue. */ if (!INNinput) { /* Split up the fields. */ Dir = p; if ((p = strchr(p, '\t')) == NULL || p[1] == '\0') { (void)fprintf(stderr, "overchan missing field 1: %s\n", Dir); return; } *p++ = '\0'; Art = p; if ((p = strchr(p, '\t')) == NULL || p[1] == '\0') { (void)fprintf(stderr, "overchan missing field 2: %s\n", Dir); return; } *p++ = '\0'; /* Write data. */ if (!WriteData(Dir, Art, p, FALSE) && (!MakeOverDir(Dir) || !WriteData(Dir, Art, p, TRUE))) (void)fprintf(stderr, "overchan cant update %s %s\n", Dir, strerror(errno)); continue; } /* Nip off the first part. */ Dir = p; if ((Rest = strchr(p, '\t')) == NULL) { (void)fprintf(stderr, "overchan bad input\n"); continue; } *Rest++ = '\0'; /* Process all fields in the first part. */ for ( ; *Dir; Dir = p) { /* Split up this field, then split it up. */ for (p = Dir; *p; p++) if (ISWHITE(*p)) { *p++ = '\0'; break; } if ((Art = strrchr(Dir, '/')) == NULL || Art[1] == '\0') { (void)fprintf(stderr, "overchan bad entry %s\n", Dir); continue; } *Art++ = '\0'; /* Write data. */ if (!WriteData(Dir, Art, Rest, FALSE) && (!MakeOverDir(Dir) || !WriteData(Dir, Art, Rest, TRUE))) (void)fprintf(stderr, "overchan cant update %s %s\n", Dir, strerror(errno)); } } if (QIOerror(qp)) (void)fprintf(stderr, "overchan cant read %s\n", strerror(errno)); QIOclose(qp); } STATIC NORETURN Usage() { (void)fprintf(stderr, "usage: overchan [-c] [-D dir] [files...]\n"); exit(1); } int main(ac, av) int ac; char *av[]; { register int i; QIOSTATE *qp; char *Dir; BOOL INNinput; /* Set defaults. */ Dir = _PATH_OVERVIEWDIR; INNinput = TRUE; (void)umask(NEWSUMASK); /* Parse JCL. */ while ((i = getopt(ac, av, "cD:")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'c': INNinput = FALSE; break; case 'D': Dir = optarg; break; } ac -= optind; av += optind; InSpoolDir = EQ(Dir, _PATH_SPOOL); if (chdir(Dir) < 0) { (void)fprintf(stderr, "overchan cant chdir %s %s\n", Dir, strerror(errno)); exit(1); } if (ac == 0) ProcessIncoming(INNinput, QIOfdopen(STDIN, QIO_BUFFER)); else { for ( ; *av; av++) if (EQ(*av, "-")) ProcessIncoming(INNinput, QIOfdopen(STDIN, QIO_BUFFER)); else if ((qp = QIOopen(*av, QIO_BUFFER)) == NULL) (void)fprintf(stderr, "overchan cant open %s %s\n", *av, strerror(errno)); else ProcessIncoming(INNinput, qp); } exit(0); /* NOTREACHED */ } inn-1.7.2/expire/0040755000175100001440000000000006443103542012126 5ustar mdusersinn-1.7.2/expire/prunehistory.c0100644000175100001440000001437606443103542015055 0ustar mdusers/* $Revision: 1.8 $ ** ** Prune file names from history file. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include "paths.h" #include "libinn.h" #include "dbz.h" #include "macros.h" /* ** A reusable data buffer. */ typedef struct _BUFFER { char *Data; int Size; int Used; } BUFFER; /* ** Convert a pathname into a history-like entry. */ STATIC void Splice(name, Line) register char *name; BUFFER *Line; { static char SPOOL[] = _PATH_SPOOL; register char *last; register char *p; register char *end; register int i; register int j; /* Make sure it's a relative pathname. */ if (name[0] == '/' && name[STRLEN(SPOOL)] == '/' && EQn(name, SPOOL, STRLEN(SPOOL))) name += STRLEN(SPOOL); /* Turn foo/bar/baz into foo.bar/baz and get the length. */ for (last = NULL, p = name; *p; p++) if (*p == '/') { last = p; *p = '.'; } if (last) *last = '/'; i = p - name; if (i == 0 || i > Line->Used) /* No file (shouldn't happen) or line too small to hold it. */ return; /* Look for the string; allow it to appear multiple times. */ end = &Line->Data[Line->Used - i]; for (p = Line->Data; p <= end; ) if (*p == *name && EQn(p, name, i) && (p == end || ISWHITE(p[i]))) for (j = i; --j >= 0; ) *p++ = ' '; else p++; } /* ** Print usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage: prunehistory [-f file] [input]\n"); exit(1); } int main(ac, av) int ac; char *av[]; { static char SEPS[] = " \t"; register char *p; register char *q; register FILE *rfp; register int wfd; register int c; register int i; OFFSET_T where; char buff[BUFSIZ]; char *files; datum key; datum value; STRING History; BUFFER Line; BOOL Passing; /* Set defaults. */ History = _PATH_HISTORY; Line.Size = BUFSIZ; Line.Data = NEW(char, Line.Size); Line.Used = 0; Passing = FALSE; /* Parse JCL. */ while ((i = getopt(ac, av, "f:p")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'f': History = optarg; break; case 'p': Passing = TRUE; break; } ac -= optind; av += optind; if (ac) Usage(); /* Open files. */ if (dbminit(History) < 0) { (void)fprintf(stderr, "Can't set up \"%s\" database, %s\n", History, strerror(errno)); exit(1); } if ((rfp = fopen(History, "r")) == NULL) { (void)fprintf(stderr, "Can't open \"%s\" for reading, %s\n", History, strerror(errno)); exit(1); } if ((wfd = open(History, O_WRONLY)) < 0) { (void)fprintf(stderr, "Can't open \"%s\" for writing, %s\n", History, strerror(errno)); (void)fclose(rfp); exit(1); } /* Loop over all input. */ while (fgets(buff, sizeof buff, stdin) != NULL) { if ((p = strchr(buff, '\n')) == NULL) { if (Passing) (void)printf("%s\n", buff); else (void)fprintf(stderr, "Line too long, ignored:\n\t%s\n", buff); continue; } *p = '\0'; /* Ignore blank and comment lines. */ if (buff[0] == '\0' || buff[0] == COMMENT_CHAR) { if (Passing) (void)printf("%s\n", buff); continue; } if (buff[0] != '<' || (p = strchr(buff, '>')) == NULL) { if (Passing) (void)printf("%s\n", buff); else (void)fprintf(stderr, "Line doesn't start with a , ignored:\n\t%s\n", buff); continue; } *++p = '\0'; files = p + 1; /* Loop up the article. */ key.dsize = p - buff + 1; key.dptr = buff; value = dbzfetch(key); if (value.dptr == NULL || value.dsize != sizeof where) { (void)fprintf(stderr, "No entry for \"%s\", %s\n", buff, strerror(errno)); continue; } /* Copy the value to an aligned spot. */ for (p = value.dptr, q = (char *)&where, i = sizeof where; --i >= 0; ) *q++ = *p++; if (fseek(rfp, where, SEEK_SET) == -1) { (void)fprintf(stderr, "Can't fseek for \"%s\", %s\n", buff, strerror(errno)); continue; } /* Move forward to the filename fields, and note where they start. */ for (i = 2; (c = getc(rfp)) != EOF && c != '\n'; ) if (c == HIS_FIELDSEP && --i == 0) break; if (c != HIS_FIELDSEP) { (void)fprintf(stderr, "Bad text line for \"%s\", %s\n", buff, strerror(errno)); continue; } where = ftell(rfp); /* Read the the first chunk. */ i = fread((POINTER)Line.Data, (SIZE_T)1, BUFSIZ, rfp); if (i <= 0) { (void)fprintf(stderr, "Bad read for \"%s\", %s\n", buff, strerror(errno)); continue; } Line.Used = i; /* No newline; get another chunk and try again. */ while ((p = memchr((POINTER)Line.Data, '\n', (SIZE_T)Line.Used)) == NULL) { if (Line.Used + BUFSIZ >= Line.Size) { Line.Size += BUFSIZ; RENEW(Line.Data, char, Line.Size); } i = fread((POINTER)&Line.Data[Line.Used], (SIZE_T)1, BUFSIZ, rfp); if (i <= 0) break; Line.Used += i; if (Line.Used >= BUFSIZ * 10) { (void)fprintf(stderr, "Too long: "); break; } } if (p == NULL) { (void)fprintf(stderr, "Can't read line for \"%s\", %s\n", buff, strerror(errno)); continue; } Line.Used = p - Line.Data; /* Get the write pointer ready. */ if (lseek(wfd, where, SEEK_SET) == -1) { (void)fprintf(stderr, "Can't fseek back for \"%s\", %s\n", buff, strerror(errno)); continue; } /* If Message-ID was only thing on line, zap the text line. */ if (*files == '\0') { (void)memset((POINTER)Line.Data, ' ', (SIZE_T)Line.Used); if (xwrite(wfd, Line.Data, Line.Used) < 0) (void)fprintf(stderr, "Can't blank \"%s\", %s\n", buff, strerror(errno)); continue; } /* Prune out all the found filenames. */ if ((p = strtok(files, SEPS)) == NULL) { (void)fprintf(stderr, "Bad input, \"%s\"\n", files); continue; } do { Splice(p, &Line); } while ((p = strtok((char *)NULL, SEPS)) != NULL); /* Write out the new line. */ if (xwrite(wfd, Line.Data, Line.Used) < 0) (void)fprintf(stderr, "Can't write new text for \"%s\", %s\n", buff, strerror(errno)); } /* Close files; we're done. */ if (close(wfd) < 0) (void)fprintf(stderr, "Can't close \"%s\", %s\n", History, strerror(errno)); (void)fclose(rfp); exit(0); /* NOTREACHED */ } inn-1.7.2/expire/makehistory.c0100644000175100001440000005161106443103542014632 0ustar mdusers/* $Revision: 1.21 $ ** ** Rebuild the history database. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include #include "paths.h" #include "libinn.h" #include "inndcomm.h" #include "dbz.h" #include "qio.h" #include "macros.h" #include "mydir.h" typedef struct _BUFFER { char *Data; int Size; int Used; } BUFFER; STATIC char *ACTIVE = _PATH_ACTIVE; STATIC char SPOOL[] = _PATH_SPOOL; STATIC char *HISTORYDIR; STATIC char HISTORY[] = _PATH_HISTORY; STATIC char MESSAGEID[] = "Message-ID:"; STATIC char EXPIRES[] = "Expires:"; STATIC char DATE[] = "Date:"; STATIC BOOL INNDrunning; STATIC char *TextFile; STATIC char Reason[] = "makehistory is running"; STATIC TIMEINFO Now; extern long dbztagmask(); /* ** Change to a directory or exit out. */ STATIC void xchdir(where) char *where; { if (chdir(where) < 0) { (void)fprintf(stderr, "Can't change to \"%s\", %s\n", where, strerror(errno)); exit(1); } } /* ** Remove the DBZ files for the specified base text file. */ STATIC void RemoveDBZFiles(p) char *p; { static char NOCANDO[] = "Can't remove \"%s\", %s\n"; char buff[SMBUF]; (void)sprintf(buff, "%s.dir", p); if (unlink(buff) && errno != ENOENT) (void)fprintf(stderr, NOCANDO, buff, strerror(errno)); (void)sprintf(buff, "%s.pag", p); if (unlink(buff) && errno != ENOENT) (void)fprintf(stderr, NOCANDO, buff, strerror(errno)); } /* ** Rebuild the DBZ file from the text file. */ STATIC void Rebuild(size, IgnoreOld, Overwrite) long size; BOOL IgnoreOld; BOOL Overwrite; { register QIOSTATE *qp; register char *p; register char *save; register long count; long where; datum key; datum value; char temp[SMBUF]; xchdir(HISTORYDIR); /* Open the text file. */ qp = QIOopen(TextFile, QIO_BUFFER); if (qp == NULL) { (void)fprintf(stderr, "Can't open \"%s\", %s\n", TextFile, strerror(errno)); exit(1); } /* If using the standard history file, force DBZ to use history.n. */ if (EQ(TextFile, HISTORY) && !Overwrite) { (void)sprintf(temp, "%s.n", HISTORY); if (link(HISTORY, temp) < 0) { (void)fprintf(stderr, "Can't make temporary link to \"%s\", %s\n", temp, strerror(errno)); exit(1); } RemoveDBZFiles(temp); p = temp; } else { temp[0] = '\0'; RemoveDBZFiles(TextFile); p = TextFile; } /* Open the new database, using the old file if desired and possible. */ (void)dbzincore(1); if (IgnoreOld) { /* 70 == average history file line length */ if (dbzfresh(p, dbzsize(size), HIS_FIELDSEP, 'C', dbztagmask(size*70)) < 0) { (void)fprintf(stderr, "Can't do dbzfresh, %s\n", strerror(errno)); if (temp[0]) (void)unlink(temp); exit(1); } } else { if (dbzagain(p, HISTORY) < 0) { (void)fprintf(stderr, "Can't do dbzagain, %s\n", strerror(errno)); if (temp[0]) (void)unlink(temp); exit(1); } } /* Set up the value pointer. */ value.dptr = (char *)&where; value.dsize = sizeof where; /* Loop through all lines in the text file. */ count = 0; for (where = QIOtell(qp); (p = QIOread(qp)) != NULL; where = QIOtell(qp)) { count++; if ((save = strchr(p, HIS_FIELDSEP)) == NULL) { (void)fprintf(stderr, "Bad line #%ld \"%.30s...\"\n", count, p); if (temp[0]) (void)unlink(temp); exit(1); } *save = '\0'; key.dptr = p; key.dsize = save - p + 1; if (dbzstore(key, value) < 0) { (void)fprintf(stderr, "Can't store \"%s\", %s\n", p, strerror(errno)); if (temp[0]) (void)unlink(temp); exit(1); } } if (QIOerror(qp)) { (void)fprintf(stderr, "Can't read \"%s\" near line %ld, %s\n", TextFile, count, strerror(errno)); if (temp[0]) (void)unlink(temp); exit(1); } if (QIOtoolong(qp)) { (void)fprintf(stderr, "Line %ld is too long\n", count); if (temp[0]) (void)unlink(temp); exit(1); } /* Close files. */ QIOclose(qp); if (dbmclose() < 0) { (void)fprintf(stderr, "Can't close history, %s\n", strerror(errno)); if (temp[0]) (void)unlink(temp); exit(1); } if (temp[0]) (void)unlink(temp); } /* ** Remove a bad article. */ STATIC void Removeit(name) char *name; { char *p; /* Already in the spool directory, so skip right past the name; * the strchr can't return NULL. */ p = strchr(name, '/') + 1; if (unlink(p) < 0 && errno != ENOENT) (void)fprintf(stderr, "Can't unlink %s, %s\n", name, strerror(errno)); else (void)fprintf(stderr, "Removing %s\n", name); } /* ** Check and parse a Message-ID header line. Return private space. */ static char * GetMessageID(p) register char *p; { static BUFFER B; int length; static char NIL[] = ""; while (ISWHITE(*p)) p++; if (p[0] != '<' || p[strlen(p) - 1] != '>') return NIL; /* Copy into re-used memory space. */ length = strlen(p); if (B.Size == 0) { B.Size = length; B.Data = NEW(char, B.Size + 1); } else if (B.Size < length) { B.Size = length; RENEW(B.Data, char, B.Size + 1); } (void)memcpy((POINTER)B.Data, (POINTER)p, (SIZE_T)length + 1); for (p = B.Data; *p; p++) if (*p == HIS_FIELDSEP) *p = HIS_BADCHAR; return B.Data; } /* ** Check and parse an date header line. Return the new value or ** zero on error. */ static long GetaDate(p) register char *p; { time_t t; while (ISWHITE(*p)) p++; if ((t = parsedate(p, &Now)) == -1) return 0L; return (long)t; } /* ** Process a single article. */ STATIC void DoArticle(qp, Sbp, name, out, RemoveBad, Update) register QIOSTATE *qp; struct stat *Sbp; char *name; FILE *out; BOOL RemoveBad; BOOL Update; { static char IGNORE[] = "Ignoring duplicate %s header in %s\n"; static char BADHDR[] = "Bad %s header in %s\n"; register char *p; char *MessageID; time_t Arrived; time_t Expires; time_t Posted; int i; datum key; datum value; /* Read the file for Message-ID and Expires header. */ Arrived = Sbp->st_mtime; Expires = 0; MessageID = NULL; Posted = 0; while ((p = QIOread(qp)) != NULL && *p != '\0') switch (*p) { default: break; case 'M': case 'm': if (caseEQn(p, MESSAGEID, STRLEN(MESSAGEID))) { if (MessageID) (void)fprintf(stderr, IGNORE, MESSAGEID, name); else { MessageID = GetMessageID(&p[STRLEN(MESSAGEID)]); if (*MessageID == '\0') (void)fprintf(stderr, BADHDR, MESSAGEID, name); } } break; case 'E': case 'e': if (caseEQn(p, EXPIRES, STRLEN(EXPIRES))) { if (Expires > 0) (void)fprintf(stderr, IGNORE, EXPIRES, name); else { Expires = GetaDate(&p[STRLEN(EXPIRES)]); if (Expires == 0) (void)fprintf(stderr, BADHDR, EXPIRES, name); } } break; case 'D': case 'd': if (caseEQn(p, DATE, STRLEN(DATE))) { if (Posted > 0) (void)fprintf(stderr, IGNORE, DATE, name); else { Posted = GetaDate(&p[STRLEN(DATE)]); if (Posted == 0) (void)fprintf(stderr, BADHDR, DATE, name); } } break; } /* Check for errors, close the input. */ if (p == NULL) { if (QIOerror(qp)) { (void)fprintf(stderr, "Can't read %s, %s\n", name, strerror(errno)); return; } if (QIOtoolong(qp)) { (void)fprintf(stderr, "Line too long in %s\n", name); return; } } /* Make sure we have everything we need. */ if (MessageID == NULL || *MessageID == '\0') { if (MessageID == NULL) (void)fprintf(stderr, "No %s in %s\n", MESSAGEID, name); if (RemoveBad) Removeit(name); return; } if (Update) { /* Server already know about this one? */ key.dptr = MessageID; key.dsize = strlen(MessageID) + 1; value = dbzfetch(key); if (value.dptr != NULL) { return; } } /* Output the line. */ if (Posted == 0) Posted = Arrived; if (Expires > 0) i = fprintf(out, "%s%c%lu%c%lu%c%lu%c%s\n", MessageID, HIS_FIELDSEP, (unsigned long)Arrived, HIS_SUBFIELDSEP, (unsigned long)Expires, HIS_SUBFIELDSEP, (unsigned long)Posted, HIS_FIELDSEP, name); else i = fprintf(out, "%s%c%lu%c%s%c%lu%c%s\n", MessageID, HIS_FIELDSEP, (unsigned long)Arrived, HIS_SUBFIELDSEP, HIS_NOEXP, HIS_SUBFIELDSEP, (unsigned long)Posted, HIS_FIELDSEP, name); if (i == EOF || ferror(out)) { (void)fprintf(stderr, "Can't write history line, %s\n", strerror(errno)); exit(1); } } /* ** Process one newsgroup directory. */ STATIC void DoNewsgroup(group, out, RemoveBad, Update) char *group; FILE *out; BOOL RemoveBad; BOOL Update; { register DIR *dp; register DIRENTRY *ep; register QIOSTATE *qp; register char *p; register char *q; struct stat Sb; char buff[SPOOLNAMEBUFF]; #if defined(DO_HAVE_SYMLINK) char linkbuff[SPOOLNAMEBUFF]; int oerrno; #endif /* defined(DO_HAVE_SYMLINK) */ (void)strcpy(buff, group); for (p = group; *p; p++) if (*p == '.') *p = '/'; xchdir(SPOOL); if (chdir(group) < 0) return; if ((dp = opendir(".")) == NULL) { (void)fprintf(stderr, "Can't opendir %s, %s\n", group, strerror(errno)); return; } q = &buff[strlen(buff)]; *q++ = '/'; /* Read all entries in the directory. */ while ((ep = readdir(dp)) != NULL) { p = ep->d_name; if (!CTYPE(isdigit, *p) || strspn(p, "0123456789") != strlen(p)) continue; (void)strcpy(q, p); /* Is this a regular file? */ if (stat(p, &Sb) < 0) { (void)fprintf(stderr, "Can't stat %s, %s\n", buff, strerror(errno)); #if defined(DO_HAVE_SYMLINK) /* Symlink to nowhere? */ oerrno = errno; (void)memset((POINTER)linkbuff, '\0', sizeof linkbuff); if (lstat(p, &Sb) >= 0 && readlink(p, linkbuff, sizeof linkbuff - 1) >= 0) { linkbuff[sizeof linkbuff - 1] = '\0'; (void)fprintf(stderr, "Bad symlink %s -> %s, %s\n", buff, linkbuff, strerror(oerrno)); if (RemoveBad) Removeit(buff); } #endif /* defined(DO_HAVE_SYMLINK) */ continue; } if (!S_ISREG(Sb.st_mode)) { (void)fprintf(stderr, "%s is not a file\n", buff); continue; } /* ignore articles added after we started running because: ** - innd should be catching these already if it is running. ** - expire may have run and changed to a new history file. */ if (Sb.st_mtime > Now.time) { continue; } /* Open the article. */ if ((qp = QIOopen(p, QIO_BUFFER)) == NULL) { (void)fprintf(stderr, "Can't open %s, %s\n", buff, strerror(errno)); continue; } DoArticle(qp, &Sb, buff, out, RemoveBad, Update); QIOclose(qp); } (void)closedir(dp); } /* ** Tell innd to add a history line. */ STATIC BOOL AddThis(line, Verbose) register char *line; BOOL Verbose; { int i; char *arrive; char *exp; char *posted; char *paths; char *av[6]; if ((arrive = strchr(line, HIS_FIELDSEP)) == NULL || (exp = strchr(arrive + 1, HIS_SUBFIELDSEP)) == NULL || (posted = strchr(exp + 1, HIS_SUBFIELDSEP)) == NULL || (paths = strchr(exp + 1, HIS_FIELDSEP)) == NULL) { (void)fprintf(stderr, "Got bad history line \"%s\"\n", line); return FALSE; } av[0] = line; *arrive = '\0'; av[1] = arrive + 1; *exp = '\0'; av[2] = exp + 1; *posted = '\0'; av[3] = posted + 1; *paths = '\0'; av[4] = paths + 1; av[5] = NULL; if (EQ(av[2], HIS_NOEXP)) av[2] = "0"; i = ICCcommand(SC_ADDHIST, av, (char **)NULL); *arrive = HIS_FIELDSEP; *exp = HIS_SUBFIELDSEP; *posted = HIS_SUBFIELDSEP; *paths = HIS_FIELDSEP; if (i < 0) { (void)fprintf(stderr, "Can't add history line \"%s\", %s\n", line, strerror(errno)); return FALSE; } if (Verbose) (void)fprintf(stderr, "Added %s\n", line); return TRUE; } /* ** Close the server link, and exit. */ STATIC NORETURN ErrorExit(Updating, Stopped) BOOL Updating; BOOL Stopped; { if (Updating) { if (!INNDrunning && Stopped && ICCgo(Reason) < 0) (void)fprintf(stderr, "Can't restart server, %s\n", strerror(errno)); if (ICCclose() < 0) (void)fprintf(stderr, "Can't close link, %s\n", strerror(errno)); } exit(1); } /* ** Print a usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage: makehistory [ -A file ][ -a file ][ -b ][ -f file ][ -i ][ -n ] [ -o ] [ -T dir ][ -v ][ -f file ][ -r ][ -s size ][ -u ]\n"); exit(1); /* NOTREACHED */ } int main(ac, av) int ac; char *av[]; { register QIOSTATE *qp; register FILE *out; register char *line; register char *p; register char *q; register long count; BUFFER B; long size; int i; BOOL JustRebuild; BOOL DoRebuild; BOOL IgnoreOld; BOOL Overwrite; BOOL Update; BOOL RemoveBad; BOOL Verbose; char temp[SMBUF]; char *TempTextFile; char *tv[2]; STRING tmpdir; char *Tflag; char *mode; char *oldtemp; /* Set defaults. */ TextFile = HISTORY; DoRebuild = TRUE; JustRebuild = FALSE; IgnoreOld = FALSE; Update = FALSE; RemoveBad = FALSE; Overwrite = FALSE; Verbose = FALSE; Tflag = ""; mode = "w"; size = 0; oldtemp = NULL; if ((tmpdir = getenv("TMPDIR")) == NULL) tmpdir = _PATH_TMP; (void)umask(NEWSUMASK); /* Parse JCL. */ while ((i = getopt(ac, av, "A:a:bf:inors:T:uv")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'A': mode = "a"; oldtemp = optarg; break; case 'a': ACTIVE = optarg; break; case 'b': RemoveBad = TRUE; break; case 'f': TextFile = optarg; break; case 's': size = atol(optarg); /* FALLTHROUGH */ case 'i': IgnoreOld = TRUE; break; case 'n': DoRebuild = FALSE; break; case 'o': Overwrite = TRUE; IgnoreOld = TRUE; break; case 'r': JustRebuild = TRUE; break; case 'T': tmpdir = optarg; Tflag = NEW(char, 3 + strlen(optarg) + 1); (void)sprintf(Tflag, "-T %s", optarg); break; case 'u': Update = TRUE; break; case 'v': Verbose = TRUE; break; } ac -= optind; av += optind; if (ac || (Overwrite && Update) || (Verbose && !Update)) Usage(); if ((p = strrchr(TextFile, '/')) == NULL) { /* find the default history file directory */ HISTORYDIR = COPY(_PATH_HISTORY); p = strrchr(HISTORYDIR, '/'); if (p != NULL) { *p = '\0'; } } else { *p = '\0'; HISTORYDIR = COPY(TextFile); *p = '/'; } /* If we're not gonna scan the database, get out. */ if (JustRebuild) { Rebuild(size, IgnoreOld, Overwrite); exit(0); } /* Get the time. Only get it once, which is good enough. */ if (GetTimeInfo(&Now) < 0) { (void)fprintf(stderr, "Can't get the time, %s\n", strerror(errno)); exit(1); } /* Open history file. */ xchdir(HISTORYDIR); if (Update || !Overwrite) { (void)sprintf(temp, "%s/histXXXXXX", tmpdir); (void)mktemp(temp); TempTextFile = oldtemp ? COPY(oldtemp) : COPY(temp); } else TempTextFile = NULL; if (Update) { if (ICCopen() < 0) { (void)fprintf(stderr, "Can't talk to server, %s\n", strerror(errno)); exit(1); } tv[0] = Reason; tv[1] = NULL; if (DoRebuild && ICCcommand(SC_THROTTLE, tv, (char **)NULL) < 0) { (void)fprintf(stderr, "Can't throttle innd, %s\n", strerror(errno)); exit(1); } if (dbminit(TextFile) == -1) { (void)fprintf(stderr, "Can't open dbz file, %s\n", strerror(errno)); ErrorExit(TRUE, DoRebuild); } } if ((out = fopen(TempTextFile ? TempTextFile : TextFile, mode)) == NULL) { (void)fprintf(stderr, "Can't write to history file, %s\n", strerror(errno)); exit(1); } /* Start scanning the directories. */ if ((qp = QIOopen(ACTIVE, QIO_BUFFER)) == NULL) { (void)fprintf(stderr, "Can't open %s, %s\n", ACTIVE, strerror(errno)); exit(1); } for (count = 1; (line = QIOread(qp)) != NULL; count++) { if ((p = strchr(line, ' ')) == NULL) { (void)fprintf(stderr, "Bad line %ld, \"%s\"\n", count, line); continue; } *p = '\0'; DoNewsgroup(line, out, RemoveBad, Update); } /* Test error conditions; QIOtoolong shouldn't happen. */ if (QIOtoolong(qp)) { (void)fprintf(stderr, "Line %ld is too long\n", count); ErrorExit(Update, DoRebuild); } if (QIOerror(qp)) { (void)fprintf(stderr, "Can't read %s around line %ld, %s\n", ACTIVE, count, strerror(errno)); ErrorExit(Update, DoRebuild); } if (fflush(out) == EOF || ferror(out) || fclose(out) == EOF) { (void)fprintf(stderr, "Can't close history file, %s\n", strerror(errno)); ErrorExit(Update, DoRebuild); } /* Move. */ xchdir(HISTORYDIR); if (Update) { INNDrunning = TRUE; if (dbmclose() < 0) { (void)fprintf(stderr, "Can't close DBZ file, %s\n", strerror(errno)); ErrorExit(Update, DoRebuild); } if (DoRebuild && ICCgo(Reason) < 0) { (void)fprintf(stderr, "Can't restart innd, %s\n", strerror(errno)); ErrorExit(Update, DoRebuild); } } /* Make a temporary file, sort the text file into it. */ (void)sprintf(temp, "%s/histXXXXXX", tmpdir); (void)mktemp(temp); i = 50 + strlen(TempTextFile ? TempTextFile : TextFile) + strlen(temp); p = NEW(char, i); (void)sprintf(p, "exec sort %s -t'%c' +1n -o %s %s", Tflag, HIS_FIELDSEP, temp, TempTextFile ? TempTextFile : TextFile); i = system(p) >> 8; if (i != 0) { (void)fprintf(stderr, "Can't sort history file (exit %d), %s\n", i, strerror(errno)); ErrorExit(Update, DoRebuild); } DISPOSE(p); if (TempTextFile) { if (unlink(TempTextFile) && errno != ENOENT) (void)fprintf(stderr, "Can't remove \"%s\", %s\n", TempTextFile, strerror(errno)); DISPOSE(TempTextFile); TempTextFile = NULL; } /* Open the sorted file, get ready to write the final text file. */ if ((qp = QIOopen(temp, QIO_BUFFER)) == NULL) { (void)fprintf(stderr, "Can't open work file \"%s\", %s\n", temp, strerror(errno)); ErrorExit(Update, DoRebuild); } if (!Update && (out = fopen(TextFile, "w")) == NULL) { (void)fprintf(stderr, "Can't start writing %s, %s\n", TextFile, strerror(errno)); (void)fprintf(stderr, "Work file %s untouched.\n", temp); ErrorExit(Update, DoRebuild); } /* Get space to keep the joined history lines. */ B.Size = 100; B.Used = 0; B.Data = NEW(char, B.Size); p = COPY(""); /* Read the sorted work file. */ for (count = 0; (line = QIOread(qp)) != NULL; ) { count++; if ((q = strchr(line, HIS_FIELDSEP)) == NULL) { (void)fprintf(stderr, "Work file line %ld had bad format\n", count); ErrorExit(Update, DoRebuild); } *q = '\0'; if (EQ(p, line)) { /* Same Message-ID as last time -- get filename */ if ((q = strchr(q + 1, HIS_FIELDSEP)) == NULL) { (void)fprintf(stderr, "Work file line %ld missing filename\n", count); ErrorExit(Update, DoRebuild); } i = strlen(q); if (B.Size < B.Used + i + 3) { B.Size = B.Used + i + 3; RENEW(B.Data, char, B.Size); } *q = ' '; (void)strcpy(&B.Data[B.Used], q); B.Used += i; } else { /* Different Message-ID; end old line, start new one. */ if (*p) { if (!Update) (void)fprintf(out, "%s\n", B.Data); else if (!AddThis(B.Data, Verbose)) ErrorExit(Update, DoRebuild); } DISPOSE(p); p = COPY(line); *q = HIS_FIELDSEP; i = strlen(line); if (B.Size <= i) { B.Size = i + 2; RENEW(B.Data, char, B.Size); } (void)strcpy(B.Data, line); B.Used = i; } if (!Update && ferror(out)) { (void)fprintf(stderr, "Can't write output from line %ld, %s\n", count, strerror(errno)); ErrorExit(Update, DoRebuild); } } /* Check for errors and close. */ if (QIOtoolong(qp)) { (void)fprintf(stderr, "Line %ld is too long\n", count); ErrorExit(Update, DoRebuild); } if (QIOerror(qp)) { (void)fprintf(stderr, "Can't read work file, %s\n", strerror(errno)); ErrorExit(Update, DoRebuild); } QIOclose(qp); if (unlink(temp) && errno != ENOENT) (void)fprintf(stderr, "Can't remove \"%s\", %s\n", temp, strerror(errno)); if (*p) { /* Add tail end of last line. */ if (!Update) (void)fprintf(out, "%s\n", B.Data); else if (!AddThis(B.Data, Verbose)) ErrorExit(Update, DoRebuild); } /* Close the output file. */ if (!Update) { if (fflush(out) == EOF || fclose(out) == EOF) { (void)fprintf(stderr, "Can't close history file, %s\n", strerror(errno)); ErrorExit(Update, DoRebuild); } if (DoRebuild) Rebuild(size ? size : count, TRUE, Overwrite); } else if (ICCclose() < 0) (void)fprintf(stderr, "Can't close link, %s\n", strerror(errno)); exit(0); /* NOTREACHED */ } inn-1.7.2/expire/fastrm.c0100644000175100001440000003523206443103542013570 0ustar mdusers/* * delete a list of filenames from stdin * * exit(0) if all is OK (files that can't be unlinked because they * didn't exist is "OK") * * exit(1) in other cases - problems with stdin, no permission, ... * written by */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #include "mydir.h" #include "macros.h" #include "libinn.h" #define MAX_LINE_SIZE 1024 #define SHORT_NAME 16 #define MAX_DIR_LEN 2048 /* typedef unsigned char chr; */ typedef char chr; typedef struct _dnode { struct _dnode *next; int count; chr *dir; chr *longname; chr shortname[SHORT_NAME]; } dnode; #define NODENAME(d) ((d)->longname ? (d)->longname : (d)->shortname) STATIC char DotDot[] = "../../../../"; STATIC chr base_dir[MAX_DIR_LEN]; STATIC chr cur_dir[MAX_DIR_LEN]; STATIC chr prefix_dir[MAX_DIR_LEN]; STATIC int prefix_len; STATIC char *MyName; STATIC int fatals; /* error counter */ STATIC BOOL AmRoot; STATIC BOOL Debugging; STATIC int dotdot; STATIC int sortdirs; STATIC int cdval = 3; STATIC void err_exit(s) char *s; { (void)fprintf(stderr, "%s: %s\n", MyName, s); exit(1); } STATIC int myexit() { err_exit("Could not allocate memory"); /* NOTREACHED */ } /* ** Get the next line from stdin into 'l' which has 'len' bytes available. */ STATIC BOOL get_line(l, len) register chr *l; register int len; { static int count; register chr *p; for ( ; ; ) { /* Get the line. */ if (fgets(l, len, stdin) == NULL) return FALSE; count++; /* See if we got the \n terminator. */ p = (chr *)strchr(l, '\n'); if (p != NULL) { /* Yes, ok, that's a good line, trash the \n & return. */ *p = '\0'; return TRUE; } /* No, this line is longer than our buffer. */ (void)fprintf(stderr, "%s: Line %d (%.40s...) too long\n", MyName, count, l); fatals++; /* Trash the rest of the long line. */ while (fgets(l, len, stdin) != NULL && strchr(l, '\n') == NULL) continue; /* Go back and get the nest (just ignore the long one). */ } } /* ** Remember a file name; this is pretty trivial (only fancy bit is not ** malloc'ing mem for short names). */ STATIC dnode * build_node(prev, dir, name) dnode *prev; chr *dir; chr *name; { register dnode *n; register int i; n = NEW(dnode, 1); if (prev) prev->next = n; n->next = NULL; n->dir = dir; i = strlen(name); if (i >= SHORT_NAME) { n->longname = COPY(name); } else { n->longname = NULL; (void)strcpy(n->shortname, name); } return n; } /* ** Read lines from stdin (including the first that may have been there ** from our last time in) until we reach EOF, or until we get a line that ** names a file not in the same directory as the previous lot remember ** the file names in the directory we're examining, and count them */ STATIC dnode * build_dir(ip) int *ip; { static chr line[MAX_LINE_SIZE]; register dnode *start; register dnode *n; register int dlen; register chr *p; register chr *dir; *ip = 0; if (line[0] == '\0' && !get_line(line, (int)sizeof line)) return NULL; /* Build node. */ p = (chr *)strrchr(line, '/'); if (p != NULL) { *p++ = '\0'; dlen = strlen(line); dir = COPY(line); } else { dir = NULL; dlen = -1; p = line; } n = start = build_node((dnode *)NULL, dir, p); *ip = 1; while (get_line(line, (int)sizeof line)) { if ((dlen < 0 && strchr(line, '/')) || (dlen >= 0 && (line[dlen] != '/' || strchr(line + dlen + 1, '/') != NULL || strncmp(dir, line, dlen)))) return start; n = build_node(n, dir, line + dlen + 1); (*ip)++; } line[0] = '\0'; return start; } /* ** Sorting predicate for qsort to put nodes in alphabetical order. */ STATIC int comp(a, b) CPOINTER a; CPOINTER b; { dnode *l1, *l2; l1 = *CAST(dnode**, a); l2 = *CAST(dnode**, b); return strcmp(NODENAME(l1), NODENAME(l2)); } /* ** Find a node in the list. */ STATIC dnode * inlist(list, num, name) register dnode **list; int num; char *name; { register dnode **top; register dnode **cur; register int i; for (top = list + num - 1; top >= list; ) { cur = list + (top - list) / 2; i = strcmp(name, NODENAME(*cur)); if (i == 0) return *cur; if (i < 0) top = cur - 1; else list = cur + 1; } return NULL; } /* ** Free a list of nodes. */ STATIC void freelist(list) register dnode *list; { register dnode *l; while ((l = list) != NULL) { list = l->next; if (l->longname) DISPOSE(l->longname); DISPOSE(l); } } STATIC void unlink_node(n) dnode *n; { register chr *p; struct stat sb; int oerrno; p = NODENAME(n); if (prefix_len != 0) { (void)strcpy(prefix_dir + prefix_len, p); p = prefix_dir; } if (AmRoot) { if (stat(p, &sb) < 0) { if (errno != ENOENT) { oerrno = errno; (void)fprintf(stderr, "%s: stat %s ", MyName, p); if (*p != '/') (void)fprintf(stderr, "in %s ", cur_dir); (void)fprintf(stderr, "%s\n", strerror(oerrno)); fatals++; } return; } if (S_ISDIR(sb.st_mode)) { (void)fprintf(stderr, "%s: Directory ", MyName); if (*p != '/') (void)fprintf(stderr, "in %s ", cur_dir); (void)fprintf(stderr, "\"%s\"\n", p); fatals++; return; } } if (Debugging) { if (*p == '/') (void)printf("%s\n", p); else (void)printf("%s / %s\n", cur_dir, p); return; } if (unlink(p) < 0) { if (errno != ENOENT) { oerrno = errno; (void)fprintf(stderr, "%s: unlink %s", MyName, p); if (*p != '/') (void)fprintf(stderr, "in %s ", cur_dir); (void)fprintf(stderr, "%s\n", strerror(oerrno)); fatals++; } } } STATIC void copynsegs(from, to, n) register chr *from; register chr *to; register int n; { register chr c; while ((*to++ = c = *from++) != '\0') if (c == '/' && --n <= 0) break; if (c == '/') *--to = '\0'; } STATIC int slashcount(p) register chr *p; { register int i; for (i = 0; *p; ) if (*p++ == '/') i++; return i; } /* ** Set our environment (process working cirectory, and global vars) to ** reflect a change to directory 'd' (relative to base_dir if 'd' is not ** an absolute path). We're likely to want to do different things ** depending on the amount of work to do in 'd' - that's given by 'num'. ** Return FALSE if the directory can be determined not to exist. */ STATIC BOOL setup_dir(d, num) register chr *d; int num; { register chr *p; register chr *q; register chr *abs; register int bsegs; register int oerrno; chr string[MAX_DIR_LEN]; bsegs = slashcount(base_dir); if (d == NULL) abs = base_dir; else if (*d == '/') abs = d; else if (*d == '\0') abs = (chr *)"/"; else { while (d[0] == '.' && d[1] == '/') for (d += 2; *d == '/'; ) d++; while (bsegs > 0 && d[0] == '.' && d[1] == '.' && d[2] == '/') for (bsegs--, d += 3; *d == '/'; ) d++; if (bsegs <= 0) err_exit("Can't handle that many ..'s in path"); abs = string; copynsegs(base_dir, abs, bsegs + 1); (void)strcat(abs, "/"); (void)strcat(abs, d); } /* Now "abs" is the full path name of the directory we want to * be at, and "cur_dir" is where we presently are. */ for (p = abs, q = cur_dir; *p == *q; ) { /* If we've reached the end, this is easy, we want to be in * the same place as we were (which is probably really some * kind of error, it shouldn't happen). */ if (*p == '\0') return TRUE; p++; q++; } prefix_len = 0; if (*p == 0 && *q == '/') { /* Want to go back up the tree, it might be faster to chdir(abs) * or chdir(../../..). But, since the this case happens rarely if * the user cares about speed (sorted input will usually mean that * we don't simply want to go back up the tree) it's not worth the * bother. */ if (cdval == 0 || num < cdval) { /* Except if we have just a couple of files in this directory * to deal with, in which case we'll just use their absolute * path names. */ (void)strcpy(prefix_dir, abs); prefix_len = p - abs; return TRUE; } if (chdir(abs) < 0) { (void)fprintf(stderr, "%s: chdir to %s, %s\n", MyName, abs, strerror(errno)); (void)fflush(stderr); /* If we fail here, something is badly broken, since we're * supposedly further down the tree. */ err_exit("Chdir failed"); } *q = '\0'; return TRUE; } if (*q == '\0' && *p == '/') { /* Want to change into a sub-dir of where we were; easy. */ p++; if (cdval == 0 || num < cdval) { (void)strcpy(prefix_dir, p); prefix_len = strlen(p); return TRUE; } if (chdir(p) < 0) { oerrno = errno; (void)fprintf(stderr, "%s: chdir from %s to %s, %s\n", MyName, cur_dir, p, strerror(oerrno)); if (oerrno == ENOENT) return FALSE; err_exit("Chdir failed"); } (void)strcpy(cur_dir, abs); return TRUE; } /* If its possible, (promised we have a pure tree), see if its * worth going up the tree with ".." then down again, or if * its better to simply start again at the start. */ if (dotdot) { bsegs = slashcount(q); /* 1 default "dotdot" here can be 0, 1, 2, or 3, 1 seems * frationally faster than 2, bigger values would require * extending the "../../../" string, but are very unlikely * to be helpful; '0' is the same as not using -u. */ if (bsegs <= dotdot) { /* Looks like its probably worth using "..". */ while (p > abs && *--p != '/') continue; p++; (void)strcpy(prefix_dir, DotDot + 9 - bsegs * 3); (void)strcpy(prefix_dir + (bsegs + 1) * 3, p); if (cdval == 0 || num < cdval) { prefix_len = strlen(prefix_dir); return TRUE; } if (chdir(prefix_dir) < 0) { oerrno = errno; (void)fprintf(stderr, "%s: chdir from %s to %s, %s\n", MyName, cur_dir, prefix_dir, strerror(oerrno)); if (oerrno == ENOENT) return FALSE; err_exit("Chdir failed"); } /* Now patch up curdir to reflect where we are. */ while (q > cur_dir && *--q != '/') continue; (void)strcpy(q + 1, p); return TRUE; } } /* Simply use the absolute path. */ if (cdval == 0 || num < cdval) { (void)strcpy(prefix_dir, abs); prefix_len = strlen(abs); return TRUE; } if (chdir(abs) < 0) { oerrno = errno; (void)fprintf(stderr, "%s: chdir to %s, %s\n", MyName, abs, strerror(oerrno)); if (oerrno == ENOENT) return FALSE; err_exit("Chdir failed"); } (void)strcpy(cur_dir, abs); return TRUE; } STATIC void unlink_dir(list, num) register dnode *list; register int num; { static dnode **dptrs; static int ndp; register dnode *l; register dnode **pl; register DIR *dfd; register DIRENTRY *d; register BOOL sorted; struct stat sb; if (!setup_dir(list->dir, num)) { /* The directory doesn't exist, no point attempting to * delete anything, just forget it all. */ if (list->dir) DISPOSE(list->dir); freelist(list); return; } if (list->dir) DISPOSE(list->dir); if (sortdirs == 0 || num < sortdirs) { if (prefix_len != 0) { prefix_dir[prefix_len++] = '/'; prefix_dir[prefix_len] = '\0'; } /* Easier to just unlink the files than worry about the * order we unlink them in. */ while ((l = list) != NULL) { unlink_node(l); list = l->next; if (l->longname) DISPOSE(l->longname); DISPOSE(l); } return; } if (ndp == 0) { ndp = num; dptrs = NEW(dnode*, ndp); } else if (num > ndp) { ndp = num + 16; RENEW(dptrs, dnode*, ndp); } if ((pl = dptrs) == NULL) err_exit("Out of mem in unlink_dir"); for (sorted = TRUE, *pl = list, l = list->next; l; l = l->next) { if (sorted && strcmp(NODENAME(*pl), NODENAME(l)) > 0) sorted = FALSE; *++pl = l; } if (!sorted) qsort((char *)dptrs, num, sizeof (dnode *), comp); if (prefix_len == 0) { if ((dfd = opendir(".")) == NULL) { (void)fprintf(stderr, "Can't open \".\" in directory \"%s\"\n", cur_dir); fatals++; freelist(list); return; } } else { if ((dfd = opendir(prefix_dir)) == NULL) { if (prefix_dir[0] == '/') (void)fprintf(stderr, "Can't open directory \"%s\"\n", prefix_dir); else (void)fprintf(stderr, "Can't open directory \"%s\" in \"%s\"\n", prefix_dir, cur_dir); if (stat(prefix_dir, &sb) >= 0 || errno != ENOENT) fatals++; freelist(list); return; } } if (prefix_len != 0) { prefix_dir[prefix_len++] = '/'; prefix_dir[prefix_len] = '\0'; } while ((d = readdir(dfd)) != NULL) if ((l = inlist(dptrs, num, d->d_name)) != NULL) unlink_node(l); (void)closedir(dfd); freelist(list); } STATIC BOOL bad_path(p) register char *p; { while (*p) { if (p[0] == '.' && ((p[1] == '/' || p[1] == '.') && p[2] == '/')) return TRUE; while (*p && *p != '/') p++; if (p[0] == '/' && p[1] == '/') return TRUE; if (*p == '/') p++; } return FALSE; } int main(ac, av) int ac; char *av[]; { register dnode *list; register char *p; int count; BOOL empty_error; MyName = av[0]; if ((p = strrchr(MyName, '/')) != NULL) MyName = p + 1; ONALLOCFAIL(myexit); AmRoot = geteuid() == 0; empty_error = FALSE; while (ac > 2) { if (*(p = av[1]) != '-') break; while (*++p) { switch (*p) { default: err_exit("Usage error, unknown flag"); exit(1); case 'd': Debugging = TRUE; continue; case 'u': dotdot = 1; if (!isdigit(p[1])) continue; dotdot = atoi(p + 1); if (dotdot >= strlen(DotDot)/(SIZE_T)3) dotdot = strlen(DotDot)/(SIZE_T)3 - 1; break; case 's': sortdirs = 5; if (!isdigit(p[1])) continue; sortdirs = atoi(p + 1); break; case 'c': cdval = 1; if (!isdigit(p[1])) continue; cdval = atoi(p + 1); break; case 'e': empty_error = TRUE; continue; case 'a': case 'r': continue; } break; } ac--; av++; } if (ac != 2) { err_exit("Usage error, wrong number of arguments"); exit(1); } p = av[1]; if (*p != '/' || bad_path(p) || strlen(p) >= (SIZE_T)MAX_DIR_LEN) { (void)fprintf(stderr, "%s: Bad base path: %s\n", MyName, p); exit(1); } (void)strcpy(base_dir, p); (void)strcpy(cur_dir, p); if (chdir(cur_dir) < 0) { (void)fprintf(stderr, "%s: chdir to base path %s\n", MyName, strerror(errno)); exit(1); } while ((list = build_dir(&count)) != NULL) { empty_error = FALSE; unlink_dir(list, count); } if (empty_error) err_exit("No files to remove"); if (fatals) exit(1); exit(0); /* NOTREACHED */ } inn-1.7.2/expire/expire.c0100644000175100001440000007134606443103542013576 0ustar mdusers/* $Revision: 1.28 $ ** ** Expire news articles. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include #include "paths.h" #include "libinn.h" #include "inndcomm.h" #include "dbz.h" #include "qio.h" #include "macros.h" /* ** Stuff that more or less duplicates stuff in innd. */ #define NGH_HASH(Name, p, j) \ for (p = Name, j = 0; *p; ) j = (j << 5) + j + *p++ #define NGH_SIZE 2048 #define NGH_BUCKET(j) &NGHtable[j & (NGH_SIZE - 1)] typedef struct _BUFFER { int Size; int Used; int Left; char *Data; } BUFFER; typedef struct _NEWSGROUP { char *Name; char *Rest; unsigned long Last; /* These fields are new. */ time_t Keep; time_t Default; time_t Purge; } NEWSGROUP; typedef struct _NGHASH { int Size; int Used; NEWSGROUP **Groups; } NGHASH; /* ** Expire-specific stuff. */ #define MAGIC_TIME 49710. typedef struct _BADGROUP { struct _BADGROUP *Next; char *Name; BOOL HasDirectory; } BADGROUP; STATIC BADGROUP *EXPbadgroups; STATIC BOOL EXPlinks; STATIC BOOL EXPquiet; STATIC BOOL EXPsizing; STATIC BOOL EXPtracing; STATIC BOOL EXPusepost; STATIC BOOL EXPearliest; STATIC char ACTIVE[] = _PATH_ACTIVE; STATIC char SPOOL[] = _PATH_SPOOL; STATIC int nGroups; STATIC FILE *EXPunlinkfile; STATIC long EXPsaved; STATIC NEWSGROUP *Groups; STATIC NEWSGROUP EXPdefault; STATIC NGHASH NGHtable[NGH_SIZE]; STATIC STRING EXPreason; STATIC time_t EXPremember; STATIC time_t Now; STATIC time_t RealNow; /* Statistics; for -v flag. */ STATIC char *EXPgraph; STATIC int EXPverbose; STATIC long EXPprocessed; STATIC long EXPunlinked; STATIC long EXPhistdrop; STATIC long EXPhistremember; STATIC long EXPallgone; STATIC long EXPstillhere; STATIC int EXPsplit(); #if ! defined (atof) /* NEXT defines aotf as a macro */ extern double atof(); #endif /* ** Hash a newsgroup and see if we get it. */ STATIC NEWSGROUP * NGfind(Name) char *Name; { register char *p; register int i; unsigned int j; register NEWSGROUP **ngp; char c; NGHASH *htp; /* SUPPRESS 6 *//* Over/underflow from plus expression */ NGH_HASH(Name, p, j); htp = NGH_BUCKET(j); for (c = *Name, ngp = htp->Groups, i = htp->Used; --i >= 0; ngp++) if (c == ngp[0]->Name[0] && EQ(Name, ngp[0]->Name)) return ngp[0]; return NULL; } /* ** Sorting predicate to put newsgroups in rough order of their activity. */ STATIC int NGcompare(p1, p2) CPOINTER p1; CPOINTER p2; { NEWSGROUP **ng1; NEWSGROUP **ng2; ng1 = CAST(NEWSGROUP**, p1); ng2 = CAST(NEWSGROUP**, p2); return ng1[0]->Last - ng2[0]->Last; } /* ** Build the newsgroup structures from the active file. */ STATIC void BuildGroups(active) char *active; { register NGHASH *htp; register NEWSGROUP *ngp; register char *p; register char *q; register int i; register unsigned j; register int lines; int NGHbuckets; char *fields[5]; /* Count the number of groups. */ for (p = active, i = 0; (p = strchr(p, '\n')) != NULL; p++, i++) continue; nGroups = i; Groups = NEW(NEWSGROUP, i); /* Set up the default hash buckets. */ NGHbuckets = i / NGH_SIZE; if (NGHbuckets == 0) NGHbuckets = 1; for (i = NGH_SIZE, htp = NGHtable; --i >= 0; htp++) { htp->Size = NGHbuckets; htp->Groups = NEW(NEWSGROUP*, htp->Size); htp->Used = 0; } /* Fill in the array. */ lines = 0; for (p = active, ngp = Groups, i = nGroups; --i >= 0; ngp++, p = q + 1) { lines++; if ((q = strchr(p, '\n')) == NULL) { (void)fprintf(stderr, "%s: line %d missing newline\n", ACTIVE, lines); exit(1); } *q = '\0'; if (EXPsplit(p, ' ', fields, SIZEOF(fields)) != 4) { (void)fprintf(stderr, "%s: line %d wrong number of fields\n", ACTIVE, lines); exit(1); } ngp->Name = fields[0]; ngp->Last = atol(fields[1]); ngp->Rest = fields[3]; /* Find the right bucket for the group, make sure there is room. */ /* SUPPRESS 6 *//* Over/underflow from plus expression */ NGH_HASH(ngp->Name, p, j); htp = NGH_BUCKET(j); if (htp->Used >= htp->Size) { htp->Size += NGHbuckets; RENEW(htp->Groups, NEWSGROUP*, htp->Size); } htp->Groups[htp->Used++] = ngp; } /* Sort each hash bucket. */ for (i = NGH_SIZE, htp = NGHtable; --i >= 0; htp++) if (htp->Used > 1) qsort((POINTER)htp->Groups, (SIZE_T)htp->Used, sizeof htp->Groups[0], NGcompare); } /* ** Open a file or give up. */ STATIC FILE * EXPfopen(Remove, Name, Mode) BOOL Remove; STRING Name; char *Mode; { FILE *F; if (Remove && unlink(Name) < 0 && errno != ENOENT) (void)fprintf(stderr, "Warning, can't remove %s, %s\n", Name, strerror(errno)); if ((F = fopen(Name, Mode)) == NULL) { (void)fprintf(stderr, "Can't open %s in %s mode, %s\n", Name, Mode, strerror(errno)); exit(1); } return F; } /* ** Split a line at a specified field separator into a vector and return ** the number of fields found, or -1 on error. */ STATIC int EXPsplit(p, sep, argv, count) register char *p; register char sep; register char **argv; register int count; { register int i; for (i = 1, *argv++ = p; *p; ) if (*p++ == sep) { if (++i == count) /* Overflow. */ return -1; p[-1] = '\0'; for (*argv++ = p; *p == sep; p++) continue; } return i; } /* ** Parse a number field converting it into a "when did this start?". ** This makes the "keep it" tests fast, but inverts the logic of ** just about everything you expect. Print a message and return FALSE ** on error. */ STATIC BOOL EXPgetnum(line, word, v, name) int line; char *word; time_t *v; char *name; { register char *p; register BOOL SawDot; double d; if (caseEQ(word, "never")) { *v = (time_t)0; return TRUE; } /* Check the number. We don't have strtod yet. */ for (p = word; ISWHITE(*p); p++) continue; if (*p == '+' || *p == '-') p++; for (SawDot = FALSE; *p; p++) if (*p == '.') { if (SawDot) break; SawDot = TRUE; } else if (!CTYPE(isdigit, *p)) break; if (*p) { (void)fprintf(stderr, "Line %d, bad `%c' character in %s field\n", line, *p, name); return FALSE; } d = atof(word); if (d > MAGIC_TIME) *v = (time_t)0; else *v = Now - (time_t)(d * 86400.); return TRUE; } /* ** Set the expiration fields for all groups that match this pattern. */ STATIC void EXPmatch(p, v, mod) register char *p; register NEWSGROUP *v; register char mod; { register NEWSGROUP *ngp; register int i; register BOOL negate; negate = *p == '!'; if (negate) p++; for (ngp = Groups, i = nGroups; --i >= 0; ngp++) if (negate ? !wildmat(ngp->Name, p) : wildmat(ngp->Name, p)) if (mod == 'a' || (mod == 'm' && ngp->Rest[0] == NF_FLAG_MODERATED) || (mod == 'u' && ngp->Rest[0] != NF_FLAG_MODERATED)) { ngp->Keep = v->Keep; ngp->Default = v->Default; ngp->Purge = v->Purge; if (EXPverbose > 4) { (void)printf("%s", ngp->Name); (void)printf(" %13.13s", ctime(&v->Keep) + 3); (void)printf(" %13.13s", ctime(&v->Default) + 3); (void)printf(" %13.13s", ctime(&v->Purge) + 3); (void)printf(" (%s)\n", p); } } } /* ** Parse the expiration control file. Return TRUE if okay. */ STATIC BOOL EXPreadfile(F) register FILE *F; { register char *p; register int i; register int j; register int k; register char mod; NEWSGROUP v; BOOL SawDefault; char buff[BUFSIZ]; char *fields[6]; char **patterns; /* Scan all lines. */ EXPremember = -1; SawDefault = FALSE; patterns = NEW(char*, nGroups); for (i = 1; fgets(buff, sizeof buff, F) != NULL; i++) { if ((p = strchr(buff, '\n')) == NULL) { (void)fprintf(stderr, "Line %d too long\n", i); return FALSE; } *p = '\0'; p = strchr(buff, '#'); if (p) *p = '\0'; else p = buff + strlen(buff); while (--p >= buff) { if (isspace(*p)) *p = '\0'; else break; } if (buff[0] == '\0') continue; if ((j = EXPsplit(buff, ':', fields, SIZEOF(fields))) == -1) { (void)fprintf(stderr, "Line %d too many fields\n", i); return FALSE; } /* Expired-article remember line? */ if (EQ(fields[0], "/remember/")) { if (j != 2) { (void)fprintf(stderr, "Line %d bad format\n", i); return FALSE; } if (EXPremember != -1) { (void)fprintf(stderr, "Line %d duplicate /remember/\n", i); return FALSE; } if (!EXPgetnum(i, fields[1], &EXPremember, "remember")) return FALSE; continue; } /* Regular expiration line -- right number of fields? */ if (j != 5) { (void)fprintf(stderr, "Line %d bad format\n", i); return FALSE; } /* Parse the fields. */ if (strchr(fields[1], 'M') != NULL) mod = 'm'; else if (strchr(fields[1], 'U') != NULL) mod = 'u'; else if (strchr(fields[1], 'A') != NULL) mod = 'a'; else { (void)fprintf(stderr, "Line %d bad modflag\n", i); return FALSE; } if (!EXPgetnum(i, fields[2], &v.Keep, "keep") || !EXPgetnum(i, fields[3], &v.Default, "default") || !EXPgetnum(i, fields[4], &v.Purge, "purge")) return FALSE; /* These were turned into offsets, so the test is the opposie * of what you think it should be. If Purge isn't forever, * make sure it's greater then the other two fields. */ if (v.Purge) { /* Some value not forever; make sure other values are in range. */ if (v.Keep && v.Keep < v.Purge) { (void)fprintf(stderr, "Line %d keep>purge\n", i); return FALSE; } if (v.Default && v.Default < v.Purge) { (void)fprintf(stderr, "Line %d default>purge\n", i); return FALSE; } } /* Is this the default line? */ if (fields[0][0] == '*' && fields[0][1] == '\0' && mod == 'a') { if (SawDefault) { (void)fprintf(stderr, "Line %d duplicate default\n", i); return FALSE; } EXPdefault.Keep = v.Keep; EXPdefault.Default = v.Default; EXPdefault.Purge = v.Purge; SawDefault = TRUE; } /* Assign to all groups that match the pattern and flags. */ if ((j = EXPsplit(fields[0], ',', patterns, nGroups)) == -1) { (void)fprintf(stderr, "Line %d too many patterns\n", i); return FALSE; } for (k = 0; k < j; k++) EXPmatch(patterns[k], &v, mod); } DISPOSE(patterns); return TRUE; } /* ** Handle a newsgroup that isn't in the active file. */ STATIC NEWSGROUP * EXPnotfound(Entry) char *Entry; { static NEWSGROUP Removeit; register BADGROUP *bg; register char *p; struct stat Sb; char buff[SPOOLNAMEBUFF]; /* See if we already know about this group. */ for (bg = EXPbadgroups; bg; bg = bg->Next) if (EQ(Entry, bg->Name)) break; if (bg == NULL) { bg = NEW(BADGROUP, 1); bg->Name = COPY(Entry); (void)strcpy(buff, bg->Name); for (p = buff; *p; p++) if (*p == '.') *p = '/'; bg->HasDirectory = stat(buff, &Sb) >= 0 && S_ISDIR(Sb.st_mode); bg->Next = EXPbadgroups; EXPbadgroups = bg; if (!EXPquiet) { (void)fflush(stdout); (void)fprintf(stderr, "Group not matched (removed?) %s -- %s\n", Entry, bg->HasDirectory ? "Using default expiration" : "Purging all articles"); } } /* Directory still there; use default expiration. */ if (bg->HasDirectory) return &EXPdefault; /* No directory -- remove it all now. */ if (Removeit.Keep == 0) { Removeit.Keep = Now; Removeit.Default = Now; Removeit.Purge = Now; } return &Removeit; } /* ** Should we keep the specified article? */ STATIC BOOL EXPkeepit(Entry, when, Expires) char *Entry; time_t when; time_t Expires; { register char *p; register NEWSGROUP *ngp; if ((p = strchr(Entry, '/')) == NULL) { (void)fflush(stdout); (void)fprintf(stderr, "Bad entry, \"%s\"\n", Entry); return TRUE; } *p = '\0'; if ((ngp = NGfind(Entry)) == NULL) ngp = EXPnotfound(Entry); *p = '/'; /* Bad posting date? */ if (when > RealNow + 86400) { /* Yes -- force the article to go right now. */ when = Expires ? ngp->Purge : ngp->Default; } if (EXPverbose > 2) { if (EXPverbose > 3) (void)printf("%s age = %0.2f\n", Entry, (Now - when) / 86400.); if (Expires == 0) { if (when <= ngp->Default) (void)printf("%s too old (no exp)\n", Entry); } else { if (when <= ngp->Purge) (void)printf("%s later than purge\n", Entry); if (when >= ngp->Keep) (void)printf("%s earlier than min\n", Entry); if (Now >= Expires) (void)printf("%s later than header\n", Entry); } } /* If no expiration, make sure it wasn't posted before the default. */ if (Expires == 0) return when > ngp->Default; /* Make sure it's not posted before the purge cut-off and * that it's not due to expire. */ return when > ngp->Purge && (Expires > Now || when > ngp->Keep); } /* ** An article can be removed. Either print a note, or actually remove it. ** Also fill in the article size. */ STATIC void EXPremove(p, size) char *p; long *size; { register char *q; struct stat Sb; /* Turn into a filename and get the size if we need it. */ for (q = p; *q; q++) if (*q == '.') *q = '/'; if (EXPsizing && *size < 0 && stat(p, &Sb) >= 0) *size = (int)(((long)Sb.st_size >> 10) + (((long)Sb.st_size >> 9) & 1)); if (EXPverbose > 1) (void)printf("\tunlink %s\n", p); EXPunlinked++; if (EXPtracing) { (void)printf("%s\n", p); return; } if (EXPunlinkfile) { (void)fprintf(EXPunlinkfile, "%s\n", p); if (!ferror(EXPunlinkfile)) return; (void)fprintf(stderr, "Can't write to -z file, %s\n", strerror(errno)); (void)fprintf(stderr, "(Will ignore it for rest of run.)\n"); (void)fclose(EXPunlinkfile); EXPunlinkfile = NULL; } if (unlink(p) < 0 && errno != ENOENT) (void)fprintf(stderr, "Can't unlink %s, %s\n", p, strerror(errno)); } /* ** Do the work of expiring one line. */ STATIC BOOL EXPdoline(out, line, length, arts) FILE *out; char *line; int length; char **arts; { static char IGNORING[] = "Ignoring bad line, \"%.20s...\"\n"; static long Offset; static BUFFER New; register char *p; register char *q; register char *first; register int i; int count; char *fields[4]; time_t Arrived; time_t Expires; time_t Posted; time_t when; long where; long size; datum key; datum value; char date[20]; /* Split up the major fields. */ i = EXPsplit(line, HIS_FIELDSEP, fields, SIZEOF(fields)); if (i != 2 && i != 3) { (void)fprintf(stderr, IGNORING, line); return TRUE; } if ( strlen(fields[0]) >= (DBZMAXKEY-1) ) { (void)fprintf(stderr, IGNORING, line); return TRUE; } /* Split up the time field, robustly. */ if ((p = strchr(fields[1], HIS_SUBFIELDSEP)) == NULL) { /* One sub-field: when the article arrived. */ Arrived = atol(fields[1]); Expires = 0; Posted = Arrived; } else { *p = '\0'; Arrived = atol(fields[1]); *p++ = HIS_SUBFIELDSEP; if ((q = strchr(p, HIS_SUBFIELDSEP)) == NULL) { /* Two sub-fields: arrival and expiration. */ Expires = EQ(p, HIS_NOEXP) ? 0 : atol(p); Posted = Arrived; } else { /* All three sub-fields: arrival, expiration, posted. */ *q = '\0'; Expires = EQ(p, HIS_NOEXP) ? 0 : atol(p); *q++ = HIS_SUBFIELDSEP; Posted = atol(q); } } if (i == 2) { /* History line for already-expired article. */ if (Arrived < EXPremember || Arrived > Now + 86400) { if (EXPverbose > 3) (void)printf("forget: %s\n", line); EXPhistdrop++; return TRUE; } /* Not time to forget about this one yet. */ if (out) { where = Offset; (void)fprintf(out, "%s%c%s\n", fields[0], HIS_FIELDSEP, fields[1]); Offset += strlen(fields[0]) + 1 + strlen(fields[1]) + 1; if (EXPverbose > 3) (void)printf("remember: %s\n", line); EXPhistremember++; } } else { /* Active article -- split up the file entries. */ count = EXPsplit(fields[2], ' ', arts, nGroups); if (count == -1) { (void)fprintf(stderr, IGNORING, line); return TRUE; } EXPprocessed++; when = EXPusepost ? Posted : Arrived; /* Get space to hold the remaining file name entries. */ if (New.Data == NULL) { New.Size = length; New.Data = NEW(char, New.Size); } else if (New.Size < length) { New.Size = length; RENEW(New.Data, char, New.Size); } /* The "first" variable tells us if we haven't saved the first * article yet. This only matters if we're doing link-saving. */ first = EXPlinks && count > 1 ? arts[0] : (char *)NULL; if (EXPearliest) { for (size = -1, q = New.Data, i = 0; i < count; i++) { p = arts[i]; if (*p == '\0') /* Shouldn't happen. */ continue; if (EXPkeepit(p, when, Expires)) { if (EXPverbose > 1) (void)printf("keep %s\n", p); if (q > New.Data) *q++ = ' '; q += strlen(strcpy(q, p)); continue; } break; /* expired, stop looking */ } if(i < count) { /* clobber them all */ q = New.Data; /* no files for history line */ for (i = 0; i < count; i++) { p = arts[i]; if (*p == '\0') /* Shouldn't happen. */ continue; EXPremove(p, &size); } } } else { /* not earliest mode */ /* Loop over all file entries, see if we should keep each one. */ for (size = -1, q = New.Data, i = 0; i < count; i++) { p = arts[i]; if (*p == '\0') /* Shouldn't happen. */ continue; if (EXPkeepit(p, when, Expires)) { if (EXPverbose > 1) (void)printf("keep %s\n", p); if (first != NULL) { /* Keeping one and haven't kept the first; so save it. */ if (i > 0) q += strlen(strcpy(q, first)); first = NULL; } if (q > New.Data) *q++ = ' '; q += strlen(strcpy(q, p)); continue; } /* Don't delete the file if preserving symbolic links to it. */ if (EXPlinks && i == 0 && count > 1) continue; EXPremove(arts[i], &size); } /* If saving links and didn't have to save the leader, delete it. */ if (EXPlinks && first != NULL) EXPremove(first, &size); } /* not earliest mode */ if (q == New.Data) { if (EXPsizing && size > 0) EXPsaved += size; if (EXPremember > 0 && out != NULL) { where = Offset; if (Arrived > RealNow) Arrived = RealNow; (void)sprintf(date, "%lu", (unsigned long)Arrived); (void)fprintf(out, "%s%c%s%c%s\n", fields[0], HIS_FIELDSEP, date, HIS_SUBFIELDSEP, HIS_NOEXP); Offset += strlen(fields[0]) + 1 + strlen(date) + 1 + STRLEN(HIS_NOEXP) + 1; if (EXPverbose > 3) (void)printf("remember history: %s%c%s%c%s\n", fields[0], HIS_FIELDSEP, date, HIS_SUBFIELDSEP, HIS_NOEXP); EXPallgone++; } } else if (out) { where = Offset; (void)fprintf(out, "%s%c%s%c%s\n", fields[0], HIS_FIELDSEP, fields[1], HIS_FIELDSEP, New.Data); Offset += strlen(fields[0]) + 1 + strlen(fields[1]) + 1 + strlen(New.Data) + 1; if (EXPverbose > 3) (void)printf("remember article: %s%c%s%c%s\n", fields[0], HIS_FIELDSEP, fields[1], HIS_FIELDSEP, New.Data); EXPstillhere++; } } if (out == NULL) return TRUE; if (ferror(out)) { (void)fprintf(stderr, "Can't write new history, %s\n", strerror(errno)); return FALSE; } /* Set up the DBZ data. We don't have to sanitize the Message-ID * since it had to have been clean to get in there. */ key.dptr = fields[0]; key.dsize = strlen(key.dptr) + 1; value.dptr = (char *)&where; value.dsize = sizeof where; if (EXPverbose > 4) (void)printf("\tdbz %s@%ld\n", key.dptr, where); if (dbzstore(key, value) < 0) { (void)fprintf(stderr, "Can't store key, %s\n", strerror(errno)); return FALSE; } return TRUE; } /* ** Clean up link with the server and exit. */ STATIC NORETURN CleanupAndExit(Server, Paused, x) BOOL Server; BOOL Paused; int x; { FILE *F; if (Server) (void)ICCreserve(""); if (Paused && ICCgo(EXPreason) != 0) { (void)fprintf(stderr, "Can't unpause server, %s\n", strerror(errno)); x = 1; } if (Server && ICCclose() < 0) { (void)fprintf(stderr, "Can't close communication link, %s\n", strerror(errno)); x = 1; } if (EXPunlinkfile && fclose(EXPunlinkfile) == EOF) { (void)fprintf(stderr, "Can't close -z file, %s\n", strerror(errno)); x = 1; } /* Report stats. */ if (EXPsizing) (void)printf("%s approximately %ldk\n", EXPtracing ? "Would remove" : "Removed", EXPsaved); if (EXPverbose) { (void)printf("Article lines processed %8ld\n", EXPprocessed); (void)printf("Articles retained %8ld\n", EXPstillhere); (void)printf("Entries expired %8ld\n", EXPallgone); (void)printf("Files unlinked %8ld\n", EXPunlinked); (void)printf("Old entries dropped %8ld\n", EXPhistdrop); (void)printf("Old entries retained %8ld\n", EXPhistremember); } /* Append statistics to a summary file */ if (EXPgraph) { F = EXPfopen(FALSE, EXPgraph, "a"); (void)fprintf(F, "%ld %ld %ld %ld %ld %ld %ld\n", (long)Now, EXPprocessed, EXPstillhere, EXPallgone, EXPunlinked, EXPhistdrop, EXPhistremember); (void)fclose(F); } exit(x); } /* ** Print a usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage: expire [flags] [expire.ctl]\n"); exit(1); } int main(ac, av) int ac; char *av[]; { static char CANTCD[] = "Can't cd to %s, %s\n"; register int i; register int line; register char *p; register QIOSTATE *qp; FILE *F; char *active; char **arts; STRING History; STRING HistoryText; STRING HistoryPath; STRING HistoryDB; char *Historydir; char *Historypag; char *NHistory; char *NHistorydir; char *NHistorypag; char *EXPhistdir; char buff[SMBUF]; register FILE *out; BOOL Server; BOOL Paused; BOOL Bad; BOOL IgnoreOld; BOOL Writing; BOOL UnlinkFile; time_t TimeWarp; /* Set defaults. */ Server = TRUE; IgnoreOld = FALSE; History = "history"; HistoryText = _PATH_HISTORY; HistoryPath = NULL; Writing = TRUE; TimeWarp = 0; UnlinkFile = FALSE; (void)umask(NEWSUMASK); /* find the default history file directory */ EXPhistdir = COPY(_PATH_HISTORY); p = strrchr(EXPhistdir, '/'); if (p != NULL) { *p = '\0'; } /* Parse JCL. */ while ((i = getopt(ac, av, "f:h:d:eg:ilnpqr:stv:w:xz:")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'd': HistoryPath = optarg; break; case 'e': EXPearliest = TRUE; break; case 'f': History = optarg; break; case 'g': EXPgraph = optarg; break; case 'h': HistoryText = optarg; break; case 'i': IgnoreOld = TRUE; break; case 'l': EXPlinks = TRUE; break; case 'n': Server = FALSE; break; case 'p': EXPusepost = TRUE; break; case 'q': EXPquiet = TRUE; break; case 'r': EXPreason = optarg; break; case 's': EXPsizing = TRUE; break; case 't': EXPtracing = TRUE; break; case 'v': EXPverbose = atoi(optarg); break; case 'w': TimeWarp = (time_t)(atof(optarg) * 86400.); break; case 'x': Writing = FALSE; break; case 'z': EXPunlinkfile = EXPfopen(TRUE, optarg, "a"); UnlinkFile = TRUE; break; } ac -= optind; av += optind; if (ac != 0 && ac != 1) Usage(); /* Get active file, parse it. */ if ((active = ReadInFile(ACTIVE, (struct stat *)NULL)) == NULL) { (void)fprintf(stderr, "Can't read %s, %s\n", ACTIVE, strerror(errno)); exit(1); } BuildGroups(active); (void)time(&Now); RealNow = Now; Now += TimeWarp; /* Parse the control file. */ if (av[0]) F = EQ(av[0], "-") ? stdin : EXPfopen(FALSE, av[0], "r"); else F = EXPfopen(FALSE, _PATH_EXPIRECTL, "r"); if (!EXPreadfile(F)) { (void)fclose(F); (void)fprintf(stderr, "Format error in expire.ctl\n"); exit(1); } (void)fclose(F); /* Set up the link, reserve the lock. */ if (EXPreason == NULL) { (void)sprintf(buff, "Expiring process %ld", (long)getpid()); EXPreason = COPY(buff); } if (Server) { /* If we fail, leave evidence behind. */ if (ICCopen() < 0) { (void)fprintf(stderr, "Can't open channel to server, %s\n", strerror(errno)); CleanupAndExit(FALSE, FALSE, 1); } if (ICCreserve(EXPreason) != 0) { (void)fprintf(stderr, "Can't reserve server\n"); CleanupAndExit(FALSE, FALSE, 1); } } /* Make the history filenames. */ HistoryDB = COPY(HistoryText); (void)sprintf(buff, "%s.dir", HistoryDB); Historydir = COPY(buff); (void)sprintf(buff, "%s.pag", HistoryDB); Historypag = COPY(buff); if (HistoryPath) (void)sprintf(buff, "%s/%s.n", HistoryPath, History); else (void)sprintf(buff, "%s.n", HistoryText); NHistory = COPY(buff); (void)sprintf(buff, "%s.dir", NHistory); NHistorydir = COPY(buff); (void)sprintf(buff, "%s.pag", NHistory); NHistorypag = COPY(buff); if (!Writing) out = NULL; else { /* Open new history files, relative to news lib. */ if (chdir(EXPhistdir) < 0) { (void)fprintf(stderr, CANTCD, EXPhistdir, strerror(errno)); exit(1); } out = EXPfopen(TRUE, NHistory, "w"); (void)fclose(EXPfopen(TRUE, NHistorydir, "w")); (void)fclose(EXPfopen(TRUE, NHistorypag, "w")); if (EXPverbose > 3) (void)printf("created: %s %s %s\n", NHistory, NHistorydir, NHistorypag); (void)dbzincore(1); if (IgnoreOld) { if (dbzfresh(NHistory, dbzsize(0L), '\t', 'C', 0L) < 0) { (void)fprintf(stderr, "Can't create database, %s\n", strerror(errno)); exit(1); } } else if (dbzagain(NHistory, HistoryDB) < 0) { (void)fprintf(stderr, "Can't dbzagain, %s\n", strerror(errno)); exit(1); } } if (chdir(SPOOL) < 0) { (void)fprintf(stderr, CANTCD, SPOOL, strerror(errno)); exit(1); } /* Main processing loop. */ arts = NEW(char*, nGroups); if ((qp = QIOopen(HistoryText, QIO_BUFFER)) == NULL) { (void)fprintf(stderr, "Can't open history file, %s\n", strerror(errno)); CleanupAndExit(Server, FALSE, 1); } for (Bad = FALSE, line = 1, Paused = FALSE; ; line++) { if ((p = QIOread(qp)) != NULL) { if (!EXPdoline(out, p, QIOlength(qp), arts)) { Bad = TRUE; if (errno == ENOSPC) { (void)unlink(NHistory); (void)unlink(NHistorydir); (void)unlink(NHistorypag); } break; } continue; } /* Read or line-format error? */ if (QIOerror(qp)) { (void)fprintf(stderr, "Can't read line %d, %s\n", line, strerror(errno)); QIOclose(qp); CleanupAndExit(Server, Paused, 1); } if (QIOtoolong(qp)) { (void)fprintf(stderr, "Line %d too long\n", line); QIOclose(qp); CleanupAndExit(Server, Paused, 1); } /* We hit EOF. */ if (Paused || !Server) /* Already paused or we don't want to pause -- we're done. */ break; if (ICCpause(EXPreason) != 0) { (void)fprintf(stderr, "Can't pause server, %s\n", strerror(errno)); QIOclose(qp); CleanupAndExit(Server, Paused, 1); } Paused = TRUE; } QIOclose(qp); DISPOSE(arts); if (Writing) { /* Close the output files. */ if (ferror(out) || fflush(out) == EOF || fclose(out) == EOF) { (void)fprintf(stderr, "Can't close %s, %s\n", NHistory, strerror(errno)); Bad = TRUE; } if (dbmclose() < 0) { (void)fprintf(stderr, "Can't close history, %s\n", strerror(errno)); Bad = TRUE; } if (UnlinkFile && EXPunlinkfile == NULL) /* Got -z but file was closed; oops. */ Bad = TRUE; /* If we're done okay, and we're not tracing, slip in the new files. */ if (EXPverbose) { if (Bad) (void)printf("Expire errors: history files not updated.\n"); if (EXPtracing) (void)printf("Expire tracing: history files not updated.\n"); } if (!Bad && !EXPtracing) { if (chdir(EXPhistdir) < 0) { (void)fprintf(stderr, CANTCD, EXPhistdir, strerror(errno)); CleanupAndExit(Server, Paused, 1); } /* If user used the -d flag, mark we're done and exit. */ if (HistoryPath != NULL) { (void)sprintf(buff, "%s.done", NHistory); (void)fclose(EXPfopen(FALSE, buff, "w")); CleanupAndExit(Server, FALSE, 0); } if (rename(NHistory, HistoryText) < 0 || rename(NHistorydir, Historydir) < 0 || rename(NHistorypag, Historypag) < 0) { (void)fprintf(stderr, "Can't replace history files, %s\n", strerror(errno)); /* Yes -- leave the server paused. */ CleanupAndExit(Server, FALSE, 1); } } } CleanupAndExit(Server, Paused, Bad ? 1 : 0); /* NOTREACHED */ } inn-1.7.2/expire/convdate.c0100644000175100001440000000451206443103542014074 0ustar mdusers/* $Revision: 1.7 $ ** ** Convert date strings and numbers to numbers and strings. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include "libinn.h" #include "macros.h" /* This is sloppy, but good enough. */ STATIC STRING Program = "convdate"; STATIC BOOL AllDigits(p) register char *p; { for (; *p; p++) if (!CTYPE(isdigit, *p)) return FALSE; return TRUE; } /* ** Print usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage: %s [-c|-n|-s] arg...\n", Program); exit(1); } int main(ac, av) int ac; char *av[]; { static char CANTCONVERT[] = "%s: Can't convert \"%s\"\n"; int Mode; int i; int s; time_t t; char *p; TIMEINFO Now; /* Set defaults. */ Mode = 0; /* Parse JCL. */ while ((i = getopt(ac, av, "cns")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'c': case 'n': case 's': if (Mode != 0) { (void)fprintf(stderr, "Only one -c -n or -s flag is allowed.\n"); exit(1); } Mode = i; break; } ac -= optind; av += optind; if (ac == 0) Usage(); /* Get the current time. */ if (Mode != 'c' && GetTimeInfo(&Now) < 0) { (void)fprintf(stderr, "%s: Can't get time, %s\n", Program, strerror(errno)); exit(1); } for (s = 0; (p = *av++) != NULL; ) switch (Mode) { default: case 's': if ((t = parsedate(p, &Now)) == -1) { (void)fprintf(stderr, CANTCONVERT, Program, p); s++; } else if ((p = ctime(&t)) == NULL) { (void)fprintf(stderr, "%s: Can't convert %ld to string\n", Program, (long)t); s++; } else (void)printf("%s", p); break; case 'n': if ((t = parsedate(p, &Now)) == -1) { (void)fprintf(stderr, CANTCONVERT, Program, p); s++; } else (void)printf("%ld\n", (long)t); break; case 'c': if (!AllDigits(p)) { (void)fprintf(stderr, CANTCONVERT, Program, p); s++; } else { t = (time_t)atol(p); if ((p = ctime(&t)) == NULL) { (void)fprintf(stderr, CANTCONVERT, Program, p); s++; } else (void)printf("%s", p); } break; } exit(s); /* NOTREACHED */ } inn-1.7.2/expire/newsrequeue.c0100644000175100001440000005103006443103542014636 0ustar mdusers/* $Revision: 1.11 $ ** ** Expire news articles. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include #include "paths.h" #include "libinn.h" #include "dbz.h" #include "qio.h" #include "macros.h" /* ** Hashing functions. See innd for comments. */ #define NGH_HASH(Name, p, j) \ for (p = Name, j = 0; *p; ) j = (j << 5) + j + *p++ #define NGH_SIZE 128 #define NGH_BUCKET(j) &NGHtable[j & (NGH_SIZE - 1)] typedef struct _NGHASH { int Size; int Used; struct _NEWSGROUP **Groups; } NGHASH; /* ** A site has a filename, and flag saying if we already sent it here. */ typedef struct _SITE { char *Name; char **Exclusions; char *Patterns; char **Distributions; char *Flags; BOOL Sent; } SITE; /* ** A newsgroup has a name, and a set of sites that get the group. */ typedef struct _NEWSGROUP { char *Name; char Flag; int nSites; SITE **Sites; } NEWSGROUP; /* ** Bit array, indexed by character (8bit chars only). If ARTpathbits['x'] ** is non-zero, then 'x' is a valid character for a host name. */ STATIC char ARTpathbits[256]; #define ARThostchar(c) (ARTpathbits[(int) c] != '\0') /* ** Global variables. */ STATIC SITE *Sites; STATIC int nSites; STATIC NEWSGROUP *Groups; STATIC int nGroups; STATIC long Epoch; STATIC NGHASH NGHtable[NGH_SIZE]; /* ** Get the next filename from the history file. */ STATIC BOOL GetName(F, buff) register FILE *F; register char *buff; { static char SPOOL[] = _PATH_SPOOL; register int c; register char *p; /* Skip whitespace before filename. */ while ((c = getc(F)) == ' ' || c == '<') continue; if (c == EOF || c == '\n') return FALSE; (void)strcpy(buff, SPOOL); p = &buff[STRLEN(SPOOL)]; *p++ = '/'; *p++ = (char)c; while ((c = getc(F)) != EOF && c != ' ' && c != '\n') *p++ = (char)(c == '.' ? '/' : c); *p = '\0'; return TRUE; } /* ** Find an existing file for the specified Message-ID, and return the ** open file pointer or NULL. */ STATIC FILE * FindFile(F, id, name) FILE *F; char *id; char *name; { static char BADLINE[] = "Bad text line for \"%s\", %s\n"; register char *p; register char *q; register int i; register int c; register FILE *art; datum key; datum val; OFFSET_T offset; char date[SMBUF]; key.dsize = strlen(id) + 1; key.dptr = id; /* Do the lookup. */ val = dbzfetch(key); if (val.dptr == NULL || val.dsize != sizeof offset) { (void)fprintf(stderr, "Can't find \"%s\"\n", key.dptr); return NULL; } /* Get the seek offset, and seek. */ for (p = val.dptr, q = (char *)&offset, i = sizeof offset; --i >= 0; ) *q++ = *p++; if (fseek(F, offset, SEEK_SET) == -1) { (void)fprintf(stderr, "Can't seek to %ld, %s\n", offset, strerror(errno)); return NULL; } if ((c = getc(F)) == EOF || c != '<') abort(); if (Epoch) { /* Skip forward to the date. */ while ((c = getc(F)) != EOF && c != '\n') if (c == HIS_FIELDSEP) break; if (c != HIS_FIELDSEP) { (void)fprintf(stderr, BADLINE, key.dptr, strerror(errno)); return NULL; } for (p = date; (c = getc(F)) != EOF && CTYPE(isdigit, c); ) *p++ = (char)c; if (c == EOF) { (void)fprintf(stderr, BADLINE, key.dptr, strerror(errno)); return NULL; } *p = '\0'; if (atol(date) < Epoch) return NULL; } else { /* Move to the filename fields. */ for (i = 2; (c = getc(F)) != EOF && c != '\n'; ) if (c == HIS_FIELDSEP && --i == 0) break; if (c != HIS_FIELDSEP) { (void)fprintf(stderr, BADLINE, key.dptr, strerror(errno)); return NULL; } } /* Loop over all possible files. */ while (GetName(F, name)) if ((art = fopen(name, "r")) != NULL) return art; return NULL; } /* ** Read the active file and fill in the Groups array. Note that ** NEWSGROUP.Sites is filled in later. */ STATIC void ParseActive(name) STRING name; { char *active; register char *p; register char *q; register int i; register unsigned j; register NGHASH *htp; register NEWSGROUP *ngp; int NGHbuckets; /* Read the file, count the number of groups. */ if ((active = ReadInFile(name, (struct stat *)NULL)) == NULL) { (void)fprintf(stderr, "Can't read \"%s\", %s\n", name, strerror(errno)); exit(1); } for (p = active, i = 0; (p = strchr(p, '\n')) != NULL; p++, i++) continue; nGroups = i; Groups = NEW(NEWSGROUP, i); /* Set up the default hash buckets. */ NGHbuckets = i / NGH_SIZE; if (NGHbuckets == 0) NGHbuckets = 1; for (i = NGH_SIZE, htp = NGHtable; --i >= 0; htp++) { htp->Size = NGHbuckets; htp->Groups = NEW(NEWSGROUP*, htp->Size); htp->Used = 0; } /* Fill in the newsgroups array. */ for (p = active, ngp = Groups, i = nGroups; --i >= 0; ngp++, p = q + 1) { if ((q = strchr(p, '\n')) == NULL) { (void)fprintf(stderr, "Missing newline near \"%.10s...\"\n", p); exit(1); } *q = '\0'; ngp->Name = p; ngp->nSites = 0; /* Get the first character after the third space. */ for (j = 0; *p; p++) if (*p == ' ' && ++j == 3) break; if (*p == '\0') { (void)fprintf(stderr, "Bad format near \"%.10s...\"\n", ngp->Name); exit(1); } ngp->Flag = p[1]; /* Find the right bucket for the group, make sure there is room. */ /* SUPPRESS 6 *//* Over/underflow from plus expression */ p = strchr(ngp->Name, ' '); *p = '\0'; NGH_HASH(ngp->Name, p, j); htp = NGH_BUCKET(j); if (htp->Used >= htp->Size) { htp->Size += NGHbuckets; RENEW(htp->Groups, NEWSGROUP*, htp->Size); } htp->Groups[htp->Used++] = ngp; } /* Note that we don't bother to sort the buckets. */ } /* ** Split text into comma-separated fields. */ STATIC char ** CommaSplit(text) char *text; { register int i; register char *p; register char **argv; char **save; /* How much space do we need? */ for (i = 2, p = text; *p; p++) if (*p == ',') i++; for (argv = save = NEW(char*, i), *argv++ = p = text; *p; ) if (*p == ',') { *p++ = '\0'; *argv++ = p; } else p++; *argv = NULL; return save; } /* ** Read the newsfeeds file and fill in the Sites array. Finish off the ** Groups array. */ STATIC void ParseNewsfeeds(name) STRING name; { register char *p; register char *to; register int i; register NEWSGROUP *ngp; register SITE *sp; char **strings; char *save; char *newsfeeds; /* Read in the file, get a gross count of the number of sites. */ if ((newsfeeds = ReadInFile(name, (struct stat *)NULL)) == NULL) { (void)fprintf(stderr, "Can't read \"%s\", %s\n", name, strerror(errno)); exit(1); } for (p = newsfeeds, i = 0; (p = strchr(p, '\n')) != NULL; p++, i++) continue; /* Scan the file, parse all multi-line entries. */ for (strings = NEW(char*, i + 1), i = 0, to = p = newsfeeds; *p; ) { for (save = to; *p; ) { if (*p == '\n') { p++; *to = '\0'; break; } if (*p == '\\' && p[1] == '\n') while (*++p && CTYPE(isspace, *p)) continue; else *to++ = *p++; } *to++ = '\0'; if (*save == COMMENT_CHAR || *save == '\0') continue; strings[i++] = COPY(save); } DISPOSE(newsfeeds); if (i == 0) { (void)fprintf(stderr, "No sites.\n"); exit(1); } /* Get space for the sites. */ nSites = i; Sites = NEW(SITE, nSites); for (i = nGroups, ngp = Groups; --i >= 0; ngp++) ngp->Sites = NEW(SITE*, nSites); /* Do initial processing of the site entries. */ for (i = 0, sp = Sites; i < nSites; i++, sp++) { /* Nip off the first and second fields. */ sp->Name = strings[i]; if ((p = strchr(sp->Name, NF_FIELD_SEP)) == NULL) { (void)fprintf(stderr, "No separator for site \"%.10s...\"\n", sp->Name); exit(1); } *p++ = '\0'; sp->Patterns = p; /* Nip off the third field. */ if ((p = strchr(sp->Patterns, NF_FIELD_SEP)) == NULL) { (void)fprintf(stderr, "No flags for site \"%s\"\n", sp->Name); exit(1); } *p++ = '\0'; sp->Flags = p; /* Nip off the last field, build the filename. */ if ((p = strchr(sp->Flags, NF_FIELD_SEP)) == NULL) { (void)fprintf(stderr, "No last field for site \"%s\"\n", sp->Name); exit(1); } *p++ = '\0'; /* Handle the subfields. */ if ((p = strchr(sp->Name, NF_SUBFIELD_SEP)) != NULL) { *p++ = '\0'; sp->Exclusions = CommaSplit(p); } else sp->Exclusions = NULL; if ((p = strchr(sp->Patterns, NF_SUBFIELD_SEP)) != NULL) { *p++ = '\0'; sp->Distributions = CommaSplit(p); } else sp->Distributions = NULL; } } /* ** Build the subscription list for a site. */ STATIC void BuildSubList(sp, subbed) register SITE *sp; char *subbed; { static char SEPS[] = ","; register char subvalue; register char *pat; register char *p; register NEWSGROUP *ngp; register int i; BOOL JustModerated; BOOL JustUnmoderated; if (EQ(sp->Name, "ME")) return; /* Fill in the subbed array with the mask of groups. */ (void)memset((POINTER)subbed, SUB_DEFAULT, (SIZE_T)nGroups); if ((pat = strtok(sp->Patterns, SEPS)) != NULL) do { subvalue = *pat != SUB_NEGATE; if (!subvalue) pat++; for (p = subbed, ngp = Groups, i = nGroups; --i >= 0; ngp++, p++) if (wildmat(ngp->Name, pat)) *p = subvalue; } while ((pat = strtok((char *)NULL, SEPS)) != NULL); /* Parse the flags.. */ JustModerated = FALSE; JustUnmoderated = FALSE; if ((p = strtok(sp->Flags, SEPS)) != NULL) do { switch (*p) { case 'W': if (EQ(p, "Wnm")) break; /* FALLTHROUGH */ default: (void)fprintf(stderr, "Ignoring \"%s\" flag for \"%s\"\n", p, sp->Name); break; case 'N': while (*++p) switch (*p) { default: (void)fprintf(stderr, "Unknown N%c flag for \"%s\"\n", *p, sp->Name); break; case 'm': JustModerated = TRUE; break; case 'u': JustUnmoderated = TRUE; break; } break; case 'T': break; } } while ((p = strtok((char *)NULL, SEPS)) != NULL); /* Modify the subscription list based on the flags. */ if (JustModerated) for (p = subbed, ngp = Groups, i = nGroups; --i >= 0; ngp++, p++) if (ngp->Flag != NF_FLAG_MODERATED) *p = FALSE; if (JustUnmoderated) for (p = subbed, ngp = Groups, i = nGroups; --i >= 0; ngp++, p++) if (ngp->Flag == NF_FLAG_MODERATED) *p = FALSE; /* Tell the groups that this site gets that they should feed this site. */ for (p = subbed, ngp = Groups, i = nGroups; --i >= 0; ngp++) if (*p++) ngp->Sites[ngp->nSites++] = sp; } STATIC NEWSGROUP * NGfind(Name) char *Name; { register char *p; register int i; register unsigned int j; register NEWSGROUP **ngp; char c; NGHASH *htp; /* SUPPRESS 6 *//* Over/underflow from plus expression */ NGH_HASH(Name, p, j); htp = NGH_BUCKET(j); for (c = *Name, ngp = htp->Groups, i = htp->Used; --i >= 0; ngp++) if (c == ngp[0]->Name[0] && EQ(Name, ngp[0]->Name)) return ngp[0]; return NULL; } /* ** Split up the Path line. */ STATIC char ** ParsePath(p) register char *p; { static char *save; static int oldlength; static char **hosts; register int i; register char **hp; char *nl; if (save) DISPOSE(save); if ((nl = strchr(p, '\n')) != NULL) *nl = '\0'; save = p = COPY(p); if (nl) *nl = '\n'; /* Get an array of character pointers. */ i = strlen(p); if (hosts == NULL) { hosts = NEW(char*, i + 1); oldlength = i; } else if (oldlength < i) { RENEW(hosts, char*, i + 1); oldlength = i; } /* Loop over text. */ for (hp = hosts; *p; *p++ = '\0') { /* Skip leading separators. */ for (; *p && !ARThostchar(*p); p++) continue; if (*p == '\0') break; /* Mark the start of the host, move to the end of it. */ for (*hp++ = p; *p && ARThostchar(*p); p++) continue; if (*p == '\0') break; } *hp = NULL; return hosts; } /* ** Has this site or its excludes already been seen? */ STATIC BOOL Seen(sp, Path) SITE *sp; char **Path; { register char *p; register char **pp; while ((p = *Path++) != NULL) { if (EQ(p, sp->Name)) return TRUE; if ((pp = sp->Exclusions) != NULL) for ( ; *pp; pp++) if (EQ(p, *pp)) return TRUE; } return FALSE; } /* ** Check a single word against a distribution list. */ STATIC BOOL WantThisOne(list, p) register char **list; register char *p; { register char *q; register char c; register BOOL sawbang; for (sawbang = FALSE, c = *p; (q = *list) != NULL; list++) if (*q == '!') { sawbang = TRUE; if (c == *++q && EQ(p, q)) return FALSE; } else if (c == *q && EQ(p, q)) return TRUE; /* If we saw any !foo's and didn't match, then assume they are all * negated distributions and return TRUE, else return false. */ return sawbang; } /* ** Does the site want this article with this distribution? */ STATIC BOOL Wanted(site, article) register char **site; register char **article; { for ( ; *article; article++) if (WantThisOne(site, *article)) return TRUE; return FALSE; } /* ** Split up the Distribution line. */ STATIC char ** ParseDistribs(p) register char *p; { static char SEPS[] = ", \t"; static char *save; static int Size; static int Used; static char **List; char *nl; /* Throw out old storage, make sure we have a list. */ if (save) DISPOSE(save); if ((nl = strchr(p, '\n')) != NULL) *nl = '\0'; save = p = COPY(p); if (nl) *nl = '\n'; if (List == NULL) { Size = 10; List = NEW(char*, Size); } Used = 0; if ((p = strtok(p, SEPS)) == NULL) return NULL; do { if (Used == Size - 2) { Size += 10; RENEW(List, char*, Size); } List[Used++] = p; } while ((p = strtok((char *)NULL, SEPS)) != NULL); List[Used] = NULL; return List; } /* ** Process a single file. */ STATIC void QueueArticle(name, id, art) char *name; char *id; register FILE *art; { static char SEPS[] = ","; static char DISTRIBUTION[] = "Distribution"; static char PATH[] = "Path"; static char NG[] = "Newsgroups"; static char *Buffer; static int Size; register SITE *sp; register int i; register char *p; register BOOL Dirty; register char *nl; register NEWSGROUP *ngp; struct stat Sb; char **Path; char **Distribs; /* Read in the file. */ if (fstat((int)fileno(art), &Sb) < 0) { (void)fprintf(stderr, "Can't fstat \"%s\", %s\n", name, strerror(errno)); return; } if (Buffer == NULL) { Size = Sb.st_size; Buffer = NEW(char, Size + 1); } else if (Size < Sb.st_size) { Size = Sb.st_size; RENEW(Buffer, char, Size + 1); } if (fread((POINTER)Buffer, (SIZE_T)1, (SIZE_T)Sb.st_size, art) != Sb.st_size) { (void)fprintf(stderr, "Can't read \"%s\", %s\n", name, strerror(errno)); return; } Buffer[Sb.st_size] = '\0'; /* Clear all sites. */ for (Dirty = FALSE, i = nSites, sp = Sites; --i >= 0; sp++) sp->Sent = FALSE; /* Parse the Path and Distribution headers. */ if ((p = HeaderFind(Buffer, PATH, STRLEN(PATH))) == NULL) { (void)fprintf(stderr, "No \"Path\" header in \"%s\"\n", name); return; } Path = ParsePath(p); if ((p = HeaderFind(Buffer, DISTRIBUTION, STRLEN(DISTRIBUTION))) == NULL) Distribs = NULL; else Distribs = ParseDistribs(p); /* Look at the newsgroups, see who gets the article. */ if ((p = HeaderFind(Buffer, NG, STRLEN(NG))) == NULL) { (void)fprintf(stderr, "No \"Newsgroups\" header in \"%s\"\n", name); return; } if ((nl = strchr(p, '\n')) != NULL) *nl = '\0'; if ((p = strtok(p, SEPS)) != NULL) do { if ((ngp = NGfind(p)) != NULL) { for (i = 0; i < ngp->nSites; i++) { sp = ngp->Sites[i]; if (Path && Seen(sp, Path)) continue; if (Distribs && sp->Distributions && !Wanted(sp->Distributions, Distribs)) continue; sp->Sent = TRUE; Dirty = TRUE; } } } while ((p = strtok((char *)NULL, SEPS)) != NULL); /* Write the output. */ if (Dirty) { (void)printf("%s %s", name, id); for (i = nSites, sp = Sites; --i >= 0; sp++) if (sp->Sent) (void)printf(" %s", sp->Name); (void)printf("\n"); if (fflush(stdout) == EOF || ferror(stdout)) (void)fprintf(stderr, "Error writing \"%s\", %s\n", id, strerror(errno)); } } /* ** Print a usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage error.\n"); exit(1); } int main(ac, av) int ac; char *av[]; { register int i; register QIOSTATE *qp; register char *p; register char *q; #if defined(DO_NNTPLINK_LOG) register char *r; #endif /* defined(DO_NNTPLINK_LOG) */ register char *line; register FILE *art; register FILE *F; STRING Active; STRING History; STRING Newsfeeds; char *subbed; time_t t; BOOL Logfile; char name[SPOOLNAMEBUFF]; char save; /* Set defaults. */ Active = _PATH_ACTIVE; History = _PATH_HISTORY; Newsfeeds = _PATH_NEWSFEEDS; Logfile = FALSE; /* Parse JCL. */ while ((i = getopt(ac, av, "a:d:h:ln:")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'a': Active = optarg; break; case 'd': (void)time(&t); Epoch = (long)t - atol(optarg) * 86400L; break; case 'h': History = optarg; break; case 'l': Logfile = TRUE; break; case 'n': Newsfeeds = optarg; break; } ac -= optind; av += optind; if (Epoch && Logfile) Usage(); /* Parse positional parameters; at most one, the input file. */ switch (ac) { default: Usage(); /* NOTREACHED */ case 0: break; case 1: if (freopen(av[0], "r", stdin) == NULL) { (void)fprintf(stderr, "Can't open \"%s\" for input, %s\n", av[0], strerror(errno)); exit(1); } break; } qp = QIOfdopen((int)fileno(stdin), QIO_BUFFER); /* Open the history file. */ if (dbminit(History) < 0) { (void)fprintf(stderr, "Can't set up \"%s\" database, %s\n", History, strerror(errno)); exit(1); } if ((F = fopen(History, "r")) == NULL) { (void)fprintf(stderr, "Can't open \"%s\" for reading, %s\n", History, strerror(errno)); exit(1); } if (!Logfile) { /* Read the control files and build the subscription list. */ ParseActive(Active); ParseNewsfeeds(Newsfeeds); subbed = NEW(char, nGroups); for (i = 0; i < nSites; i++) BuildSubList(&Sites[i], subbed); DISPOSE(subbed); /* Set up the character class tables. */ (void)memset((POINTER)ARTpathbits, 0, sizeof ARTpathbits); p = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._-"; while ((i = *p++) != 0) ARTpathbits[i] = TRUE; } /* Now we're ready to start reading input. */ for (i = 1; ; i++) { if ((line = QIOread(qp)) == NULL) { /* Read or line-format error? */ if (QIOerror(qp)) { (void)fprintf(stderr, "Can't read line %d, %s\n", i, strerror(errno)); exit(1); } if (QIOtoolong(qp)) { (void)fprintf(stderr, "Line %d too long\n", i); exit(1); } /* We hit EOF. */ break; } if (Logfile) { /* Check the log character (correct for zero-origin subscripts. */ switch (line[STRLEN("Jan 23 12:52:12.631 +") - 1]) { default: (void)fprintf(stderr, "Ignoring \"%s\"\n", line); continue; case ART_CANC: case ART_REJECT: continue; case ART_ACCEPT: case ART_JUNK: break; } } /* Snip off the Message-ID. */ if ((p = strchr(line, '<')) == NULL || (q = strchr(p, '>')) == NULL) { (void)fprintf(stderr, "No Message-ID in \"%s\"\n", line); continue; } save = *++q; *q = '\0'; /* Open the article. */ if ((art = FindFile(F, p, name)) == NULL) continue; if (Logfile) { #if defined(DO_NNTPLINK_LOG) /* Skip the (filename) if it's there. */ if (save != '\0' && (r = strchr(q + 1, ')')) != NULL) (void)printf("%s %s%s\n", name, p, r + 1); else { *q = save; (void)printf("%s %s\n", name, p); } #else *q = save; (void)printf("%s %s\n", name, p); #endif /* defined(DO_NNTPLINK_LOG) */ if (fflush(stdout) == EOF || ferror(stdout)) (void)fprintf(stderr, "Can't write %s, %s\n", p, strerror(errno)); } else QueueArticle(name, p, art); (void)fclose(art); } /* That's all she wrote. */ QIOclose(qp); (void)fclose(F); (void)dbmclose(); exit(0); /* NOTREACHED */ } inn-1.7.2/expire/reap.pch0100644000175100001440000002171006443103542013547 0ustar mdusers$Revision: 1.2 $ Steven Grimm, November, 1991. Reap is a space-based expire program written by David B. Thomas, . It was posted to alt.sources in March, 1991, with Message-ID <1991Mar28.025957.1976@yenta.alb.nm.us>. Among other places, it is available for FTP from ftp.cs.widener.edu, as /pub/src/news/reap.shar.Z. Usage: reap -m | prunehistory The following patch adds two new flags: -x foo Ignore filename foo (useful for NN databases; for example "-x .nnd -x .nnx"). -m Print filename and Message-Id of every article it removes (useful for modifying the INN history database). It also sends reap's summary lines to stdout, so prunehistory won't complain about them. *** lib.c.ORIG Mon Nov 25 13:54:15 1991 --- lib.c Mon Nov 25 13:54:14 1991 *************** *** 168,173 **** --- 168,188 ---- f->next = incl; incl = f; } + + /* + * Add a name to the filename exclude list, "efil." + */ + exclude_file(text) + char *text; + { + struct filspec *f; + + f = newnode(text); + f->recurse = 0; /* It's irrelevant here. */ + f->next = efil; + efil = f; + } + preclude() { struct filspec *p; *** main.c.ORIG Mon Nov 25 13:54:19 1991 --- main.c Mon Nov 25 13:54:18 1991 *************** *** 11,16 **** --- 11,17 ---- /* linked lists for included and excluded file specs */ struct filspec *incl = NULL, + *efil = NULL, /* list of excluded filenames */ *excl = NULL ; char *************** *** 20,26 **** ; int verbose = 0, /* verbosity (-v) flag */ ! dryrun = 0 /* do-not-unlink (-n) flag */ ; time_t age, /* unlink files older than this */ --- 21,28 ---- ; int verbose = 0, /* verbosity (-v) flag */ ! dryrun = 0, /* do-not-unlink (-n) flag */ ! printid = 0 /* print message-id (-m) flag */ ; time_t age, /* unlink files older than this */ *************** *** 53,60 **** progname = argv[0]; /* parse args */ ! while ( (c=getopt(argc,argv,"vsnf:")) != EOF) switch(c) { case 'n': ++dryrun; break; --- 55,65 ---- progname = argv[0]; /* parse args */ ! while ( (c=getopt(argc,argv,"mvsnf:x:")) != EOF) switch(c) { + case 'm': + ++printid; + break; case 'n': ++dryrun; break; *************** *** 64,69 **** --- 69,78 ---- case 'f': scriptfile = optarg; break; + case 'x': + if (optarg != NULL && optarg[0] != '\0') + exclude_file(optarg); + break; case 's': ++summary; break; *************** *** 78,88 **** if (errflag) { fprintf (stderr, ! "usage: %s [-v] [-s] [-n] [-f funclist] freeblocks\n", progname); exit (-1); } /* stat newsdir to find the number of the device it's on */ if (stat(newsdir, &st)) --- 87,102 ---- if (errflag) { fprintf (stderr, ! "usage: %s [-v] [-s] [-n] [-m] [-x filename] [-f funclist] freeblocks\n", progname); exit (-1); } + /* Add "." and ".." to the excluded-file list, so we don't try to remove + * them. + */ + exclude_file("."); + exclude_file(".."); /* stat newsdir to find the number of the device it's on */ if (stat(newsdir, &st)) *** reap.8.ORIG Mon Nov 25 13:54:25 1991 --- reap.8 Mon Nov 25 13:54:22 1991 *************** *** 3,9 **** reap - remove news articles as space needed .SH SYNOPSIS .B reap ! [-v] [-s] [-n] [-f scriptfile] freeblocks .SH DESCRIPTION .I Reap checks disk freespace and deletes netnews articles --- 3,9 ---- reap - remove news articles as space needed .SH SYNOPSIS .B reap ! [-v] [-s] [-n] [-m] [-x filename] [-f scriptfile] freeblocks .SH DESCRIPTION .I Reap checks disk freespace and deletes netnews articles *************** *** 49,54 **** --- 49,66 ---- The .B -f option is used to specify an alternate function script file. + .PP + The + .B -x + option (which may be used more than once) specifies a filename to ignore + wherever it occurs. This can be used to ignore nn or trn database files, + for example. + .PP + The + .B -m + option instructs reap to print the filename and message ID of each article + it deletes. The filename is output, followed by a tab, the message ID, and + a newline. .SH FUNCTION SCRIPT FILE FORMAT A function script file consists of a series of expire functions, one per line. Each expire function contains an age limit (in days, decimals okay), followed *** reap.c.ORIG Mon Nov 25 13:54:28 1991 --- reap.c Mon Nov 25 13:54:26 1991 *************** *** 10,15 **** --- 10,16 ---- #include "reap.h" + void print_message_id(); reap() { *************** *** 42,48 **** /* open directory for reading */ if ( (dirp = opendir(name)) == NULL) ! ouch ("%s: can't read directory %s\n", name); /* see if this directory is excluded. --- 43,52 ---- /* open directory for reading */ if ( (dirp = opendir(name)) == NULL) ! { ! fprintf(stderr, "Warning: can't read directory %s\n", name); ! return; ! } /* see if this directory is excluded. *************** *** 62,68 **** /* loop for each directory entry */ ! while ( (dp = readdir(dirp)) != NULL) { /* name might be exactly MAXFILENAME characters long, and thus * might not be null-terminated. Some insurance: --- 66,74 ---- /* loop for each directory entry */ ! while ( (dp = readdir(dirp)) != NULL) ! { ! int skipflag; /* Skip this file? */ /* name might be exactly MAXFILENAME characters long, and thus * might not be null-terminated. Some insurance: *************** *** 70,77 **** strncpy (thisname, dp->d_name, MAXFILENAME); thisname[MAXFILENAME] = '\0'; ! /* skip dot and dotdot */ ! if (!strcmp(thisname, ".") || !strcmp(thisname, "..")) continue; /* build the full pathname of current object */ --- 76,90 ---- strncpy (thisname, dp->d_name, MAXFILENAME); thisname[MAXFILENAME] = '\0'; ! /* Scan through the excluded filename list to see if we should avoid ! * messing with this file. "." and ".." are automatically members ! * of the excluded-file list, so we don't deal with them specially. ! */ ! skipflag = 0; ! for (e = efil; e != NULL; e = e->next) ! if (! strcmp(thisname, e->name)) ! skipflag = 1; ! if (skipflag) continue; /* build the full pathname of current object */ *************** *** 113,118 **** --- 126,133 ---- /* reap this file! */ if (dryrun) { + if (printid) + print_message_id(fullpath); printf ("Would unlink %s\n", fullpath); free (fullpath); continue; *************** *** 120,125 **** --- 135,143 ---- if (verbose) printf ("Unlinking %s\n", fullpath); + if (printid) + print_message_id(fullpath); + if (unlink (fullpath) == -1) fprintf (stderr, "%s: cannot unlink %s\n", progname, fullpath); *************** *** 131,133 **** --- 149,210 ---- closedir (dirp); } /* dodir() */ + + /* Replacement for index() so we don't have to worry about libraries */ + char * + ind(s, c) + char *s, c; + { + while (*s) + if (*s == c) + return(s); + else + s++; + return(NULL); + } + + /* + * koreth 11/24/91 + * + * Open an article and scan for the message-ID header line, printing whatever + * is between the < and > there. (And the <>, of course.) + */ + void + print_message_id(name) + char *name; + { + char buffer[BUFSIZ], *left, *right; + int c; + FILE *fp; + + fp = fopen(name, "r"); + if (fp == NULL) + { + perror(name); + return; + } + + while (! feof(fp)) + { + fgets(buffer, sizeof(buffer), fp); + if (buffer[0] == '\n' || buffer[0] == '\0') + break; + + if (strncmp(buffer, "Message-ID: ", 12)) + continue; + + if ((left = ind(buffer, '<')) == NULL) + continue; + if ((right = ind(left, '>')) == NULL) + continue; + + right[1] = '\0'; + + printf("%s\t%s\n", left, name); + fclose(fp); + return; + } + + fprintf(stderr, "%s has no Message-ID\n", name); + fclose(fp); + } *************** *** 127,135 **** if (summary) { c = freeblox(device); ! printf ("Freespace was %d, now %d. Cleared %d.\n", thenfree, c, c - thenfree); ! printf ("Stopped after line %d in %s\n", lineno, scriptfile); } --- 127,135 ---- if (summary) { c = freeblox(device); ! fprintf (stderr, "Freespace was %d, now %d. Cleared %d.\n", thenfree, c, c - thenfree); ! fprintf (stderr, "Stopped after line %d in %s\n", lineno, scriptfile); } *** reap.h.ORIG Mon Nov 25 13:54:30 1991 --- reap.h Mon Nov 25 13:54:29 1991 *************** *** 45,50 **** --- 45,51 ---- extern struct filspec *incl, + *efil, *excl ; extern char *************** *** 55,61 **** extern int verbose, dryrun, ! optind ; extern char *optarg; extern double atof(); --- 56,63 ---- extern int verbose, dryrun, ! optind, ! printid ; extern char *optarg; extern double atof(); inn-1.7.2/expire/grephistory.c0100644000175100001440000001433206443103542014651 0ustar mdusers/* $Revision: 1.9 $ ** ** Get data from history database. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include #include "paths.h" #include "libinn.h" #include "dbz.h" #include "macros.h" /* ** Get the next filename from the history file. */ STATIC BOOL GetName(F, buff, Againp) register FILE *F; register char *buff; BOOL *Againp; { static char SPOOL[] = _PATH_SPOOL; register int c; register char *p; /* Skip whitespace before filename. */ while ((c = getc(F)) == ' ') continue; if (c == EOF || c == '\n') return FALSE; (void)strcpy(buff, SPOOL); p = &buff[STRLEN(SPOOL)]; *p++ = '/'; *p++ = (char)c; while ((c = getc(F)) != EOF && c != ' ' && c != '\n') *p++ = (char)(c == '.' ? '/' : c); *p = '\0'; *Againp = c != EOF && c != '\n'; return TRUE; } /* ** Given a DBZ value, seek to the right spot. */ STATIC BOOL HistorySeek(F, p) register FILE *F; register char *p; { register char *dest; OFFSET_T l; register int c; register int i; for (dest = (char *)&l, i = sizeof l; --i >= 0; ) *dest++ = *p++; if (fseek(F, l, SEEK_SET) == -1) { (void)fprintf(stderr, "Can't seek to %ld, %s\n", l, strerror(errno)); return FALSE; } /* Move to the filename fields. */ for (i = 2; (c = getc(F)) != EOF && c != '\n'; ) if (c == HIS_FIELDSEP && --i == 0) break; if (c != HIS_FIELDSEP) /* Could have only two fields (if expired) so don't complain now. * (void)fprintf(stderr, "Bad text line for \"%s\", %s\n", * key, strerror(errno)); */ return FALSE; return TRUE; } /* ** Print the full line from the history file. */ STATIC void FullLine(F, p) register FILE *F; register char *p; { register char *dest; OFFSET_T l; register int c; register int i; for (dest = (char *)&l, i = sizeof l; --i >= 0; ) *dest++ = *p++; if (fseek(F, l, SEEK_SET) == -1) { (void)fprintf(stderr, "Can't seek to %ld, %s\n", l, strerror(errno)); exit(1); } while ((c = getc(F)) != EOF && c != '\n') (void)putchar(c); (void)putchar('\n'); } /* ** Read stdin for list of Message-ID's, output list of ones we ** don't have. Or, output list of files for ones we DO have. */ STATIC void IhaveSendme(History, What) STRING History; register char What; { register FILE *F; register char *p; register char *q; datum key; datum value; struct stat Sb; BOOL More; char buff[BUFSIZ]; char Name[SPOOLNAMEBUFF]; /* Open history. */ if (dbminit(History) < 0) { (void)fprintf(stderr, "Can't open history database, %s\n", strerror(errno)); exit(1); } if ((F = fopen(History, "r")) == NULL) { (void)fprintf(stderr, "Can't open \"%s\", %s\n", History, strerror(errno)); exit(1); } while (fgets(buff, sizeof buff, stdin) != NULL) { for (p = buff; ISWHITE(*p); p++) continue; if (*p != '<') continue; for (q = p; *q && *q != '>' && !ISWHITE(*q); q++) continue; if (*q != '>') continue; *++q = '\0'; key.dptr = p; key.dsize = q - key.dptr + 1; value = dbzfetch(key); /* Ihave -- say if we want it, and continue. */ if (What == 'i') { if (value.dptr == NULL) (void)printf("%s\n", p); continue; } /* Sendme -- print a filename for the message. */ if (value.dptr == NULL) /* Doesn't exist. */ continue; if (HistorySeek(F, value.dptr)) while (GetName(F, Name, &More)) { if (stat(Name, &Sb) >= 0) { (void)printf("%s\n", Name); break; } if (!More) break; } } } /* ** Print a usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage: grephistory [flags] MessageID\n"); exit(1); } int main(ac, av) int ac; char *av[]; { register int i; register char *p; register FILE *F; STRING History; datum key; datum value; struct stat Sb; BOOL More; char What; char Name[SPOOLNAMEBUFF]; /* Set defaults. */ History = _PATH_HISTORY; What = '?'; /* Parse JCL. */ while ((i = getopt(ac, av, "f:eiltnqs")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'f': History = optarg; break; case 'e': case 'i': case 'l': case 't': case 'n': case 'q': case 's': if (What != '?') { (void)fprintf(stderr, "Only one [eiltnqs] flag allowed.\n"); exit(1); } What = (char)i; break; } ac -= optind; av += optind; /* Set operating mode. */ switch (What) { case '?': What = 'n'; break; case 'i': case 's': IhaveSendme(History, What); exit(0); /* NOTREACHED */ } /* All modes other than -i -l want a Message-ID. */ if (ac != 1) Usage(); /* Open the history file, do the lookup. */ if (dbminit(History) < 0) { (void)fprintf(stderr, "Can't open history database, %s\n", strerror(errno)); exit(1); } key.dptr = av[0]; if (*key.dptr != '<') { /* Add optional braces. */ key.dptr = NEW(char, 1 + strlen(av[0]) + 1 + 1); (void)sprintf(key.dptr, "<%s>", av[0]); } for (p = key.dptr; *p; p++) if (*p == HIS_FIELDSEP || *p == '\n') *p = HIS_BADCHAR; key.dsize = p - key.dptr + 1; value = dbzfetch(key); /* Not found. */ if (value.dptr == NULL) { if (What == 'n') (void)fprintf(stderr, "Not found.\n"); exit(1); } /* Simple case? */ if (What == 'q') exit(0); /* Just give offset into history file */ if (What == 't') { (void)printf("%lu\n", *(long *) value.dptr); exit(0); } /* Open the text file, go to the entry. */ if ((F = fopen(History, "r")) == NULL) { (void)fprintf(stderr, "Can't open \"%s\", %s\n", History, strerror(errno)); exit(1); } if (What == 'l') { FullLine(F, value.dptr); exit(0); } /* Loop until we find an existing file. */ if (HistorySeek(F, value.dptr)) while (GetName(F, Name, &More)) { if (stat(Name, &Sb) >= 0) { (void)printf("%s\n", Name); exit(0); } if (!More) break; } if (What == 'n') (void)printf("/dev/null\n"); exit(0); /* NOTREACHED */ } inn-1.7.2/expire/expire.pch0100644000175100001440000000614006443103542014114 0ustar mdusers$Revision: 1.7 $ Matthias Urlichs, . July 8 This patch to C News expire.c (6Jul91 patchdate) teaches expire to interact with innd. You will also need to add "lib/inndcomm.o" to your libcnews.a ****WARNING**** If you install this patch, make sure that your doexpire script does NOT call updatemin or upact! *** expire.c.orig Tue Jul 9 15:57:21 1991 --- expire.c Wed Jul 10 16:26:26 1991 *************** *** 6,11 **** --- 6,16 ---- * is arbitrarily hard when control files get complex, to hell with it. */ + /* + * Extended by Matthias Urlichs (urlichs@smurf.sub.org) to talk to innd. + */ + #define INND + #include #include #include *************** *** 240,246 **** --- 245,256 ---- (void) umask(newsumask()); doit(); /* side effect: newslock() */ + #ifdef INND + if(nlocked && ICCgo("expiring") < 0) + fail("ctlinnd go failed", ""); + #else newsunlock(); + #endif if (latest > time((time_t *)NULL)) { complain("some article arrival dates are in the future!", ""); *************** *** 471,476 **** --- 481,490 ---- if (dbzagain("history.n", "history") < 0) fail("dbzagain(history.n) failed", ""); } + #ifdef INND + if (ICCopen() < 0) + fail("ICCopen() failed", ""); + #endif cd(artfile((char *)NULL)); while ((line = readline(old)) != NULL) { *************** *** 713,718 **** --- 733,746 ---- p = strchr(p+1, '.')) *p = '/'; expire(name, dir); + #ifdef INND + if(!nlocked && nleft == 0 && srcc == '\0') { + if(expdebug) + fprintf(stderr,"Cancelling %s '%s'\n", + name,msgid); + ICCcancel(msgid); + } + #endif if (dir != NULL && printexpiring) printstuff(msgid, name, recdate); nexpired++; *************** *** 729,735 **** if (nleft == 0) return(NULL); *dst++ = '\0'; ! if (leaders && nleft == 1 && nexpired > 0) /* aging leader */ return(doarticle(oldnames, recdate, expdate, msgid)); return(oldnames); } --- 757,767 ---- if (nleft == 0) return(NULL); *dst++ = '\0'; ! if ( ! #ifndef INND ! leaders && ! #endif ! nleft == 1 && nexpired > 0) /* aging leader */ return(doarticle(oldnames, recdate, expdate, msgid)); return(oldnames); } *************** *** 1174,1181 **** --- 1206,1218 ---- (void) unlink("history.n.dir"); (void) unlink("history.n.pag"); } + #ifdef INND + (void) ICCclose(); + #endif errno = saveerr; + #ifndef INND errunlock(s1, s2); + #endif /* NOTREACHED */ } *************** *** 1265,1270 **** --- 1302,1311 ---- /* EOF. */ if (nlocked) return; /* We're really done. */ + #ifdef INND + if (!rebuild) /* save the rest for next time */ + return; + #endif /* EOF but we haven't locked yet. Lock and try again. */ (void) signal(SIGINT, SIG_IGN); *************** *** 1271,1277 **** --- 1312,1323 ---- (void) signal(SIGQUIT, SIG_IGN); (void) signal(SIGHUP, SIG_IGN); (void) signal(SIGTERM, SIG_IGN); + #ifdef INND + if (ICCpause("expiring") < 0) + fail("ctlinnd pause failed!", ""); + #else newslock(); + #endif nlocked = 1; refill(fd); } inn-1.7.2/expire/makeactive.c0100644000175100001440000001342706443103542014407 0ustar mdusers/* $Revision: 1.10 $ ** ** Build an active file from either an old copy or by calling find ** to get the directory names. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #include "paths.h" #include "libinn.h" #include "mydir.h" #include "macros.h" STATIC char ACTIVE[] = _PATH_ACTIVE; /* ** Given an newsgroup name, write the active file entry. */ STATIC BOOL MakeEntry(name, rest, oldhimark, oldlomark, ComputeMarks) char *name; char *rest; long oldhimark; long oldlomark; BOOL ComputeMarks; { register long himark; register long lomark; register DIR *dp; register DIRENTRY *ep; register long j; register char *p; /* Turn group name into directory name. */ for (p = name; *p; p++) if (*p == '.') *p = '/'; /* Set initial hi and lo marks. */ if (ComputeMarks) { himark = 0; lomark = 0; } else { himark = oldhimark; lomark = oldlomark; } if ((dp = opendir(name)) != NULL) { /* Scan through all entries in the directory. */ while ((ep = readdir(dp)) != NULL) { p = ep->d_name; if (!CTYPE(isdigit, p[0]) || strspn(p, "0123456789") != strlen(p) || (j = atol(p)) == 0) continue; if (lomark == 0 || j < lomark) lomark = j; if (j > himark) himark = j; } (void)closedir(dp); } if (lomark == 0 || lomark - 1 > himark) lomark = himark + 1; /* Reset marks if computed them and didn't find any articles. */ if (ComputeMarks && lomark == 1 && himark == 0) { himark = oldhimark; lomark = oldlomark; } /* Turn the directory name back into a newsgroup name. */ for (p = name; *p; p++) if (*p == '/') *p = '.'; if (printf("%s %010ld %010ld %s\n", name, himark, lomark, rest) == EOF || fflush(stdout) == EOF || ferror(stdout)) { (void)fprintf(stderr, "Error writing %s entry, %s\n", name, strerror(errno)); return FALSE; } return TRUE; } /* ** See if a line is too long to be a newsgroup name, return TRUE if so. */ STATIC BOOL TooLong(buff, i) char *buff; int i; { register char *p; if ((p = strchr(buff, '\n')) == NULL) { (void)fprintf(stderr, "Line %d is too long: \"%.40s\"...\n", i, buff); return TRUE; } *p = '\0'; if (p - buff > SMBUF) { (void)fprintf(stderr, "Group line %d is too long: \"%.40s\"...\n", i, buff); return TRUE; } return FALSE; } /* ** Renumber the active file based on the old active file. */ STATIC BOOL RebuildFromOld(ComputeMarks) BOOL ComputeMarks; { register FILE *F; register char *p; register int i; register BOOL Ok; char buff[BUFSIZ]; STRING rest; long lomark; long himark; char *save1; char *save2; /* Open the file. */ if ((F = fopen(ACTIVE, "r")) == NULL) { (void)fprintf(stderr, "Can't open \"%s\", %s\n", ACTIVE, strerror(errno)); exit(1); } /* Process each entry. */ for (i = 1, Ok = TRUE; fgets(buff, sizeof buff, F) != NULL; i++) { if (TooLong(buff, i)) { Ok = FALSE; continue; } /* Set default fields. */ lomark = 0; himark = 0; rest = "y"; /* Try to parse the other fields. */ if ((p = strchr(buff, ' ')) != NULL) { *p++ = '\0'; save1 = p; if ((p = strchr(p, ' ')) != NULL) { *p++ = '\0'; save2 = p; if ((p = strchr(p, ' ')) != NULL) { *p++ = '\0'; rest = p; lomark = atol(save2); himark = atol(save1); } } } if (!MakeEntry(buff, rest, himark, lomark, ComputeMarks)) { Ok = FALSE; break; } } (void)fclose(F); return Ok; } STATIC BOOL RebuildFromFind() { register int i; register char *p; register FILE *F; register BOOL Ok; char buff[BUFSIZ]; /* Start getting a list of the directories. */ #if defined(DO_HAVE_SYMLINK) F = popen("exec find . -follow -type d -print", "r"); #else F = popen("exec find . -type d -print", "r"); #endif /* defined(DO_HAVE_SYMLINK) */ if (F == NULL) { (void)fprintf(stderr, "Can't start find, %s\n", strerror(errno)); exit(1); } /* Loop over all input. */ for (i = 1, Ok = TRUE; fgets(buff, sizeof buff, F) != NULL; i++) { if (TooLong(buff, i)) { Ok = FALSE; continue; } /* Skip leading "./" and some known-to-be-bad directories. */ p = buff[0] == '.' && buff[1] == '/' ? &buff[2] : buff; if (EQ(p, "lost+found") || strchr(p, '.') != NULL) continue; if (!MakeEntry(p, "y", 0L, 0L, FALSE)) { Ok = FALSE; break; } } /* Clean up. */ i = pclose(F) >> 8; if (i) { (void)fprintf(stderr, "Find exited with status %d\n", i); Ok = FALSE; } return Ok; } /* ** Print a usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage: makeactive [-o [-m] ] >output\n"); exit(1); /* NOTREACHED */ } int main(ac, av) int ac; char *av[]; { BOOL Ok; register int i; BOOL OldFile; BOOL ComputeMarks; /* Set defaults. */ OldFile = FALSE; ComputeMarks = FALSE; (void)umask(NEWSUMASK); /* Parse JCL. */ while ((i = getopt(ac, av, "mo")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'm': ComputeMarks = TRUE; break; case 'o': OldFile = TRUE; break; } ac -= optind; av += optind; if (ac || (ComputeMarks && !OldFile)) Usage(); /* Go to where the articles are. */ if (chdir(_PATH_SPOOL) < 0) { (void)fprintf(stderr, "Can't change to spool directory, %s\n", strerror(errno)); exit(1); } if (OldFile) Ok = RebuildFromOld(ComputeMarks); else Ok = RebuildFromFind(); if (fflush(stdout) || ferror(stdout)) { (void)fprintf(stderr, "Can't flush stdout, %s\n", strerror(errno)); Ok = FALSE; } exit(Ok ? 0 : 1); /* NOTREACHED */ } inn-1.7.2/expire/expireover.c0100644000175100001440000006454406443103542014474 0ustar mdusers/* $Revision: 1.11 $ ** ** Expire overview database. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #include #include #include "qio.h" #include "mydir.h" #include "libinn.h" #include "macros.h" #include "paths.h" #define START_LIST_SIZE 128 /* ** Information about a line in the overview file. */ typedef struct _LINE { ARTNUM Article; char *Start; int Length; int Offset; } LINE; /* ** A list of articles; re-uses space. */ typedef struct _LIST { int Used; int Size; ARTNUM *Articles; } LIST; /* ** A buffer; re-uses space. */ typedef struct _BUFFER { int Used; int Size; char *Data; } BUFFER; /* ** Information about the schema of the news overview files. */ typedef struct _ARTOVERFIELD { char *Header; int Length; BOOL HasHeader; } ARTOVERFIELD; /* ** Append an article to an LIST. */ #define LISTappend(L, a) \ if ((L).Size == (L).Used) { \ (L).Size *= 2; \ RENEW((L).Articles, ARTNUM, (L).Size); \ (L).Articles[(L).Used++] = (a); \ } \ else \ (L).Articles[(L).Used++] = (a) /* ** Global variables. */ STATIC char SPOOL[] = _PATH_SPOOL; STATIC char *SCHEMA = _PATH_SCHEMA; STATIC BOOL InSpoolDir; STATIC BOOL Verbose; STATIC BOOL DoNothing; STATIC ARTOVERFIELD *ARTfields; STATIC int ARTfieldsize; /* ** Sorting predicate for qsort to put articles in numeric order. */ STATIC int LISTcompare(p1, p2) CPOINTER p1; CPOINTER p2; { ARTNUM *ip1; ARTNUM *ip2; ip1 = CAST(ARTNUM*, p1); ip2 = CAST(ARTNUM*, p2); return *ip1 - *ip2; } /* ** If list is big enough, and out of order, sort it. */ STATIC void LISTsort(lp) LIST *lp; { register int i; register ARTNUM *ap; for (ap = lp->Articles, i = lp->Used - 1; --i >= 0; ap++) if (ap[0] >= ap[1]) { qsort((POINTER)lp->Articles, (SIZE_T)lp->Used, sizeof lp->Articles[0], LISTcompare); break; } } /* ** Unlock the group. */ STATIC void UnlockGroup(lfd, lockfile) int lfd; char *lockfile; { if (lfd > 0) { if (unlink(lockfile) < 0 && errno != ENOENT) (void)fprintf(stderr, "expireover cant unlink %s %s\n", lockfile, strerror(errno)); if (close(lfd) < 0) (void)fprintf(stderr, "expireover cant close %s %s\n", lockfile, strerror(errno)); lfd = -1; } } /* ** Sorting predicate to put lines in numeric order. */ STATIC int LINEcompare(p1, p2) CPOINTER p1; CPOINTER p2; { LINE *lp1; LINE *lp2; lp1 = CAST(LINE*, p1); lp2 = CAST(LINE*, p2); return lp1->Article - lp2->Article; } /* ** Take in a sorted list of count article numbers in group, and delete ** them from the overview file. */ STATIC void RemoveLines(group, Deletes) char *group; LIST *Deletes; { static BUFFER B; static LINE *Lines; static int LineSize; register struct iovec *vp; register LINE *lp; register LINE *end; register char *p; register char *next; register ARTNUM *ap; register int i; struct stat Sb; struct iovec iov[8]; char file[SPOOLNAMEBUFF]; char lockfile[SPOOLNAMEBUFF]; int fd; int count; int lfd; if (Verbose) { for (ap = Deletes->Articles, i = Deletes->Used; --i >= 0; ap++) (void)printf("- %s/%ld\n", group, *ap); if (DoNothing) return; } /* Lock the group. */ (void)sprintf(lockfile, "%s/.LCK%s", group, _PATH_OVERVIEW); lfd = open(lockfile, O_WRONLY | O_TRUNC | O_CREAT, ARTFILE_MODE); if (lfd < 0) { (void)fprintf(stderr, "Can't open %s, %s\n", lockfile, strerror(errno)); return; } /* Open file, lock it. */ (void)sprintf(file, "%s/%s", group, _PATH_OVERVIEW); for ( ; ; ) { if ((fd = open(file, O_RDWR)) < 0) { (void)fprintf(stderr, "Can't open %s, %s\n", file, strerror(errno)); UnlockGroup(lfd, lockfile); return; } if (LockFile(fd, FALSE) >= 0) break; /* Wait for lock; close file -- might be unlinked -- and try again. */ (void)LockFile(fd, TRUE); (void)close(fd); } if (fstat(fd, &Sb) < 0) { (void)fprintf(stderr, "Can't open %s, %s\n", file, strerror(errno)); UnlockGroup(lfd, lockfile); (void)close(fd); return; } if (Sb.st_size == 0) { /* Empty file; done deleting. */ UnlockGroup(lfd, lockfile); (void)close(fd); return; } /* Read in the whole file. */ if (B.Size == 0) { B.Size = Sb.st_size + 1; B.Data = NEW(char, B.Size); } else if (B.Size <= Sb.st_size) { B.Size = Sb.st_size + 1; RENEW(B.Data, char, B.Size); } if (xread(fd, B.Data, Sb.st_size) < 0) { (void)fprintf(stderr, "Can't read %s, %s\n", file, strerror(errno)); UnlockGroup(lfd, lockfile); (void)close(fd); return; } B.Data[Sb.st_size] = '\0'; /* Count lines, get space. */ for (i = 1, p = B.Data; (p = strchr(p, '\n')) != NULL && *++p; i++) continue; if (LineSize == 0) { LineSize = i; Lines = NEW(LINE, LineSize + 1); } else if (LineSize < i) { LineSize = i; RENEW(Lines, LINE, LineSize + 1); } /* Build line array. */ for (lp = Lines, p = B.Data; ; p = next, lp++) { if ((next = strchr(p, '\n')) == NULL) break; lp->Start = p; lp->Length = ++next - p; lp->Article = atol(p); } qsort((POINTER)Lines, (SIZE_T)(lp - Lines), sizeof lp[0], LINEcompare); /* Remove duplicates. */ for (end = lp - 1, lp = Lines; lp < end; lp++) if (lp[0].Article == lp[1].Article) lp->Article = 0; /* Scan through lines, collecting clumps and skipping holes. */ ap = Deletes->Articles; count = Deletes->Used; iov[0].iov_len = 0; for (vp = iov, lp = Lines; lp < end + 1; lp++) { /* An already-removed article, or one that should be? */ if (lp->Article == 0) continue; /* Skip delete items before the current one. */ while (*ap < lp->Article && count > 0) { ap++; count--; } if (count > 0 && lp->Article == *ap) { while (*ap == lp->Article && count > 0) { ap++; count--; } continue; } /* We're keeping this entry; see if we can add it to any * in-progress iov element. */ if (vp->iov_len) { if (((char *) vp->iov_base) + vp->iov_len == lp->Start) { /* Contiguous. */ vp->iov_len += lp->Length; continue; } /* Doesn't fit -- get a new element. */ if (++vp == ENDOF(iov)) { if (xwritev(lfd, iov, SIZEOF(iov)) < 0) { (void)fprintf(stderr, "Can't write %s, %s\n", lockfile, strerror(errno)); UnlockGroup(lfd, lockfile); (void)close(fd); return; } vp = iov; } } /* Start new element. */ vp->iov_base = lp->Start; vp->iov_len = lp->Length; } /* Write out remaining. */ if (vp->iov_len) vp++; if (iov[0].iov_len && xwritev(lfd, iov, vp - iov) < 0) { (void)fprintf(stderr, "Can't write %s, %s\n", lockfile, strerror(errno)); UnlockGroup(lfd, lockfile); (void)close(fd); return; } if (rename(lockfile, file) < 0) (void)fprintf(stderr, "Can't rename %s, %s\n", lockfile, strerror(errno)); /* Don't call UnlockGroup; do it inline. */ if (close(lfd) < 0) (void)fprintf(stderr, "expireover cant close %s %s\n", file, strerror(errno)); if (close(fd) < 0) (void)fprintf(stderr, "expireover cant close unlinked %s %s\n", file, strerror(errno)); } /* ** Read the overview schema. */ static void ARTreadschema() { register FILE *F; register char *p; register ARTOVERFIELD *fp; register int i; char buff[SMBUF]; /* Open file, count lines. */ if ((F = fopen(SCHEMA, "r")) == NULL) { (void)fprintf(stderr, "Can't open %s, %s\n", SCHEMA, strerror(errno)); exit(1); } for (i = 0; fgets(buff, sizeof buff, F) != NULL; i++) continue; (void)fseek(F, (OFFSET_T)0, SEEK_SET); ARTfields = NEW(ARTOVERFIELD, i + 1); /* Parse each field. */ for (fp = ARTfields; fgets(buff, sizeof buff, F) != NULL; ) { /* Ignore blank and comment lines. */ if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; if ((p = strchr(buff, COMMENT_CHAR)) != NULL) *p = '\0'; if (buff[0] == '\0') continue; if ((p = strchr(buff, ':')) != NULL) { *p++ = '\0'; fp->HasHeader = EQ(p, "full"); } else fp->HasHeader = FALSE; fp->Header = COPY(buff); fp->Length = strlen(buff); fp++; } ARTfieldsize = fp - ARTfields; (void)fclose(F); } /* ** Read an article and create an overview line without the trailing ** newline. Returns pointer to static space or NULL on error. */ STATIC char * OVERgen(name) char *name; { static ARTOVERFIELD *Headers; static BUFFER B; register ARTOVERFIELD *fp; register ARTOVERFIELD *hp; register ARTOVERFIELD *lasthp = 0; register QIOSTATE *qp; register char *colon; register char *line; register char *p; register int i; register int size; register int ov_size; register long lines; struct stat Sb; long t; char value[10]; /* Open article. */ if ((qp = QIOopen(name, QIO_BUFFER)) == NULL) return NULL; if ((p = strrchr(name, '/')) != NULL) name = p + 1; /* Set up place to store headers. */ if (Headers == NULL) { Headers = NEW(ARTOVERFIELD, ARTfieldsize); for (hp = Headers, i = ARTfieldsize; --i >= 0; hp++) hp->Length = 0; } else { /* This disposes from the previous call. This simplifies handling later on. We trade off this readable code for the problem that nothing DISPOSEs() the last caller's use. mibsoft 8/22/97 */ for (hp = Headers, i = ARTfieldsize; --i >= 0; hp++) { if (hp->HasHeader) { DISPOSE(hp->Header); hp->Header = 0; } hp->Length = 0; } } for (hp = Headers, i = ARTfieldsize; --i >= 0; hp++) hp->HasHeader = FALSE; for ( ; ; ) { /* Read next line. */ if ((line = QIOread(qp)) == NULL) { if (QIOtoolong(qp)) continue; /* Error or EOF (in headers!?); shouldn't happen. */ QIOclose(qp); return NULL; } /* End of headers? */ if (*line == '\0') break; /* See if we want this header. */ fp = ARTfields; for (hp = Headers, i = ARTfieldsize; --i >= 0; hp++, fp++) { colon = &line[fp->Length]; if (*colon != ':') continue; *colon = '\0'; if (!caseEQ(line, fp->Header)) { *colon = ':'; continue; } *colon = ':'; if (fp->HasHeader) p = line; else /* Skip colon and whitespace, store value. */ for (p = colon; *++p && ISWHITE(*p); ) continue; size = strlen(p); hp->Length = size; hp->Header = NEW(char, hp->Length + 1); (void)strcpy(hp->Header, p); for (p = hp->Header; *p; p++) if (*p == '\t' || *p == '\n' || *p == '\r') *p = ' '; hp->HasHeader = TRUE; lasthp = hp; break ; /* the first one is used */ } /* handle multi-line headers -- kondou@uxd.fc.nec.co.jp */ if (i < 0) { if (lasthp && ISWHITE(*line)) { lasthp->Length += strlen(line); RENEW(lasthp->Header, char, lasthp->Length + 1); for (p = line; *p; p++) if (*p == '\t' || *p == '\n' || *p == '\r') *p = ' '; strcat(lasthp->Header, line); } else { lasthp = 0 ; } } } /* Read body of article, just to get lines. */ for (lines = 0; ; lines++) if ((p = QIOread(qp)) == NULL) { if (QIOtoolong(qp)) continue; if (QIOerror(qp)) { QIOclose(qp); return NULL; } break; } /* Calculate total size, fix hardwired headers. */ ov_size = strlen(name) + ARTfieldsize + 2; for (hp = Headers, fp = ARTfields, i = ARTfieldsize; --i >= 0; hp++, fp++) { if (caseEQ(fp->Header, "Bytes") || caseEQ(fp->Header, "Lines")) { if (fp->Header[0] == 'B' || fp->Header[0] == 'b') t = fstat(QIOfileno(qp), &Sb) >= 0 ? (long)Sb.st_size : 0L; else t = lines; (void)sprintf(value, "%ld", t); size = strlen(value); if (hp->Length == 0) { hp->Length = size; hp->Header = NEW(char, hp->Length + 1); } else if (hp->Length < size) { hp->Length = size; RENEW(hp->Header, char, hp->Length + 1); } (void)strcpy(hp->Header, value); hp->HasHeader = TRUE; } if (hp->HasHeader) ov_size += strlen(hp->Header); } /* Get space. */ if (B.Size == 0) { B.Size = ov_size; B.Data = NEW(char, B.Size + 1); } else if (B.Size < ov_size) { B.Size = ov_size; RENEW(B.Data, char, B.Size + 1); } /* Glue all the fields together. */ p = B.Data + strlen(strcpy(B.Data, name)); for (hp = Headers, i = ARTfieldsize; --i >= 0; hp++) { *p++ = '\t'; if (hp->HasHeader) p += strlen(strcpy(p, hp->Header)); } *p = '\0'; QIOclose(qp); return B.Data; } /* ** Take in a sorted list of count article numbers in group, and add ** them them to the overview file. */ STATIC void AddLines(group, Adds) char *group; LIST *Adds; { static BUFFER New; static BUFFER B; static LINE *Lines; static int LineSize; register LINE *lp; register char *next; register int i; register struct iovec *vp; register ARTNUM *ap; LINE *end; struct iovec iov[8]; struct stat Sb; char *p; char file[SPOOLNAMEBUFF]; char lockfile[SPOOLNAMEBUFF]; int LineUsed; int fd; int lfd; if (Verbose) { for (ap = Adds->Articles, i = Adds->Used; --i >= 0; ap++) (void)printf("+ %s/%ld\n", group, *ap); if (DoNothing) return; } /* Get space. */ if (New.Data == NULL) { New.Size = 1024; New.Data = NEW(char, New.Size); LineSize = Adds->Size + 1; Lines = NEW(LINE, LineSize); } else if (LineSize < Adds->Size) { LineSize = Adds->Size + 1; RENEW(Lines, LINE, LineSize); } New.Used = 0; for (lp = Lines, ap = Adds->Articles, i = Adds->Used; --i >= 0; ap++) { /* Get the overview data. */ if (InSpoolDir) (void)sprintf(file, "%s/%ld", group, *ap); else (void)sprintf(file, "%s/%s/%ld", SPOOL, group, *ap); if ((p = OVERgen(file)) == NULL) continue; /* Add it to the buffer and the lines array. */ lp->Article = *ap; lp->Length = strlen(p); lp->Offset = New.Used; while (New.Size < New.Used + lp->Length + 1) { New.Size *= 2; RENEW(New.Data, char, New.Size); } (void)strcpy(&New.Data[New.Used], p); New.Used += lp->Length++; New.Data[New.Used++] = '\n'; lp++; } LineUsed = lp - Lines; /* Turn offsets into real pointers. */ for (i = 0, lp = Lines; i < LineUsed; i++, lp++) lp->Start = New.Data + lp->Offset; /* Lock the group. */ (void)sprintf(lockfile, "%s/.LCK%s", group, _PATH_OVERVIEW); lfd = open(lockfile, O_WRONLY | O_TRUNC | O_CREAT, ARTFILE_MODE); if (lfd < 0) { (void)fprintf(stderr, "Can't open %s, %s\n", lockfile, strerror(errno)); return; } /* Open file, lock it. */ (void)sprintf(file, "%s/%s", group, _PATH_OVERVIEW); for ( ; ; ) { if ((fd = open(file, O_RDWR | O_CREAT, ARTFILE_MODE)) < 0) { (void)fprintf(stderr, "Can't open %s, %s\n", file, strerror(errno)); UnlockGroup(lfd, lockfile); return; } if (LockFile(fd, FALSE) >= 0) break; /* Wait for lock; close file -- might be unlinked -- and try again. */ (void)LockFile(fd, TRUE); (void)close(fd); } if (fstat(fd, &Sb) < 0) { (void)fprintf(stderr, "Can't open %s, %s\n", file, strerror(errno)); UnlockGroup(lfd, lockfile); (void)close(fd); return; } if (Sb.st_size != 0) { /* Read in the whole file. */ if (B.Size == 0) { B.Size = Sb.st_size + 1; B.Data = NEW(char, B.Size); } else if (B.Size < Sb.st_size) { B.Size = Sb.st_size + 1; RENEW(B.Data, char, B.Size); } if (xread(fd, B.Data, Sb.st_size) < 0) { (void)fprintf(stderr, "Can't read %s, %s\n", file, strerror(errno)); UnlockGroup(lfd, lockfile); (void)close(fd); return; } B.Data[Sb.st_size] = '\0'; /* Count lines, get space. */ for (i = 1, p = B.Data; (p = strchr(p, '\n')) != NULL && *++p; i++) continue; if (LineSize < i + 1 + LineUsed) { LineSize = i + 1 + LineUsed; RENEW(Lines, LINE, LineSize); } /* Add to lines array. */ for (lp = Lines + LineUsed, p = B.Data; ; p = next, lp++) { if ((next = strchr(p, '\n')) == NULL) break; lp->Start = p; lp->Length = ++next - p; lp->Article = atol(p); } qsort((POINTER)Lines, (SIZE_T)(lp - Lines), sizeof lp[0], LINEcompare); LineUsed = lp - Lines; } /* Remove duplicates. */ for (end = lp - 1, lp = Lines; lp < end; lp++) if (lp[0].Article == lp[1].Article) lp->Article = 0; /* Scan through lines, collecting rocks and holes. */ iov[0].iov_len = 0; for (vp = iov, lp = Lines; lp < end + 1; lp++) { /* An already-removed article, or one that should be? */ if (lp->Article == 0) continue; /* We're keeping this entry; see if we can add it to any in-progress * iov element. */ if (vp->iov_len) { if (((char *) vp->iov_base) + vp->iov_len == lp->Start) { /* Contiguous. */ vp->iov_len += lp->Length; continue; } /* Doesn't fit -- get a new element. */ if (++vp == ENDOF(iov)) { if (xwritev(lfd, iov, SIZEOF(iov)) < 0) { (void)fprintf(stderr, "Can't write %s, %s\n", lockfile, strerror(errno)); UnlockGroup(lfd, lockfile); (void)close(fd); return; } vp = iov; } } /* Start new element. */ vp->iov_base = lp->Start; vp->iov_len = lp->Length; } if (vp->iov_len) vp++; /* Write out remaining. */ if (iov[0].iov_len && xwritev(lfd, iov, vp - iov) < 0) { (void)fprintf(stderr, "Can't write %s, %s\n", lockfile, strerror(errno)); UnlockGroup(lfd, lockfile); (void)close(fd); return; } if (rename(lockfile, file) < 0) (void)fprintf(stderr, "Can't rename %s, %s\n", lockfile, strerror(errno)); /* Don't call UnlockGroup; do it inline. */ if (close(lfd) < 0) (void)fprintf(stderr, "expireover cant close %s %s\n", file, strerror(errno)); if (close(fd) < 0) (void)fprintf(stderr, "expireover cant close unlinked %s %s\n", file, strerror(errno)); } /* ** Expire by batch, or line at a time. */ STATIC void Expire(SortedInput, qp) BOOL SortedInput; register QIOSTATE *qp; { static LIST List; register char *line; register char *p; char group[SPOOLNAMEBUFF]; if (List.Articles == NULL) { List.Size = START_LIST_SIZE; List.Articles = NEW(ARTNUM, List.Size); } List.Used = 0; if (SortedInput) { for ( ; ; ) { if ((line = QIOread(qp)) == NULL) { if (QIOerror(qp)) { (void)fprintf(stderr, "Can't read input %s\n", strerror(errno)); break; } if (QIOtoolong(qp)) continue; break; } if ((p = strrchr(line, '/')) == NULL) continue; *p++ = '\0'; if (List.Used == 0) { (void)strcpy(group, line); List.Used = 0; } else if (!EQ(line, group)) { LISTsort(&List); RemoveLines(group, &List); (void)strcpy(group, line); List.Used = 0; } LISTappend(List, atol(p)); } /* Do the last group. */ if (List.Used) { LISTsort(&List); RemoveLines(group, &List); } } else { for (List.Used = 1; ; ) { if ((line = QIOread(qp)) == NULL) { if (QIOerror(qp)) { (void)fprintf(stderr, "Can't read input %s\n", strerror(errno)); break; } if (QIOtoolong(qp)) continue; break; } if ((p = strrchr(line, '/')) == NULL) continue; *p++ = '\0'; List.Articles[0] = atol(p); RemoveLines(line, &List); } } QIOclose(qp); } /* ** Read the overview file, return sorted list of all articles in it. */ STATIC LIST * GetOverviewList(group) char *group; { static LIST List; register QIOSTATE *qp; register char *p; char file[SPOOLNAMEBUFF]; /* Open the file. */ (void)sprintf(file, "%s/%s", group, _PATH_OVERVIEW); if ((qp = QIOopen(file, QIO_BUFFER)) == NULL) return NULL; /* Setup the article list. */ if (List.Articles == NULL) { List.Size = START_LIST_SIZE; List.Articles = NEW(ARTNUM, List.Size); } List.Used = 0; /* Read all lines, picking up the article number. */ for ( ; ; ) { if ((p = QIOread(qp)) == NULL) { if (QIOerror(qp)) { (void)fprintf(stderr, "Can't read %s, %s\n", file, strerror(errno)); QIOclose(qp); return NULL; } if (QIOtoolong(qp)) continue; break; } LISTappend(List, atol(p)); } QIOclose(qp); if (List.Used == 0) return NULL; LISTsort(&List); return &List; } /* ** Read spool directory and return sorted list of articles or NULL on error. */ STATIC LIST * GetSpoolList(group) char *group; { static LIST List; register DIR *dp; register DIRENTRY *ep; register char *p; char buff[SPOOLNAMEBUFF]; /* Open directory. */ if (InSpoolDir) (void)strcpy(buff, group); else (void)sprintf(buff, "%s/%s", SPOOL, group); if ((dp = opendir(buff)) == NULL) return NULL; /* Setup article list. */ if (List.Articles == NULL) { List.Size = START_LIST_SIZE; List.Articles = NEW(ARTNUM, List.Size); } List.Used = 0; /* Get all articles. */ while ((ep = readdir(dp)) != NULL) { p = ep->d_name; if (!CTYPE(isdigit, p[0]) || strspn(p, "0123456789") != strlen(p)) continue; LISTappend(List, atol(p)); } (void)closedir(dp); if (List.Used == 0) return NULL; LISTsort(&List); return &List; } /* ** Return a list of all articles in the Over list that are not in ** the Spool list. Both lists are sorted. See SpoolUpdate for an ** explanation of the names. */ STATIC LIST * GetNotIn(Over, Spool) register LIST *Over; register LIST *Spool; { static LIST List; register ARTNUM *oEnd; register ARTNUM *sEnd; register ARTNUM *o; register ARTNUM *s; /* Setup the list. */ if (List.Articles == NULL) { List.Size = START_LIST_SIZE; List.Articles = NEW(ARTNUM, List.Size); } List.Used = 0; o = Over->Articles; s = Spool->Articles; oEnd = o + Over->Used; sEnd = s + Spool->Used; while (o != oEnd && s != sEnd) { if (*o < *s) { LISTappend(List, *o++); continue; } if (*o == *s) o++; s++; } /* If we hit the end of the Spool, then add everything else in the * Overview. */ if (s == sEnd) { while (o != oEnd) LISTappend(List, *o++); } return List.Used ? &List : NULL; } /* ** Try to make one directory. Return FALSE on error. */ STATIC BOOL MakeDir(Name) char *Name; { struct stat Sb; if (mkdir(Name, GROUPDIR_MODE) >= 0) return TRUE; /* See if it failed because it already exists. */ return stat(Name, &Sb) >= 0 && S_ISDIR(Sb.st_mode); } /* ** Given a directory, comp/foo/bar, create that directory and all ** intermediate directories needed. Return FALSE on error. */ static BOOL MakeOverDir(Name) register char *Name; { register char *p; BOOL made; /* Optimize common case -- parent almost always exists. */ if (MakeDir(Name)) return TRUE; /* Try to make each of comp and comp/foo in turn. */ for (p = Name; *p; p++) if (*p == '/') { *p = '\0'; made = MakeDir(Name); *p = '/'; if (!made) return FALSE; } return MakeDir(Name); } /* ** Update using the News Spool. Either add or delete entries. */ STATIC void SpoolUpdate(AddEntries, Name) BOOL AddEntries; char *Name; { register QIOSTATE *qp; register char *line; register char *p; LIST *Over; LIST *Spool; LIST *Missing; /* Open file. */ if (EQ(Name, "-")) qp = QIOfdopen(STDIN, QIO_BUFFER); else if ((qp = QIOopen(Name, QIO_BUFFER)) == NULL) { (void)fprintf(stderr, "Can't open %s, %s\n", Name, strerror(errno)); exit(1); } if (AddEntries) ARTreadschema(); for ( ; ; ) { if ((line = QIOread(qp)) == NULL) { if (QIOtoolong(qp) || QIOerror(qp)) { (void)fprintf(stderr, "Line too long or error reading %s, %s\n", Name, strerror(errno)); exit(1); } break; } /* Nip off newsgroup name, and turn it into a directory. */ for (p = line; *p && !ISWHITE(*p) && *p != '\n'; p++) if (*p == '.') *p = '/'; *p = '\0'; Spool = GetSpoolList(line); Over = GetOverviewList(line); if (AddEntries && (Spool != NULL)) { if (Over != NULL) { if ((Missing = GetNotIn(Spool, Over)) != NULL) AddLines(line, Missing); } else if (!InSpoolDir) { if (MakeOverDir(line)) AddLines(line, Spool); else (void)fprintf(stderr, "expireover: cant mkdir %s, %s\n", line, strerror(errno)); } else AddLines(line, Spool); } if (Over == NULL) continue; if (Spool != NULL) { if ((Missing = GetNotIn(Over, Spool)) != NULL) RemoveLines(line, Missing); } else RemoveLines(line, Over); } QIOclose(qp); exit(0); } /* ** Print usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage: expireover [flags] [file...]\n"); exit(1); } int main(ac, av) int ac; char *av[]; { register int i; QIOSTATE *qp; BOOL AddEntries; BOOL ReadSpool; BOOL SortedInput; char *Dir; char *Name; /* Set defaults. */ Dir = _PATH_OVERVIEWDIR; Name = _PATH_ACTIVE; AddEntries = FALSE; ReadSpool = FALSE; SortedInput = FALSE; (void)umask(NEWSUMASK); /* Parse JCL. */ while ((i = getopt(ac, av, "aD:f:nO:svz")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'a': AddEntries = TRUE; ReadSpool = TRUE; break; case 'D': Dir = optarg; break; case 'f': Name = optarg; break; case 'n': DoNothing = TRUE; break; case 'O': SCHEMA = optarg; break; case 's': ReadSpool = TRUE; break; case 'v': Verbose = TRUE; break; case 'z': SortedInput = TRUE; break; } ac -= optind; av += optind; if ((ReadSpool && ac) || (AddEntries && !ReadSpool)) Usage(); /* Setup. */ if (chdir(Dir) < 0) { (void)fprintf(stderr, "Cant chdir to %s, %s\n", Dir, strerror(errno)); exit(1); } InSpoolDir = EQ(Dir, SPOOL); /* Do work. */ if (ReadSpool) SpoolUpdate(AddEntries, Name); if (ac == 0) Expire(SortedInput, QIOfdopen(STDIN, QIO_BUFFER)); else { for ( ; *av; av++) if (EQ(*av, "-")) Expire(SortedInput, QIOfdopen(STDIN, QIO_BUFFER)); else if ((qp = QIOopen(*av, QIO_BUFFER)) == NULL) (void)fprintf(stderr, "Can't open %s, %s\n", *av, strerror(errno)); else Expire(SortedInput, qp); } exit(0); /* NOTREACHED */ } inn-1.7.2/expire/Makefile0100644000175100001440000001702606443103542013571 0ustar mdusers## $Revision: 1.20 $ SHELL = /bin/sh MAKE = make DESTDIR = D = $(DESTDIR) ## =()

@>()= P = ## =()@>()= CC = gcc ## =()@>()= DEFS = -I../include ## =()@>()= CFLAGS = $(DEFS) -g ## =()@>()= LDFLAGS = ## =()@>()= LINTFLAGS = -b -h -z $(DEFS) ## =()@>()= LINTFILTER = | sed -n -f ../sedf.sun ## =()@>()= CTAGS = ctags -t -w ## =()@>()= PROF = -pg ## =()@>()= NEWSBIN = /usr/news/bin ## =()@ -G @@>()= OWNER = -O news -G news ## =()@>()= LIBS = -lutil LIBNEWS = ../libinn.a LINTLIB = ../llib-linn.ln SOURCES = convdate.c expire.c expireover.c fastrm.c grephistory.c \ makeactive.c makehistory.c newsrequeue.c prunehistory.c ALL = convdate expire expireover fastrm grephistory \ makeactive makehistory newsrequeue prunehistory all: $(ALL) install: $D$(NEWSBIN)/convdate $D$(NEWSBIN)/expire \ $D$(NEWSBIN)/expireover $D$(NEWSBIN)/fastrm \ $D$(NEWSBIN)/grephistory $D$(NEWSBIN)/makeactive \ $D$(NEWSBIN)/makehistory $D$(NEWSBIN)/newsrequeue \ $D$(NEWSBIN)/prunehistory clobber clean: rm -f *.o $(ALL) rm -f expirep expireoverp profiled rm -f all install lint tags ctags: $(SOURCES) $(CTAGS) $(SOURCES) ../lib/*.c ../include/*.h convdate: $(P) convdate.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ convdate.o $(LIBNEWS) $(LIBS) expire: $(P) expire.o dbz.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ expire.o dbz.o $(LIBNEWS) $(LIBS) expireover: $(P) expireover.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ expireover.o $(LIBNEWS) $(LIBS) fastrm: $(P) fastrm.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ fastrm.o $(LIBNEWS) $(LIBS) grephistory: $(P) grephistory.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ grephistory.o $(LIBNEWS) $(LIBS) makeactive: $(P) makeactive.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ makeactive.o $(LIBNEWS) $(LIBS) makehistory: $(P) makehistory.o dbz.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ makehistory.o dbz.o $(LIBNEWS) $(LIBS) newsrequeue: $(P) newsrequeue.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ newsrequeue.o $(LIBNEWS) $(LIBS) prunehistory: $(P) prunehistory.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ prunehistory.o $(LIBNEWS) $(LIBS) lint: $(ALL) @rm -f lint -lint $(LINTFLAGS) convdate.c $(LINTLIB) $(LINTFILTER) >lint -lint $(LINTFLAGS) expire.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) expireover.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) fastrm.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) grephistory.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) makeactive.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) makehistory.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) newsrequeue.c $(LINTLIB) $(LINTFILTER) >>lint -lint $(LINTFLAGS) prunehistory.c $(LINTLIB) $(LINTFILTER) >>lint # Build our own version of dbz.o for expire and makehistory, to avoid # any -DMMAP in DBZCFLAGS - using mmap() for dbz in expire can slow it # down really bad, and has no benefits as it pertains to the *new* .pag. dbz.o: ../lib/dbz.c $(CC) $(CFLAGS) -c ../lib/dbz.c ../include/dbz.h: (cd ../lib ; $(MAKE) ../include/dbz.h) $(LIBNEWS) $(LINTLIB): (cd ../lib ; $(MAKE) install) ## Profiling. The rules are a bit brute-force, but good enough. profiled: expirep expireoverp date >$@ NEWFLAGS = CFLAGS="$(CFLAGS) $(PROF)" LDFLAGS="$(LDFLAGS) $(PROF)" expirep: expire.c rm -f expire.o $(MAKE) expire $(NEWFLAGS) LIBNEWS=../libinn_p.a mv expire expirep rm -f expire.o expireoverp: expireover.c rm -f expireover.o $(MAKE) expireover $(NEWFLAGS) LIBNEWS=../libinn_p.a mv expireover expireoverp rm -f expireover.o ## .SUFFIXES: .c .src .c.src: #load $(CFLAGS) $< ## Low-level install actions. $D$(NEWSBIN)/convdate: convdate $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/expire: expire $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/expireover: expireover $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/fastrm: fastrm $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/grephistory: grephistory $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/makeactive: makeactive $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/makehistory: makehistory $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/newsrequeue: newsrequeue $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ $D$(NEWSBIN)/prunehistory: prunehistory $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ ## Dependencies. Default list, below, is probably good enough. depend: Makefile $(SOURCES) makedepend $(DEFS) $(SOURCES) # DO NOT DELETE THIS LINE -- make depend depends on it. convdate.o: ../include/clibrary.h convdate.o: ../include/configdata.h convdate.o: ../include/configdata.h convdate.o: ../include/libinn.h convdate.o: ../include/macros.h convdate.o: ../include/macros.h expire.o: ../include/clibrary.h expire.o: ../include/configdata.h expire.o: ../include/configdata.h expire.o: ../include/dbz.h expire.o: ../include/inndcomm.h expire.o: ../include/libinn.h expire.o: ../include/libinn.h expire.o: ../include/macros.h expire.o: ../include/paths.h expire.o: ../include/qio.h expire.o: ../include/qio.h expireover.o: ../include/clibrary.h expireover.o: ../include/configdata.h expireover.o: ../include/configdata.h expireover.o: ../include/libinn.h expireover.o: ../include/macros.h expireover.o: ../include/mydir.h expireover.o: ../include/mydir.h expireover.o: ../include/paths.h expireover.o: ../include/paths.h expireover.o: ../include/qio.h fastrm.o: ../include/clibrary.h fastrm.o: ../include/configdata.h fastrm.o: ../include/configdata.h fastrm.o: ../include/libinn.h fastrm.o: ../include/macros.h fastrm.o: ../include/macros.h fastrm.o: ../include/mydir.h grephistory.o: ../include/clibrary.h grephistory.o: ../include/configdata.h grephistory.o: ../include/configdata.h grephistory.o: ../include/dbz.h grephistory.o: ../include/libinn.h grephistory.o: ../include/macros.h grephistory.o: ../include/macros.h grephistory.o: ../include/paths.h grephistory.o: ../include/paths.h makeactive.o: ../include/clibrary.h makeactive.o: ../include/configdata.h makeactive.o: ../include/configdata.h makeactive.o: ../include/libinn.h makeactive.o: ../include/macros.h makeactive.o: ../include/macros.h makeactive.o: ../include/mydir.h makeactive.o: ../include/paths.h makeactive.o: ../include/paths.h makehistory.o: ../include/clibrary.h makehistory.o: ../include/configdata.h makehistory.o: ../include/configdata.h makehistory.o: ../include/dbz.h makehistory.o: ../include/dbz.h makehistory.o: ../include/inndcomm.h makehistory.o: ../include/libinn.h makehistory.o: ../include/macros.h makehistory.o: ../include/mydir.h makehistory.o: ../include/mydir.h makehistory.o: ../include/paths.h makehistory.o: ../include/paths.h makehistory.o: ../include/qio.h newsrequeue.o: ../include/clibrary.h newsrequeue.o: ../include/configdata.h newsrequeue.o: ../include/configdata.h newsrequeue.o: ../include/dbz.h newsrequeue.o: ../include/libinn.h newsrequeue.o: ../include/macros.h newsrequeue.o: ../include/paths.h newsrequeue.o: ../include/paths.h newsrequeue.o: ../include/qio.h newsrequeue.o: ../include/qio.h prunehistory.o: ../include/clibrary.h prunehistory.o: ../include/configdata.h prunehistory.o: ../include/configdata.h prunehistory.o: ../include/dbz.h prunehistory.o: ../include/libinn.h prunehistory.o: ../include/macros.h prunehistory.o: ../include/macros.h prunehistory.o: ../include/paths.h prunehistory.o: ../include/paths.h inn-1.7.2/MakeInews0100755000175100001440000000654106443103542012446 0ustar mdusers#! /bin/sh ## $Revision: 1.10 $ ## Script to build an easy-to-ship single directory that contains ## everything needed to build inews on a machine. ## Optional first argument is the destination architecture, like "sun4" DIR=inews.${1-dist} if [ -d ${DIR} ] ; then echo ${DIR} exists! exit 1 fi mkdir ${DIR} ## Copy the files. for I in \ config/subst.c config/subst.sh config/config.data \ doc/distrib.pats.5 doc/inews.1 doc/inn.conf.5 \ doc/moderators.5 \ frontends/inews.c \ include/clibrary.h include/configdata.h include/libinn.h \ include/macros.h include/mystring.h include/mymemory.h \ include/nntp.h include/paths.h \ lib/cleanfrom.c lib/clientactive.c lib/defdist.c lib/genid.c \ lib/getconfig.c lib/parsedate.y lib/getfqdn.c lib/getmodaddr.c \ lib/gettime.c lib/localopen.c lib/radix32.c lib/readin.c \ lib/remopen.c lib/sendarticle.c lib/sendpass.c lib/strerror.c \ lib/wildmat.c lib/xfopena.c lib/xmemerr.c lib/xmalloc.c lib/xrealloc.c \ site/distrib.pats site/inn.conf site/moderators site/passwd.nntp ; do \ cp $I ${DIR} done ## Write the Makefile. We duplicate the RCS revision string of the ## script into the Makefile on purpose. cat <<\EOF >${DIR}/Makefile ## $Revision: 1.10 $ SHELL = /bin/sh MAKE = make ## Configuration dependencies -- edit as appropriate DEFS = CFLAGS = $(DEFS) -g LDFLAGS = -Bstatic LINTFLAGS=-b -h $(DEFS) ## Manual pages -- install as appropriate for your system DOC = distrib.pats.5 inews.1 moderators.5 inn.conf.5 ## Configuration files -- install in /usr/lib/news CONF = distrib.pats inn.conf moderators passwd.nntp ## Program sources. HEADERS = \ clibrary.h configdata.h libinn.h macros.h nntp.h paths.h SOURCES = \ cleanfrom.c clientactive.c defdist.c genid.c getconfig.c getfqdn.c \ getmodaddr.c gettime.c localopen.c parsedate.c radix32.c readin.c \ remopen.c sendarticle.c sendpass.c strerror.c wildmat.c xfopena.c \ xmalloc.c xmemerr.c xrealloc.c OBJECTS = \ cleanfrom.o clientactive.o defdist.o genid.o getconfig.o getfqdn.o \ getmodaddr.o gettime.o localopen.o parsedate.o radix32.o readin.o \ remopen.o sendarticle.o sendpass.o strerror.o wildmat.o xfopena.o \ xmalloc.o xmemerr.o xrealloc.o ## First target, just compile everything. all: inews $(DOC) $(CONF) date >all ## Edit these lines as appropriate for your system install: all cp inews /usr/lib/news/inews cp $(CONF) /usr/lib/news cp inews.1 /usr/man/man1 cp moderators.5 /usr/man/man5 cp inn.conf.5 /usr/man/man5 ## Clean up, remove non-essentials. clobber clean: rm -f inews core tags lint a.out *.o rm -f parsedate.c lint: inews lint $(LINTFLAGS) inews.c $(SOURCES) >lint inews: inews.o $(OBJECTS) rm -f inews $(CC) $(LDFLAGS) -o inews $(CFLAGS) inews.o $(OBJECTS) parsedate.c: parsedate.y @echo Expect 6 shift/reduce conflicts $(YACC) parsedate.y @mv y.tab.c parsedate.c subst: subst.c subst.sh make c || make sh || { rm -f subst ; echo Failed 1>&2 ; } config: subst config.data $(DOC) $(HEADERS) Makefile ./subst -f config.data $(DOC) $(HEADERS) Makefile date >config c: @rm -f subst $(CC) -o subst subst.c sh: @rm -f subst cp subst.sh subst chmod +x subst ## Dependencies. Default list, below, is probably good enough. depend: Makefile $(SOURCES) makedepend $(DEFS) $(SOURCES) # DO NOT DELETE THIS LINE -- make depend depends on it. $(OBJECTS): $(HEADERS) inews.o: $(HEADERS) EOF inn-1.7.2/FAQ/0040755000175100001440000000000006443103542011241 5ustar mdusersinn-1.7.2/FAQ/INN-faq_part40100644000175100001440000014563406443103542013501 0ustar mdusersNewsgroups: news.software.nntp,news.software.b,news.answers Approved: hwr@pilhuhn.de Subject: INN FAQ Part 4/9: Debugging & Configuring Information Followup-To: news.software.nntp Summary: This article is part 4 of a multi-part FAQ: Part 4: Read this AFTER you've read and followed the directions in Install.ms. This includes a tutorial on debugging posting/access problems. Posted-By: post_faq 2.10 Archive-name: usenet/software/inn-faq/part4 Last Changed: $Date: 1997/08/26 01:26:21 $ $Revision: 2.19 $ Part 4 of 9 INN FAQ Part 1: General and questions from people that don't (yet) run INN INN FAQ Part 2: Specific notes for specific operating systems INN FAQ Part 3: Reasons why INN isn't starting INN FAQ Part 4: The debugging tutorial (setup of feeds etc.) INN FAQ Part 5: Other error messages and what they mean INN FAQ Part 6: Day-to-day operation and changes to the system INN FAQ Part 7: Problems with INN already running INN FAQ Part 8: Appendix A: Norman's install guide INN FAQ Part 9: Appendix B: Configurations for certain systems ------------------------------ Subject: Table Of Contents for Part 4/9 ===================================================================== TABLE OF CONTENTS FOR PART 4/9: Debugging Guide & Tutorial ===================================================================== THE DEBUGGING TUTORIAL: 4.1 Should I read the Install.ms file in its entirety before reading this document? 4.2 Terminology used in the rest of this document. 4.3 How does it all fit together? 4.4 What should I monitor as I debug INN problems? 4.5 My innd won't start! 4.6 Connecting to a TCP/IP server. 4.7 Make sure that "feeders" can connect. 4.8 Make sure that "readers" can connect. 4.9 Make sure that clients can post. 4.10 "client" doesn't have the software needed to post. 4.11 Introduction to the "newsfeeds" file 4.12 The ME line in the newsfeeds file. 4.13 How does the "ME" line interact with the other lines? 4.14 Cookbook example of an outgoing NNTP feed. 4.15 Cookbook example of an outgoing UUCP feed. 4.16 Cookbook example of an outgoing UUCP-over-TCP feed. 4.17 Testing an outgoing feed (your "newsfeeds" configuration). 4.18 Other cron jobs. 4.19 Cookbook example of setting up NOV ("overchan"). 4.20 How do I use nntplink with INN? 4.21 How do I use innfeed with INN ? 4.22 How do I gate news to mail and/or mail to news? 4.23 Should I distribute control messages? ===================================================================== THE DEBUGGING TUTORIAL (or, What do I do after Install.ms?) ===================================================================== ------------------------------ Subject: (4.1) Should I read the Install.ms file in its entirety before reading this document? YES! Install.ms tells you how to compile and install the software. This document walks you through debugging the *configuration* of the software once it is installed. This document takes you from where install.ms leaves off, gives you a quick overview of how all the pieces fit together, and then takes you through specific debugging tasks. Debugging INN problems is often difficult because one needs to be an experienced netnews person to do it well. You can only get experience by having a properly running system. This is a catch-22. This tutorial attempts to take you through the basics. The rest you'll figure out. Newsgroups you should know exist: news:news.software.nntp -- INN questions go here. news:news.software.b -- Discussions about any of the many software packages that support the "B news" format (i.e. INN, C news, ANU-NEWS, etc.) This document also takes you through the process of verifying that your system is properly configured. When you are done, you should: 1. be sure that when feeders connect they are treated as feeders. 2. be sure that when clients connect they are treated as clients. 3. be sure that posting works. 4. be sure that your out-bound feeds are properly configured. ------------------------------ Subject: (4.2) Terminology used in the rest of this document. We will pretend that your machine is named "nntphost" or "nntphost.do.main" and that there is a client named "client" or "client.do.main". Some machines connect to you to try to feed you new articles. We'll call these machines "feeders". Some machines try to connect to you to read and/or post articles. We'll call these machines "readers". ------------------------------ Subject: (4.3) How does it all fit together? Here is a fantastic overview of the workings of INN. From: Ken Hornstein I discovered that the biggest problem I had with INN was understanding how everything fits together (since I had no experience with B or C news). Here's a (hopefully) simple description of how everything fits together: After running rc.news (as "root"), you should have the "innd" daemon running ("ps" will show the process to be owned by "news"). This is the Master Daemon. It handles incoming connections, stores the articles on your disk, but does _not_ send any articles out itself. It directs other programs to do that. Exactly where articles are sent and how they are sent is determined by the "newsfeeds" file. Setting up your newsfeeds file will be the hardest part of configuring INN. Here are some example entries from my newsfeeds file: ra/ra.nrl.navy.mil\ :*,!psu.*/!psu\ :Tf,Wnm: Looks complicated? It isn't. Here's what it means: "ra" is the name of the feed. "/ra.nrl.navy.mil" is an alias for ra. This is important because INN uses the "Path" header to insure the articles are not sent to sites where they have already been. Thus, any article that has "ra" or "ra.nrl.navy.mil" in the Path header will NOT be sent to this site. We know that no other site inserts "ra.nrl.navy.mil" because it is a FQDN (Fully Qualified Domain Name). We know that no other site inserts "ra" because it is registered in the UUCP Maps. (Ok, "ra" isn't registered so I'm just taking a small gamble.) The second line tells what articles will be sent out to this site. "*,!psu.*" means that articles for (all newsgroups minus those that match "psu.*") will be sent to ra. The details of the pattern matching is found in the wildmat(3) man page. The "/!psu" means that articles with a "Distribution" header of psu will also not be sent to ra. The last field specifies exactly what _kind_ of feeds. "Tf" means this is a file feed. Unless you have unusual requirements, all of your feeds will be file feeds. "Wnm" means that the relative path name and the Message-ID of the article will be written to this file. The "n" means "relative path name", the "m" means "Message-ID of the article". The newsfeeds(5) man page explains all the letters you can use with "W". By default, the output file is called the same name as your feed file, and is in your out.going directory. So on my system, every article destined to ra will have its filename and Message-ID written to the file "/var/spool/news/out.going/ra". So how do the articles actually GET to ra? You run a program that reads the feeds file and transmits the article. Two such programs are included with INN -- "send-nntp" and "nntpsend". My personal preference is for nntpsend. If you are going to use nntpsend, you will need to add a similar line to your nntpsend.ctl file: ra:ra.nrl.navy.mil This tells nntpsend that articles in the feed file "ra" should be sent to the site "ra.nrl.navy.mil". I run nntpsend out of cron every 10 minutes with this line: (in "news"'s cron) 0,10,20,30,40,50 * * * * /usr/local/news/bin/nntpsend Or, if you use an old-style cron (like Ultrix does): 0,10,20,30,40,50 * * * * /bin/su news -c '/usr/local/news/bin/nntpsend' UUCP feeds work similarly and are described in a different section. As each article comes in (note that hosts feeding you _must_ be listed in the hosts.nntp file), innd will examine it and distribute to your listed feeds based on the above-described selection criteria. Another important thing to do is to make sure your articles get expired. This is done from the "news.daily" script. The "expire.ctl" file describes how long you want each article to last. Here are some sample lines from my expire.ctl: /remember/:14 This line tells expire to keep history entries for articles at least 14 days. *:A:1:7:21 This is the default line. This says that by default, an article is kept a minimum of one day, the default expiration time is 7 days (this applies if there is no "Expires" header), and the very maximum that the article is kept is 21 days. psu.*:A:1:14:28 This line applies to groups only in Penn State. By default, those articles will last 14 days, 28 days at the most. Note that lines in expire.ctl should have the most general entries first, with the most specific entries last. Lastly, where do newsreaders fit in? When a newsreader connects to the innd process, it sees that this is not a feeder (the hosts.nntp file lists only sitest that feed YOU) so it forks a nnrpd process and hands the connection to it. This way innd can concentrate on newsfeeds. Some newsreaders don't open a connection, but instead read the articles out of "/usr/spool/news" (and gets meta data from "/usr/lib/news"). INN doesn't need to do anything about those readers except to make sure the right data is where they expect it. ------------------------------ Subject: (4.4) What should I monitor as I debug INN problems? 1. run "tail -f /var/adm/messages" to see if any syslog messages are being generated. 2. run "tail -f /var/log/news/news.err" to see if any fatal errors happen. 3. Check for incoming email constantly (especially when trying to post from "nn"). ------------------------------ Subject: (4.5) My innd won't start! Keep a "tail -f /var/adm/messages" running. INN reports most errors via syslog. The syslog messages usually explain what is wrong. Elsewhere in this document are details about some of the less obvious syslog messages. Chances are, INN is starting, finding a misconfigured "ME" line in the newsfeeds file, and exiting. You might want to read the section on configuring your "newsfeeds" file first. Rich Salz says a common reason is that you ran makehistory but didn't rename the DBZ files. "makehistory" generates history.n.dir and history.n.pag. They must be renamed: mv history.n.dir history.dir mv history.n.pag history.pag (In the future, you could run "makehistory -f history", which is a little more risky... so read the man page before you use it. "makehistory" is part of the man page "news-recovery". This will change in 1.5.) Izar Tarandach suggests that another common mistake is that innd wasn't being started by the correct uid. innd (and therefore rc.news) must be started from "root" (not "news"). It immediately turns itself in user "news" once certain tasks are completed. If you use a suid root inndstart, you can run it as any user. ------------------------------ Subject: (4.6) Connecting to a TCP/IP server. You know that "telnet"'ing to a machine lets you log into it. You are actually connecting on the "telnet" port (port 23). Many TCP/IP services allow you to "telnet" into their port and talk directly to them. Try "telnet nntphost 21". This means log into port #21 (the "ftp" port) instead of the usual remote login port. Once you are in, you'll get no prompt. Type "help" and press RETURN. You should get a list of commands. If you know what the commands are, you can talk to this server. Type "quit" and press RETURN to get out. After every command you should get some kind of status message. Each line will begin with a number. Each message has a unique number. Errors are defined as anything that starts with a number >= 400. Positive (non-error) messages are <400. SMTP (mail) and NNTP (netnews) work the same way. Telnet into their port and issue commands and data. "quit" always gets you out. We'll use this to debug INN configurations by "telnet"'ing into the innd server and seeing the raw error messages it gives us. Try "telnet"'ing into the NNTP port (#119) of a working NNTP server to see what it's like. ------------------------------ Subject: (4.7) Make sure that "feeders" can connect. "feeders" are listed in hosts.nntp. "readers" are listed in nnrp.access. This section deals with "feeders" and hosts.nntp. When a machine connects to the NNTP port of nntphost, it connects to the innd process. innd knows the internet address of the machine that is making this connection, and sees if it matches the internet addresses many of the machines listed in the hosts.nntp file. If the machine is not listed in hosts.nntp, it is assumed that this machine is not a "feeder" and forks off a nnrpd to handle this connection as a "reader". If you didn't know that, you didn't read enough of the INN installation documentation. Go back and read it now. Read the man page hosts.nntp to get a complete understanding of what's going on. nnrpd uses its own authentication scheme, which is described in the next section. Since I know you didn't read that man page, I'll give you one more chance to read it now. Let's configure hosts.nntp. Just enter the names of all the machines that feed you: feeder1.do.main: feeder2.do.main: I don't use passwords yet. If you do, add them after the ":". (See also #4.14) Now let's test to see if the feeder can connect properly. Log into to the feeder and "telnet nntphost 119". If you can't log into a feeder, configure your own machine as a feeder (i.e. feeder to itself) for testing purposes. Once you can see that INN is treating that machine as a feeder you can replace the machine's name with the name of a real feed. If you are given an error message and booted out, check the error message to see what's wrong. Maybe the machine is running maintenance at the time and you have to try again later. Maybe the machine doesn't recognize you at all and you have to edit "hosts.nntp" (and don't forget the "ctlinnd reload hosts.nntp" command!). Run "inncheck" to tell you if you have made any obvious mistakes. If your "history" file or other files have the wrong ownership or protections INN will mention the offending file in the error message. Another common mistake is that people try to use wildcards in hosts.nntp (which is not supported). Remember, there are very few machines that you consider to be "feeders", so you don't want to use a wildcard. To test a "feeder": If "feeder1" can send an "ihave" command and get a "335" as a response, you know that "nntphost" is permitting "feeder1" to transfer news as a "feeder". "ihave" requires an operand. I usually type "ihave <1@test>" and press RETURN. "<1@test>" is a Message-ID that I know doesn't exist. If I get "500 What?" I know that innd assumed that I'm a "reader" (so I have to edit my "hosts.nntp" file and add this client). If I get "335" and then a blank prompt, then INN is expecting to be fed an article. I usually just "^]" (control-]) and "quit" out; I know that it was willing to accept the article. If I get some other error message, it usually gives me enough information to debug the problem. ------------------------------ Subject: (4.8) Make sure that "readers" can connect. As I wrote before, if a connection comes from a machine that isn't listed in the hosts.nntp file, it is assumed to be a "reader". A "feeder" can also issue the "mode reader" command to become a "reader". If you have "telnet"'ed in as a "feeder", try issuing this command. Note: If a site is going to feed *and* read, you'll have to link readers with innd's client library. The reason for this is that the clients must tell innd that they want to read using the "mode reader" command. The library does that automagically. It is rare that you have a machine that is a reader and a feeder (since people will want to read on their local machine, not yours.) News readers are now being packaged as "INN ready" so this will be less and less of a problem. Once the connection has been handed off to nnrpd, nnrpd checks to make sure you are authorized. It does that by reading the nnrp.access file. There is a problem with what you enter in that file. Namely, I might call the client machine "client", but that doesn't matter. What matters is what "nntphost" thinks "client" is called. Maybe "nntphost" thinks its name is "client.do.main" or even "137.202.177.3". It doesn't matter what *you* call "client", permissions in the nnrp.access file have to be specified based on what "nntphost" calls "client". Technically, nnrpd uses gethostbyaddr() to reverse-lookup the name. gethostbyaddr() uses DNS or, if you are on a brain-dead Sun running Sun's NIS/DNS hack, it uses NIS, or DNS, or whatever the hell Sun was thinking when they created that cruft. To find out what "nntphost" thinks your machine is called, do the following: Telnet from "client" to "nntphost" and execute the "finger" command (just "finger" alone on the command line). The last column is what "nntphost" thinks your machine is called. If you don't have an account on both machines things are more difficult, consult your NIS or DNS expert to tell you what the answer would be. There is one exception to this technique. If you are using SunOS and braindead NIS you get just the machine name (like "milk") instead of the FQDN (like "milk.warren.mentorg.com") then you must tack on a period then the domain of the machine. So, with this knowledge (what your nntphost thinks client's name is) and a copy of the man page, edit nnrp.access and add "nntphost"'s name for "client" to the file. Unlike hosts.nntp, nnrp.access can have wildcards (for example, "*.sjc.mentorg.com"). You'll want to include wildcards for all the domains that should be allowed to read/post. Here are some decent examples from my nnrp.access file: -------------------------------------- Tom's nnrp.access file START ## Default is no access, no way to authentication, and no groups. *:: -no- : -no- :!* *.mentorg.com:Read:::* *.mentor.com:Read:::* *.warren.mentorg.com:Read Post:::* -------------------------------------- Tom's nnrp.access file END The second field of "nnrp.access" is case sensitive. "read post" does not mean the same as "Read Post". If you know this already it's because you read the man page. Note: nnrpd will append the domain to a name that is not a FQDN. There is no need to try to find a wildcard that will match non-FQDN names (i.e. machines in your local NIS cluster). Previously this FAQ had reported that "*[^.]*" would match these short names but that was wrong (the wildcard matches everything, oi!). nnrpd turns non-FQDN's into FQDNs. After you change "nnrp.access" you don't have do "ctlinnd reload" since the file is read by each nnrpd as they start up. Now "nntphost" should be letting "client" read. Let's test this out: Log into to the reader and "telnet nntphost 119". To test a "reader": Give the "mode reader" command and see how it it goes. If it doesn't give an error, then nnrp.access is letting you through. To read an article (or just get the header) type "head <2@test>" and press RETURN. Again, "<2@test>" is a message-id that I know doesn't exist. If you are allowed to read at all, it will tell you that it can't find that article. You should try the command with an message-id that you know exists and make sure you see the article's header. If reading works you can skip to the next section. The rest of this section helps you debug reading problems. If "mode reader" gives an error (and rudely disconnects you) then you have a typo in nnrp.access OR you didn't issue the "ctlinnd reload" command correctly (or at all) OR nntphost thinks that "client" is called yet something else OR innd can't exec nnrpd for one reason or another -- see the syslog output or the innd.err log file. Check all of those things then go to the beginning of this section and start over. Note: Some telnet implementations are Real Stupid and disconnect you before showing the error message. You can also run nnrpd by hand if you have stdin:Read Post:::* in your nnrp.access file. Just run nnrpd and type interactively. This is useful for making sure it's compiled right. ------------------------------ Subject: (4.9) Make sure that clients can post. The "inews" command (usually in /usr/local/bin) takes a post from a user, adds any missing headers, appends the file "~/.signature" (see below), and possibly replaces any headers that are obviously forged. "inews" will also reject a message if the message is seriously botched. "inews -h" expects a post on stdin beginning with headers, then a blank line, then the body. "inews -h -D" doesn't post the message, but outputs what it would have posted. The minimum headers one can feed is "Newsgroups:" (which is plural) and "Subject:" (which is singular). The "~/.signature" handling has some specific rules: INN's inews exits with an error if ~/.signature is (1) more than 4 lines long, (2) exists, but is not readable, or (3) is longer than 4k chars. inews exits with an error (rather than silently reading only the first 4 lines) to avoid a flurry of posts asking, "Why did my .signature get cut off?" By the way, a header looks like "Header-Name: data". That is, after the header name there is exactly one colon then exactly one space. The space is a space, not a tab. Another picky detail is that list of newsgroups on the "Newsgroups:" line is a comma separated list, with no spaces. There are no spaces before the colon. If there is nothing after the colon or if there is only whitespace after the colon then that header will be removed by "inews". Sites that don't remove such "empty" headers have broken software. Get it? Got it? Good. Here's the test message I constantly use: ------------------------ cut here 8< inews -h -D Newsgroups: foo.test Subject: test of inn posting this is a test ------------------------ cut here 8< Exciting huh? You might also use the 'feedone' program in the frontends directory. Do "cd $inn/frontends ; make feedone" to get it built. To run it, do feedone -t -r /tmp/inews.input This will (-t) trace all I/O with the server and (-r) use a random message-id each time. If you want to test posting from a newsreading host (i.e., one that connects to nnrpd and uses the POST command) use the -p flag. If inews was able to get to the /usr/lib/news/inn.conf file (for defaults) you should get a nice post on your screen. If you don't, here are my suggestions: 1 -- You have an old inews from C news or B news laying around 2 -- inews will give you an error message saying what's wrong. You might want to look around the usual places to make sure that there are no old versions of "relaynews" or "inews". People trying to use the "inews" from C news will get a message about "can't open redirection" or similar. Make sure they are running the programs included with INN. There is something called "mini-inews" which should just take a post and send it to the nntp server. Delete that and replace it with INN's inews. INN's inews is mini-inews and regular inews, it is the ying and then yang of inewses. It is the one true inews. It is the one inews to end all inewses and all others are false idols. Note: False idol worshipper and heathen David Myers reports that mini-inews works fine. He stays with mini-inews... "because INN inews needs to access not only inn.conf, but moderators, too. Installing and maintaining these files in a ~1000 client, multiple administrative domain setup like ours is too much of a pain. Most (all?) of the work done by INN inews is done by in.nnrpd during posting, anyway." Kenji Rikitake reports: "Keep in mind that INN inews refers to many environment variables. Beware of _inherited_ variables especially when you do su to maintain your news server. I got trapped and wasted a day with NNTPSERVER. I tried to post to a local newsgroup, and inews kept refusing it and sending me 'no such newsgroups...' error message. I finally found out that inews was looking up a wrong server, _implicitly_ specified by 'setenv NNTPSERVER ...' in my .login script. It took a day to find such a subtle misconfiguration, after a whole recompilation of entire INN kit, active and history rebuilding, and all possible configuration checking. *sigh*" "inews -h" sometimes reports: 'Warning, can't connect to server' What server is it trying to connect to? Remember, inews uses the NNTPSERVER environmental variable and (if that isn't set) looks in /usr/lib/news/inn.conf. INN's inews sometimes prints the error: "Can't get list of newsgroups, No such file or directory.". inews called CAlistactive() to get a local copy of the active file. If it can't reach the active file you get this error. Look at your PATH_TEMPACTIVE and see if it makes sense; i.e., if it is a valid /tmp directory. "inews -h" sometimes reports: Can't send article to the server: 441 480 Transfer permission denied This means that you set HAVE_UNIX_DOMAIN to DONT and you don't have your news server in its own hosts.nntp file. (nnrpd gets a POST, connects to innd over a TCP socket and sends an IHAVE.) (thanks to Chris Jackson for pointing this out). Add your news server's name and "localhost" to hosts.nntp and do "ctlinnd reload hosts.nntp". (For the reason why, read "Warnings to people that must set HAVE_UNIX_DOMAIN to DONT" in part2) Chuck Huber adds that this same error may be caused by setting REM_STYLE to NNTP in config.data, but not replacing INN's clientlib.o with the reference implementation's version. "inews -h" sometimes reports: Warning Text unavailable -- Article will be spooled. This means that inews could not connect to the server, but errno had nothing useful, and no reply came from the server. "It just didn't work." If it still doesn't work, look through your syslog to see the name of the host that innd got, and why it handed off to nnrpd. Perhaps there is a DNS/NIS/hosts-file mismatch. (suggested by Rich Salz) Other problems are usually the result of not being able to find the "inn.conf" file (copy it to the client or make it available via NFS) or you are using Sun's brain-dead NIS/DNS stuff which doesn't do reverse name lookups well. If inews tells you that it can't generate a Message-ID, ("441 Can't generate Message-ID, Resource temporary unavailable." or such ) this is because it can't figure out your domain (which is used in making the message-id string). Inews requires that gethostbyname returns FQDN and if doesn't then GetFQDN() fails. Force it to know your domain by adding a "domain:" line in "inn.conf". Solaris 2.x users will get a "can't generate message-id" error if they didn't follow the advice about getfqdn.c mentioned in another part of this FAQ (#2.14). If you get something like: 500 "GROUP"" not implemented; try "help". This implies that the client host is in hosts.nntp, not nnrp.access. However, if you need to have this machine in the hosts.nntp file (i.e. it is a feeder or you have an operating system that requires you to set HAVE_UNIX_DOMAIN to DONT) then your newsreader must send a "mode reader" to the server when it connects. Once you get "inews -h -D" working, do the same test without the "-D" option and let it actually post the message. If it can't post, it will tell you why. If the answer isn't clear enough, "telnet nntphost 119", give the "mode reader" command, then the "post" command. Enter lines of text like you would to "inews -h" and then type "." on a line by itself (and press RETURN). If posting via "telnet nntphost 119" DOES work and posting via "inews -h" DOES NOT work, you know that (1) "inews" is compiled wrong, or more likely, (2) you aren't using INN's inews. Either way, if this is happening you know you have narrowed your problems down to the inews program. By the way, posting to misc.test is pretty useless considering that the entire world doesn't need to see your message. Post to a local newsgroup or even a state-wide newsgroup like "nj.test" (assuming you are in New Jersey). There are lots of people that reply to every test message they see, so expect to get tons of stupid email. (though, if you don't get any email consider yourself lucky). Also, there is no newsgroup called "news.test" so don't post there. Many try, try fail. By the way, if you are one of those people that reply to every test message they see, get a real hobby. The convention is that replies are not sent to test messages with the word "IGNORE" in the Subject:. Do *NOT* post your test message to a non-test newsgroup. You will get many angry replies from all over the world. ...including the FAQ maintainer. Look at the posted message in the news spool (if you post a message to nj.test, "cd /var/spool/news/nj/test" and cat the highest numbered file you see). If your site name is listed multiple times in the "Path:" header, put your server's name on the "pathhost:" line of "inn.conf" and recompile INN with "INEWS_PATH" set to "DONT". (I don't know why Rich likes that as the default!) REMEMBER: inn.conf is read into innd only once. After it is changed, the innd daemon must be shutdown and restarted. (use "ctlinnd shutdown x" and then run rc.news as root). If "inews -h" posts a message, smile because most of the battle is over. ------------------------------ Subject: (4.10) "client" doesn't have the software needed to post. If the client doesn't have "inews" at all, copy it from the server (if they are compatible machines) or check the INN installation manual to find out how to compile just the client programs for a machine. There is a special gimmick included with INN to compile inews for the various other OS's and versions of Unix without having to compile the entire INN package. Since nnpost, Pnews, postnews, and all other news posting software shouldn't do anything but ask for header information, let you add a body, and then pipe the whole thing to "inews -h", you can be pretty certain that if "inews -h" works, your news posting programs will work. Think again! Post from each of them and make sure they all get posted. You might find that they access a copy of "inews" that was part of C news, mini-inews, or heavens knows what. I highly recommend that people use "find" or "gnufind" to seek out and replace all old versions of "inews" with symbolic links to the one "official". Something like: gnufind / /usr /usr/local /usr/lib -xdev -follow -name inews\* -print Then, for every file found, do the following: mv inews inews.cnews ln -s /usr/local/bin/inews inews Now you only have to update /usr/local/bin/inews, rather than chasing may copies. "nn" and "nnpost" create a file called "~/.nn/params" right before you post with tons of useful information. While posting you can shell out of the editor and view the file. The file is deleted after the message is posted. I had to view this file while shelled out of my editor to find which "inews" was being used by "nnpost". It's also a good idea to check your mail now and then while you are doing this. Some newsreaders (like "nn" notify you of a posting problem via mail. On non-INN systems, "inews" returns pretty quickly. Actually they fork a process to do the actual posting in the background. When those "inews" return, you don't know if the post was successful or not. These "inews"'s have a "-W" option which turns off this forking feature (i.e. Wait for the post to complete). INN's "inews" never forks because the wait is never that long. When "inews" returns you know if the post was successful or not. INN's "inews" accepts the "-W" option for compatibility. This may seem obvious, but when posting a test message, consider including the machine you are posting from and the program you are using. Even though you may check to see if the message got posted after every test, this will help you later when you go back to see what you have done. ------------------------------ Subject: (4.11) Introduction to the "newsfeeds" file Outgoing news is controlled by the "newsfeeds" file. The INN 1.2 man page for this file is a bit complex. The man page in 1.3 (and beyond) gives better examples. Here's a "cookbook" of examples that should cover most of your needs. Debugging tips are also included. Always remember that newsfeeds uses "wildmat" matches, not the semi-regular expressions that C news uses. This means that if you want to get comp.foo and the subgroups under it (comp.foo.bar, comp.foo.baz, etc.) you have to use a statement like: comp.foo,comp.foo.* OR comp.foo* BUT NOT comp.foo.* However, "comp.foo*" will match "comp.foobar", as well as "comp.foo.bang". ------------------------------ Subject: (4.12) The ME line in the newsfeeds file. The "ME" entry is a bit confusing. Be careful when you read the man page. Here is the "ME" line that I use in my "newsfeeds" file. I find it works quite well, but you might want to remove the distributions that you don't need (i.e. New Jersey). Since my site has clients reading from all over the world I try to have every distribution I can find. However, I hear of a new distribution almost daily so this list is always changing. ME:!*/\ news,gnu,comp,biz,alt,rec,misc,sci,soc,talk,inet,world,worldwide,all,\ aus,su,uk,york,eunet,na,can,qc,tor,us,usa,mn,oh,chi,ca,ba,tx,pnw,il,ne,\ ny,nyc,phl,bl,nj,warren:: If you want to blindly accept all distributions, try this: ME:!*:: See also the next subject on this. ------------------------------ Subject: (4.13) How does the "ME" line interact with the other lines? > I'm still a little confused about the ME line's second field. The man page as of INN 1.3 is much more clear on this. Basically, the second field of the "ME" line specifies the default for the rest of the feeds. Otherwise, it isn't used. The "active" file declares which newsgroups you accept and don't accept. Here are some examples: ME:!*::: foo:!junk:... --send no newsgroups ME:*::: foo:!junk:... --send all newsgroups except junk ME:!*::: foo:*,!junk:... --send all newsgroups except junk By the way, generally you do not want to send "junk" or "control*" to your neighbors. In unoff2 (and later unoffs) the ME line also can be used to reject articles which have certain sites in their path header. ------------------------------ Subject: (4.14) Cookbook example of an outgoing NNTP feed: This example involves a machine named oddball.mentorg.com, that has an alias of oddball.sjc.mentorg.com, which should receive all posts (but control & junk should never be passed on) and not certain distributions. Add the following line to newsfeeds: oddball.mentorg.com/oddball.sjc.mentorg.com:*,!control*,!junk/!local,!warren:Tf,Wnm: Have the user "news" run the following via cron: 3,23,43 * * * * /usr/lib/news/bin/nntpsend >/dev/null 2>&1 (this only needs to be added once. nntpsend refers to a file called nntpsend.ctl to find out what to do). Add the following to nntpsend.ctl: oddball.mentorg.com:oddball.mentorg.com:: Done! If you experience errors in the form "480 Transfer permission denied", then your remote site should double check its hosts.nntp file. Entries in hosts.nntp normally look like :[[:]], where pass and groups can be omitted. Now if the remote has an entry like the following: |host.do.main: | ^^^ note space instead of return then it expects you to send a password. If you don't, you get the above error. In this case, the remote should check its hosts.nntp, remove trailing spaces and do a ctlinnd reload hosts.nntp afterwards. See also #4.7 Another version for the "480 Transfer permission denied" problem is that the your host does not appear in the remotes hosts.nntp, but is matched by an entry in their nnrp.access. When you then send a ``ihave'' command, the remote gives you that error. ------------------------------ Subject: (4.15) Cookbook example of an outgoing UUCP feed: Example: A site named "plts" that can not get the "clari" newsgroups or distribution "warren". Add the following to the newsfeeds file: plts:*,!clari.*,!junk*,!control*/!warren:Tf,Wnb: Add the following to the cron tab (as user "news"): 0 0-5,16-23 * * 1-5 /usr/lib/news/bin/sendbatch -c plts >/dev/null 2>&1 NOTE: I know that "plts" is unique and won't conflict with some other site named "plts" because it is registered in the UUCP Maps (see comp.mail.maps). If your feeder is sending you netnews via UUCP (which is usually the case, since it isn't useful to just feed articles and not receive any) you must configure your UUCP to allow the remote system to execute rnews. Your UUCP documentation should tell you how to set up a UUCP connection and how to change the allowed commands. That means that uucico will execute /bin/rnews on every incoming batch. INN comes with a perfectly serviceable "rnews" program that can handle all the standard batched and compressed news formats. The INN rnews will uncompress and unbatch as necessary and then pass each article to innd for processing. (Thanks to Jerry Aguirre for this paragraph) ------------------------------ Subject: (4.16) Cookbook example of an outgoing UUCP-over-TCP feed: Jerry Aguirre writes: People ask about this like it was something exotic requiring special setup. Kind of like: "I know how to use a wheel barrow and I know how to shovel sand but how do I shovel sand in a wheel barrow?" Step 1: Set up a UUCP/TCP connection between you and the destination site. How? Read your UUCP documentation. If your machine's UUCP, and the destination machine's UUCP both supports UUCP/TCP then it will be documented. If not then get a better version of UUCP. For example, Taylor UUCP. Every OS sets up UUCP differently: YOU HAVE TO READ THE DOCUMENTATION. The point is to get the UUCP/TCP link working before even thinking about sending news over it. This is true of any news feed over UUCP; even dialup. Try using "uucp" to copy some scratch file to the other end. When you have that working then you are ready for the next step. The only "gotcha" here that I can think of is that the destination host may not be accepting UUCP/TCP connections. Before wasting your time trying to debug do a "telnet destination.host.name uucp" and see what happens. If the connection is accepted and you see a "login" banner then it is ready for you. If not then ask the admin of that site to enable UUCP/TCP. This is typically done by uncommenting it in /etc/inetd.conf and -HUPing inetd (on REAL versions of Unix). Step 2. Set up a standard compressed news feed to the UUCP name of the destination site. How? Read your news documentation. Setting up UUCP feeds is a standard, documented, procedure. In this FAQ you'll find it in "Cookbook example of an outgoing UUCP feed". Doing compression is nothing special, it's part of the procedure you would be doing anyway. It's either a flag or a slightly different command. The news system has NO knowledge that this is UUCP/TCP. For all it knows this is a standard dialup connection. In fact is is possible to have the UUCP connection fall back to dialup if the TCP connection fails. The news batching software just doesn't care. The only variation here I can think of is to make the batch size bigger than the default. The 50K default was picked back in the days when modems were 1200 BPS (or even 300). It is no longer appropriate for today's 9600 BPS or faster connections. Using a bigger batch size cuts down on dead time in the connection and lets compress do a better job. I would go to at least 200K batches. Now maybe it would be nice to have a "cookbook", step by step, set of instructions on how to do this. But UUCP seems to vary a bit between different versions so what might work at one place would be useless at another. And setting up the news feed is going to be different between the different versions of news (B, C, and INN). I suggest that if people are having trouble setting up a UUCP/TCP connection that they post their configuration to the net and ask how it is done on their versions of Unix and UUCP. ------------------------------ Subject: (4.17) Testing an outgoing feed (your "newsfeeds" configuration). Here is a decent game-plan for testing your newsfeeds configuration: Suppose your site is in New Jersey and you have a distribution called "mentorg" which should be used by people that want to make sure that their post will not leave their company (Mentor Graphics). You should do a test post to "nj.test" with no "Distribution:" header, and with "Distribution: nj" and "Distribution: mentorg". After posting, do a "ctlinnd flush ''" and make sure that the /var/spool/news/out.going files for all your sites did/didn't queue up those three messages as appropriate. IMPORTANT: Remember to do a "ctlinnd reload newsfeeds x" command every time you update your "newsfeeds" file! Finally, for checking out changes to newsfeeds, I've found "ctlinnd checkfile" handy. "inncheck" will verify that most of your configuration is sane. ------------------------------ Subject: (4.18) Other cron jobs. Once a night you should run the "news.daily" script which will expire old articles, run the daily reports, etc. It should run as "news" and look something like this: 40 23 * * * /usr/lib/news/bin/news.daily delayrm You should also have a line like this: 20 * * * * /bin/rnews -U This processes any batches or posts that came in while innd was down. (i.e. when users post and get a message like, "Server down, spooling locally" this command picks up those files and posts them). It can't hurt to run this more often, but once an hour should be fine. ------------------------------ Subject: (4.19) Cookbook example of setting up NOV ("overchan"). Now that you have your other feeds working, you might want to set up a NOV feed so that your NOV database is built. Newsreaders use the NOV database to speed up their queries. Christophe.Wolfhugel@grasp.insa-lyon.fr (Christophe Wolfhugel) (with many modifications from Tom Limoncelli and further input from davek@melita.com (Dave Kennedy) ) writes: Step 1: Upgrade to INN 1.4 or higher: Most of the bugs in 1.3 were related with overchan. In fact, the only reason why many people used 1.3 without any problems was due to the fact that they were not using overchan (and they didn't hit on some of the bugs that appeared for SVR4 users, all of which were fixed in 1.4) Step 1.5: Make sure _PATH_OVERVIEWDIR in config.data is NOT set to "/var/spool/news". There is a big performance boost to be realized by putting the NOV files outside the /var/spool/news hierarchy. To find out why, read "Subject: overchan can't keep up." in part 7 of this FAQ. You might want to read this anyway since it gives advice about other things to do to get better NOV performance. "/var/spool/news/over.view" is becoming the standard place to put your ".overview" files. If you do not use this location, make /var/spool/news/over.view a symbolic link to the correct place. For performance reasons, it is a good idea to set _PATH_OVERVIEWDIR to the actual location of the files. NB: if you change config.data, you must do a "make all" and "make install". It is not sufficient to just give the -D option to overchan and expireover, as nnrpd also needs to know where overview data is. If it doesn't, it won't complain nor use your overview data, but assume, there is none and generate it on the fly which is noticeable slower than using the database. Step 2: Make sure INN is working. Get everything else working before you try to get overchan to work. You'll only confuse yourself. Step 3: Ponder if you have enough disk space. NOV uses up an additional 10%-20% of your news spool. This is a good 100 Mb if you have a full feed. The real space savings come when you delete your separate databases for trn, nn, and tin and use one unified database. All serious newsreaders have NOV support. Step 4: Edit "overview.fmt" (it's in the $INN/site directory, or you can edit it where it was installed, in /usr/lib/news ) to include "Xref:full" as the last line. (i.e. uncomment out the last line). Step 5: Add this entry to your "newsfeeds" file. overchan gets it's data from a special feed. # This feeds header data to NOV: OVERVIEW!:*:Tc,WO:/usr/local/news/bin/overchan Read the "newsfeeds" man to make sure you understand what you've just done. Do a "ctlinnd checkfile" to make sure the newsfeeds file has the proper syntax, then do a "ctlinnd reload newsfeeds nov" to make it official. Step 6: If you changed your $inn/site files, then: % cd $inn/site % make install Step 7: Let innd know that files have been updated: % ctlinnd reload overview.fmt "Enabled XRef:" % ctlinnd reload newsfeeds "Added OVERVIEW - overchan entry" Step 8: You must run "expireover -s" at least once a month. Once a week is even better. This is necessary to remove overview data of for some reason or other left over entries. Here is a good crontab entry for "news" to run: 0 5 * * 1 /usr/lib/news/bin/expireover -s Step 9: (optional) To create the original database: (run this as "news") % /usr/local/news/bin/expireover -a This step will take a long time depending on the number of articles already in your system. But, if you skip this step, client access will be slow for articles that came in before you started "overchan". This is not a serious problem; you will get a lot of warnings in your "news.daily" output until you have received at least one new article in each newsgroup. Note: "a lot of warnings" means one for every newsgroup. This can make your news.daily report >6000 lines. The lines will all look like: overchan cant open clari/local/washington/.overview, No such file or directory overchan cant open clari/local/sfbay/.overview, No such file or directory overchan cant open uc/news/.overview, No such file or directory Step 9: Change the invocation of news.daily: In the crontab file for "news", edit the "news.daily" line to be something like: news.daily delayrm expireover (the expireover is required if you use overchan) Step 10: Inform your users that you now support "NOV, the News OverView database" and suggest that people switch to newsreaders that use newsreaders that are compliant with the Overview format. Step 11: You are done. Step 12: In a few weeks, drop support for mthreads, nnmaster, etc. (assuming you've upgraded to replacements that use NOV). Delete all those old databases that might have been maintained and enjoy the newly gained functionality and regained disk space! Step 13: If you are running tin (mostly the 1.2 versions) then you will get "bad overview" messages. These don't come from inn, but from tin. Solution edit the source (art.c) to increase the buffer size for overview information from 1024 bytes to at least 4096 bytes. ------------------------------ Subject: (4.20) How do I use nntplink with INN? First of all, I don't personally recommend using this program. I feel that it is a gimmick. However, if you decide to join the INN Instant Party, I suggest that you first run the feed using nntpsend (included with INN) FOR AT LEAST A WEEK. Once you are confident that functioning properly, consider to switching to nntplink ONLY IF: 0. You have read all documentation about innd and nntplink 1. You have more than 3 outgoing feeds. 2. You have gobs and gobs of real memory. 3. Your OS has a superior mmap() & disk IO system (like SunOS) If you decide to switch, here's a cookbook example of an newsfeeds entry using nntplink: PLEASE make sure traditional "nntpsend"-style feeds work reliably before you switch to nntplink. netcomsv.netcom.com\ :*,!junk/!ParcPlace\ :Tc,Wnm,S1024:/usr/local/news/bin/nntplink -i stdin netcomsv.netcom.com INN 1.2 users should have an explicit S value (i.e. S1024 or S16384). Without it innd 1.2 can choke and lose data if the receiver is jammed. (fixed in INN 1.3). The latest version of nntplink is available from ftp://ftp.math.ohio-state.edu/pub/nntplink/3.3pl2.tar.gz (3.3 is still in beta testing) Ian Phillipps notes some criteria for using nntplink rather than nnptsend: > (1) If you have more than one backbone feed, you can save a lot of > bandwidth, without risk, if you use nntplink (less duplication of > articles over nearly-parallel paths). > (2) More important, if you have a large number of feeds, nntplink > permits them to be fed simultaneously with the same articles. No big > deal, until you think of the what's going on in the pagedaemon and the > disk cache. > A "ps uaxr" rarely catches nntplink in the act ("D"), despite my having > 17 of them last time I counted. Our biggest outgoing newsfeed delivered > 16398 articles yesterday, using a total of 380 seconds CPU on a Sun > IPC, and no disk time :-) An additional note: when using nntplink in stdin mode it is fastest and can make use of the fact that the article might still be in disk buffers when it is to be transferred. But when the remote isn't able to keep up than innd buffers the information and gets bigger and bigger. If this happens - try using nntplink in logfile mode. ------------------------------ Subject: (4.21) How do I use innfeed with INN ? Innfeed is a new feeding tool by James Brister that is a combination of streaming nntp and nntplink with some other nice features. This tool is still in beta test. If you have already several nntplinks successful running, then you might to consider testing innfeed. Else stick on using nntpsend or send-nntp. Sources might be obtained via http://www.isc.org/isc/ ------------------------------ Subject: (4.22) How do I gate news to mail and/or mail to news? You might use newsgate. Rich Salz also turned over the maintenance for newsgate to ISC. So look out at http://www.isc.org/isc/ for a copy of it. Installation instructions (sample /usr/lib/news/newsfeeds and /etc/aliases entries are provided in the documentation for newsgate. But even if documentation tells you otherwise you should use rnews instead of inews with it. Also be careful not to produce loops! NB: newsgate includes mail2news and news2mail. ------------------------------ Subject: (4.23) Should I distribute control messages? |Newsgroups: news.software.nntp |Subject: Re: Pros & cons of passing control.* downstream? |References: <82rakz8r4p.fsf@dove.eecs.umich.edu> |From: David C Lawrence |Date: 09 Dec 1996 17:47:46 -0500 |Message-ID: <8682bxrl9.fsf@rodan.UU.NET> Michael Hucka writes: > The INN man pages say one would not normally want to send out control.* to > one's peer news servers. But what are the actual pros and cons of doing it? The con of doing it is that local control messages will propagate far and wide, creating groups at distant servers that were meant to be local. These groups will then attract articles that aren't really desired at the home site for the local groups. It will also look like a path for articles for the groups exist when in fact it doesn't, because non-control articles will not propagate down the same path. This all applies to other messages sites might have intended to keep local, notably including checkgroups. Cancels are largely irrelevant in this except by generating a lot of administrative traffic to cancel articles at the receiving site that it didn't get. The very weak pro for doing so is that a site with only a limited feed can see newgroup messages for groups it might want. However, admins can get this information via other mechanisms so I do not believe this pro outweighs the negatives of leaked local control messages. inn-1.7.2/FAQ/INN-faq_part90100644000175100001440000004616206443103542013502 0ustar mdusersNewsgroups: news.software.nntp,news.software.b,news.answers Approved: hwr@pilhuhn.de Subject: INN FAQ Part 9/9: Appendix B: Configurations for certain systems Followup-To: news.software.nntp Summary: This article is part 9 of a multi-part FAQ: Part 9: Configurations for certain systems Posted-By: post_faq 2.10 Archive-name: usenet/software/inn-faq/part9 Last Changed: $Date: 1997/09/23 01:25:57 $ $Revision: 2.17 $ Part 9 of 9 INN FAQ Part 1: General and questions from people that don't (yet) run INN INN FAQ Part 2: Specific notes for specific operating systems INN FAQ Part 3: Reasons why INN isn't starting INN FAQ Part 4: The debugging tutorial (setup of feeds etc.) INN FAQ Part 5: Other error messages and what they mean INN FAQ Part 6: Day-to-day operation and changes to the system INN FAQ Part 7: Problems with INN already running INN FAQ Part 8: Appendix A: Norman's install guide INN FAQ Part 9: Appendix B: Configurations for certain systems ------------------------------ Subject: Table Of Contents for Part 9/9 ===================================================================== TABLE OF CONTENTS for Part 9/9: Configurations for certain systems ===================================================================== 9.1 Comments for this part of the FAQ 9.2 NetBSD1.0/i386 9.3 Solaris 2.4 on x86 Hardware 9.4 Irix 5.[23] 9.5 DEC Alpha with OSF/1 v3.2 9.6 AIX 3.2.5 9.7 Linux (Versions >= 1.3.57) 9.8 BSD/OS 2.1 + sharedactive 9.9 HP-UX 10.01 9.10 Fujitsu DS/90 running UXP/DS(V20L10) 9.11 SunOS 4.1.x for INN 1.5 9.12 Pyramid Systems running DC/OSx 9.13 HP-UX 10.20 with HP gcc and INN1.5.1 9.14 Reliant Unix 5.43 C0024 on a MIPS RM300-C62 (Siemens Nixdorf) 9.15 UnixWare 2.1.x Note: See also part2 of the FAQ ------------------------------ Subject: (9.1) Comments for this part of the FAQ This part of the Faq is to provide some example configurations which worked at least for some sites. I want to collect more then what is below; this is just meant as a starting point. If you want to submit an entry put the following in: - Name and Email - a diff of config.data against config.dist leaving out changes to local paths (except where they are relevant for work i.e. path to egrep) Please send me diffs as you find them below, not entire config.data files. Please strip the diff to only include the changed lines (see the entries below to see what I mean). - the software environment it runs on (OS name and version, vendor patches to OS applied - compiler (version?) and compiling environment. - other changes you made Please see the entries below first to get the impression before you submit an entry. Send new entries to me (hwr@pilhuhn.de) and questions about specific configurations to the submitter of the entry. See also #1.20 and #1.8 ------------------------------ Subject: (9.2) NetBSD1.0/i386 ##FROM: Heiko W.Rupp ##DIFF: ++ config.data changes for NetBSD1.0 USE_CHAR_CONST DO OFFSET_T off_t SIZE_T size_t UID_T uid_t GID_T gid_t PID_T pid_t POINTER void HAVE_UNISTD DO HAVE_SETSID DO HAVE_WAITPID DO NOFILE_LIMIT 250 ABORTVAL void ALARMVAL unsigned int GETPIDVAL pid_t SLEEPVAL unsigned int QSORTVAL void LSEEKVAL off_t FREEVAL void _EXITVAL void MISSING_SRC MISSING_OBJ _PATH_SENDMAIL /usr/sbin/sendmail -t _PATH_EGREP /usr/bin/egrep _PATH_MAILCMD /usr/bin/Mail ##OS: NetBSD 1.0 on i486 hardware. The six very first kernel patches applied after 1.0 came out; will also run under 1.1 and probably later (1.2.1 tested). ##COMPILER: gcc 2.4.5 as supplied with NetBSD 1.0 ##MISC: ------------------------------ Subject: (9.3) Solaris 2.4 on x86 Hardware ##FROM: lev@keep.therealm.com (Lloyd Vancil) ##DIFF: DEFS -I../include -DSUNOS5 CC gcc USE_CHAR_CONST DO CFLAGS -O $(DEFS) LDFLAGS LIBS -lsocket -lnsl -lelf -lresolv LINTLIBSTYLE NONE LINTFLAGS LINTFILTER SIZE_T size_t UID_T uid_t GID_T gid_t PID_T pid_t POINTER void ALIGNPTR long LOCK_STYLE FCNTL HAVE_UNISTD DO HAVE_SETSID DO HAVE_TM_GMTOFF DONT HAVE_WAITPID DO USE_UNION_WAIT DONT HAVE_VFORK DONT BIND_USE_SIZEOF DONT CLX_STYLE FCNTL RES_STYLE TIMES FDCOUNT_STYLE SYSCONF CTYPE isXXXXX((c)) ABORTVAL void ALARMVAL unsigned GETPIDVAL pid_t SLEEPVAL unsigned LSEEKVAL off_t FREEVAL void _EXITVAL void MISSING_SRC MISSING_OBJ ACT_STYLE MMAP CHECK_INCLUDED_TEXT DONT INND_NICE_KIDS DO VERIFY_CANCELS DO LOG_CANCEL_COMMANDS DO DEFAULT_TIMEOUT 900 _PATH_COMPRESS /usr/bin/compress _PATH_EGREP /usr/local/bin/egrep _PATH_AWK /usr/local/bin/gawk _PATH_SED /usr/local/bin/sed _PATH_RNEWS /usr/local/bin/rnews _PATH_MAILCMD /usr/bin/mailx ##OS: Solaris 2.4 for x86, Jumbo Kernel Patch 101945-23, sol24-23.patch to solve setsockopt problems. ##COMPILER: gcc2.6.3 ##MISC: this config file assumes that the following GNU tools are available on the system: GCC,RANLIB,SED,GREP,GAWK The tm_gmtoff thing was unavailable for 2.4 - the includes on x86 2.4 MUST MUST include ucbinclude... ------------------------------ Subject: (9.4) Irix 5.[23] ##FROM: Robert Keller ##DIFF: USE_CHAR_CONST DO CFLAGS $(DEFS) -O2 -w LDFLAGS LIBS -lmld LINTLIBSTYLE NONE LINTFLAGS $(DEFS) LINTFILTER | sed -n -f ../sedf.sysv RANLIB echo VAR_STYLE STDARGS SIZE_T size_t UID_T uid_t GID_T gid_t PID_T pid_t POINTER void LOCK_STYLE FCNTL HAVE_UNISTD DO HAVE_SETSID DO HAVE_TM_GMTOFF DONT HAVE_ST_BLKSIZE DONT HAVE_WAITPID DO USE_UNION_WAIT DONT FORK fork HAVE_VFORK DONT CLX_STYLE FCNTL ABORTVAL void ALARMVAL uint GETPIDVAL pid_t SLEEPVAL uint QSORTVAL void LSEEKVAL off_t FREEVAL void _EXITVAL void MISSING_SRC MISSING_OBJ _PATH_EGREP /usr/bin/egrep _PATH_MAILCMD /usr/sbin/Mail ##OS: Irix 5.2 and Irix 5.3 ##COMPILER: Supplied ##MISC: ------------------------------ Subject: (9.5) DEC Alpha with OSF/1 v3.2 ##FROM: Chantelle Keller ##DIFF: CFLAGS $(DEFS) -g3 -O2 PROF -p LDFLAGS -g -O2 LINTLIBSTYLE SYSV LINTFLAGS -b -u -x -wkD $(DEFS) LINTFILTER | sed -n -f ../sedf.sysv SIZE_T unsigned long POINTER void USE_UNION_WAIT DONT ALARMVAL unsigned int SLEEPVAL unsigned int QSORTVAL void LSEEKVAL off_t FREEVAL void _EXITVAL void _PATH_COMPRESS /usr/bin/compress _PATH_EGREP /usr/bin/egrep _PATH_AWK /usr/bin/awk _PATH_SED /usr/bin/sed _PATH_MAILCMD /usr/bin/Mail ##OS: DEC Alpha with OSF/1 v3.2 ##COMPILER: standard Digital-supplied cc compiler ##MISC: I also had to make the following changes: - In innd/rc.c, lib/remopen.c, backends/rcompress.c, and include/clibrary.h, had to change all inet_addr references from "unsigned long" to "unsigned int". - In innd/rc.c, had to change "extern unsigned long htonl();" to "extern unsigned int htonl();" - In lib/makellib.sh, had to change "exec lint ${FLAGS} -u -v -x -o inn $* >/dev/null" to "exec lint ${FLAGS} -u -v -x -oinn $* >/dev/null" (i.e. remove space between "-o" and "inn") ------------------------------ Subject: (9.6) AIX 3.2.5 ##From: "Scott J. Ellentuch" ##DIFF: LIBS -lbsd LINTLIBSTYLE NONE LINTFLAGS -b -h -wkD $(DEFS) LINTFILTER | sed -n -f ../sedf.aix HAVE_TM_GMTOFF DONT USE_UNION_WAIT DONT NEED_TIME DO _PATH_EGREP /bin/egrep _PATH_AWK /bin/awk _PATH_SED /bin/sed ##OS: AIX 3.2.5 from IBM ##Compiler: xlc 1.3 ##MISC: See also Install.ms ------------------------------ Subject: (9.7) Linux (Versions >= 1.3.57) ##FROM: Gary E. Miller ##DIFF: CC gcc USE_CHAR_CONST DO CFLAGS $(DEFS) -O -fomit-frame-pointer PROF -p LDFLAGS -O LINTLIBSTYLE NONE LINTFLAGS LINTFILTER VAR_STYLE STDARGS SIZE_T size_t UID_T uid_t GID_T gid_t PID_T pid_t POINTER void SIGVAR sig_atomic_t HAVE_UNISTD DO HAVE_SETSID DO HAVE_TM_GMTOFF DONT HAVE_WAITPID DO USE_UNION_WAIT DONT HAVE_VFORK DONT BIND_USE_SIZEOF DONT CLX_STYLE FCNTL NBIO_STYLE IOCTL FDCOUNT_STYLE SYSCONF CTYPE isXXXXX((c)) ABORTVAL void ALARMVAL unsigned int GETPIDVAL pid_t SLEEPVAL unsigned int QSORTVAL void FREEVAL void _EXITVAL void MISSING_SRC MISSING_OBJ ACT_STYLE MMAP _PATH_EGREP /usr/bin/egrep _PATH_MAILCMD /bin/Mail ##OS: Linux V. >= 1.3.57 ##Compiler: gcc #MISC: You also need libc >=5.2.18. If you have older versions of Linux and/or libc, you have to turn off mmap() support. ------------------------------ Subject: (9.8) BSD/OS 2.1 + sharedactive ##FROM: Erik R. Leo ##DIFF: CC gcc2 CFLAGS $(DEFS) -O2 DBZCFLAGS $(CFLAGS) -DMMAP LDFLAGS -lipc MAN1 /usr/contrib/man/man1 MAN3 /usr/contrib/man/man3 MAN5 /usr/contrib/man/man5 MAN8 /usr/contrib/man/man8 NEWSMASTER news SIZE_T size_t UID_T uid_t GID_T gid_t PID_T pid_t POINTER void HAVE_UNISTD DO HAVE_SETSID DO HAVE_WAITPID DO HAVE_VFORK DONT ABORTVAL void ALARMVAL u_int GETPIDVAL pid_t SLEEPVAL unsigned QSORTVAL void LSEEKVAL off_t FREEVAL void _EXITVAL void MISSING_SRC MISSING_OBJ INND_NICE_KIDS DO INND_NICE_VALUE 4 _PATH_SENDMAIL /usr/sbin/sendmail -t _PATH_EGREP /usr/bin/egrep _PATH_MAILCMD /usr/bin/Mail _PATH_OVERVIEWDIR /var/spool/news/over.view ##OS: BSD/OS 2.1; P90 hardware; patches K210-001 thru K210-007, K210-revoke, U210-001 thru U210-005, U210-007 thru U210-015 ; K210-revoke seems to have been "released" as K210-008 (and K210-009, I think) ##COMPILER: gcc version 2.7.2 ##MISC: 256MB RAM (!); using kernel options: maxusers 256, DFLDSIZ="\(64*1024*1024\)", MAXDSIZ="\(128*1024*1024\)", CHILD_MAX="256", KMEMSIZE="\(16*1024*1024\)", DFLSSIZ="\(4*1024*1024\)" and NMBCLUSTERS="1024"; newest sharedactive patch applied (and modified with MAX_ACTIVE_SIZE 1000000, MAX_GROUPS 30000 and RELOAD_DELAY 60); using "su -m news -c /var/news/etc/rc.news >/dev/console" to start. ------------------------------ Subject: (9.9) HP-UX 10.01 ##FROM: Paul Wouters ##DIFF: YACC bison -y UID_T uid_t GID_T gid_t PID_T pid_t LOCK_STYLE LOCKF HAVE_UNISTD DO HAVE_SETSID DO HAVE_TM_GMTOFF DONT HAVE_ST_BLKSIZE DONT HAVE_WAITPID DO USE_UNION_WAIT DONT HAVE_VFORK DONT FDCOUNT_STYLE GETRLIMIT ABORTVAL void ALARMVAL unsigned int GETPIDVAL pid_t SLEEPVAL unsigned int QSORTVAL void LSEEKVAL off_t FREEVAL void _EXITVAL void MISSING_SRC MISSING_OBJ _PATH_COMPRESS /usr/bin/compress _PATH_MAILCMD /usr/bin/mailx ##OS: HP-UX hp9000 B.10.01 A 9000/801 ##COMPILER: gcc 2.6.3 GNU bison 1.22 ##MISC: Some minor notes on getting it to compile. My syslog.h is not in but , and it doesn't contain LOG_NEWS. A new syslog is probably much wanted on the standard hpux-10.01. I used the one from a recent berkeley syslog.h : #define LOG_NEWS (7<<3) /* network news subsystem */ Also, HPUX doesn't come with yacc. I tried byacc 3.0 but it didn't work, so I used bison -y. Finally, HPUX doens't have egrep, i used the GNU version. ----- Daryl Gaumer (darylg@cup.hp.com) adds: I use the syslog that is shipped as part of HP-UX. I have the following in my config.data file: LOG_INN_SERVER LOG_LOCAL7 LOG_INN_PROG LOG_LOCAL7 FYI. The full blown C/ANSII-C compiler is a separate product. I think yacc comes with this product. Corrections: egrep ships with HP-UX (as part of the "core-OS"). It is /usr/bin/egrep on a system running 9.05 (and on my workstation with is running HP-UX 10.01). ------------------------------ Subject: (9.10) Fujitsu DS/90 running UXP/DS(V20L10) ##FROM: Fumio MORIYA ##DIFF: DEFS -I../include -DUXPDSV20 USE_CHAR_CONST DO CFLAGS $(DEFS) -O PROF -p LIBS -lnsl -lsocket -lelf -lresolv LINTLIBSTYLE SYSV LINTFLAGS -b -h $(DEFS) LINTFILTER | sed -n -f ../sedf.sysv RANLIB echo VAR_STYLE STDARGS SIZE_T size_t UID_T uid_t GID_T gid_t PID_T pid_t POINTER void LOCK_STYLE LOCKF HAVE_UNISTD DO HAVE_SETBUFFER DONT HAVE_SETSID DO HAVE_TM_GMTOFF DONT HAVE_WAITPID DO USE_UNION_WAIT DONT HAVE_VFORK DONT CLX_STYLE FCNTL RES_STYLE TIMES FDCOUNT_STYLE SYSCONF > CTYPE (isascii((c)) && isXXXXX((c))) ABORTVAL void ALARMVAL unsigned GETPIDVAL pid_t SLEEPVAL unsigned QSORTVAL void LSEEKVAL off_t FREEVAL void _EXITVAL void MISSING_OBJ _PATH_SENDMAIL /usr/ucblib/sendmail -t _PATH_COMPRESS /usr/bin/compress _PATH_EGREP /usr/bin/egrep _PATH_MAILCMD /usr/bin/mailx ##OS: UXP/DS V20L10 (SVR4.2) ##COMPILER: supplied. ##MISC: *** nc.c.orig Fri Aug 30 11:47:19 1996 --- nc.c Fri Aug 30 11:20:52 1996 *************** *** 1216,1220 **** NCclearwip(&NCwip[cp->fd]); #if defined(SOL_SOCKET) && defined(SO_SNDBUF) && defined(SO_RCVBUF) ! #ifndef SUNOS5 i = 24 * 1024; if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&i, sizeof i) < 0) --- 1216,1220 ---- NCclearwip(&NCwip[cp->fd]); #if defined(SOL_SOCKET) && defined(SO_SNDBUF) && defined(SO_RCVBUF) ! #if !defined(SUNOS5) && !defined(UXPDSV20) i = 24 * 1024; if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&i, sizeof i) < 0) ------------------------------ Subject: (9.11) SunOS 4.1.x for INN 1.5 ##FROM: psmith@baynetworks.com (Paul D. Smith) ##DIFF: LIBS # empty SIGVAR long int HAVE_SETPROCTITLE DONT HAVE_VFORK DO QSORTVAL int MISSING_SRC memmove.c strerror.c MISSING_OBJ memmove.o strerror.o USE_CHAR_CONST DO _PATH_SENDMAIL /usr/lib/sendmail -oi -t _PATH_MAILCMD /usr/ucb/Mail INNWATCH_INODES 3 ##OS: SunOS 4.1.x ##COMPILER: gcc 2.7.2.1 ##MISC: ------------------------------ Subject: (9.12) Pyramid Systems running DC/OSx ##FROM: mark@pyramid.com (Mark Wedel) ##DIFF: CC /usr/ccs/bin/cc CFLAGS $(DEFS) -O4 LIBS -lnsl -lsocket -lelf LINTFLAGS -b -h $(DEFS) LINTFILTER | sed -n -f ../sedf.sysv RANLIB echo LOCK_STYLE FCNTL HAVE_SETBUFFER DONT HAVE_SETPROCTITLE DONT HAVE_TM_GMTOFF DONT HAVE_VFORK DO HAVE_UNIX_DOMAIN DONT CLX_STYLE FCNTL RES_STYLE TIMES MISSING_MAN strcasecmp.3 MISSING_SRC strcasecmp.c MISSING_OBJ strcasecmp.o ACT_STYLE MMAP MSYNC_3_ARG DO ##OS: DC/OSx ##COMPILER: ##MISC: These should also apply to Sinix 5.43 (and perhaps other versions) ------------------------------ Subject: (9.13) HP-UX 10.20 with HP gcc and INN1.5.1 ##FROM: Olav Kolbu ##DIFF: CC cc CFLAGS $(DEFS) -g -Ae DBZCFLAGS $(CFLAGS) -Ae LIBS LINTFLAGS -b -h $(DEFS) LINTFILTER | cat LOCK_STYLE LOCKF HAVE_SETPROCTITLE DONT HAVE_TM_GMTOFF DONT HAVE_VFORK DO _PATH_MAILCMD /usr/bin/mailx INNWATCH_DF /bin/bdf ##OS: HP-UX 10.20 ##COMPILER: HP's non-bundled (extra $$$) ANSI C compiler ##MISC: Oddities: 1. The HPUX syslogd knows about LOG_NEWS (even got an entry in ) but the actual syslogd doesn't recognice the "news" facility. Using "56.whatever" instead of "news.whatever" however appears to work fine. System info: > uname -a HP-UX aragorn B.10.20 A 9000/735 unknown > what /bin/cc /bin/cc: LINT A.10.32.03 CXREF A.10.32.03 HP92453-01 A.10.32.08 HP C Compiler /usr/lib/libc: $Revision: 2.17 $ > what /bin/yacc /bin/yacc: A.10.32.03 HP C LANGUAGE TOOL (YACC) 960517 ------------------------------ Subject: (9.14) Reliant Unix 5.43 C0024 on a MIPS RM300-C62 (Siemens Nixdorf) ##FROM: Michael Szczuka ##DIFF: USE_CHAR_CONST DO LDFLAGS -L/usr/ucblib LIBS -lsocket -lnsl -lucb -lelf LINTFLAGS -b -h $(DEFS) RANLIB echo LOCK_STYLE LOCKF HAVE_SETPROCTITLE DONT HAVE_TM_GMTOFF DONT _PATH_SH /usr/local/bin/bash _PATH_AWK /sbin/awk _PATH_SED /usr/local/bin/sed _PATH_SORT /sbin/sort _PATH_MAILCMD /usr/local/bin/mutt _PATH_GZIP /usr/local/bin/gzip ##OS: Reliant Unix 5.43 C0024 on a MIPS RM300-C62 (Siemens Nixdorf) ##COMPILER: gcc 2.7.2 ##MISC: - the environment is by no means vanilla Reliant Unix 5.43. I've installed a good deal of GNU software. This has primarily effect on the paths but doesn't really affect compilation of INN (at least I don't think so). The only important change in the paths is for sed; /sbin/sed (the one that comes with Reliant Unix 5.43) didn't pass the sedtest, so I took the GNU version (sed-v2.05). - gettimeofday() uses only _one_ argument, so you have to change the call in lib/gettime.c (line 33) from if (gettimeofday(&tv, (struct timezone *)NULL) == -1) to if (gettimeofday(&tv) == -1) ##FURTHER NOTES: - subst.c won't compile with gcc unless you explicitely tell him to use gcc - and you have no license for the cc that comes with the system ... This is no problem if you use the shell version. ------------------------------ Subject: (9.15) UnixWare 2.1.x ##FROM: "Bob Farmer" ##DIFF: CC cc USE_CHAR_CONST DO DBZCFLAGS $(CFLAGS) -DMMAP LIBS -L/usr/ccs/lib -lelf -lgen -lresolv -lsocket -lnsl -lcrypt LINTLIBSTYLE SYSV LINTFLAGS -b -h $(DEFS) LINTFILTER | sed -n -f ../sedf.sysv VAR_STYLE VARARGS SIGVAR int LOCK_STYLE LOCKF HAVE_SETBUFFER DONT HAVE_SETPROCTITLE DONT HAVE_TM_GMTOFF DONT RES_STYLE TIMES NOFILE_LIMIT 200 NEED_TIME DO MISSING_MAN strcasecmp.3 MISSING_SRC strcasecmp.c MISSING_OBJ strcasecmp.o _PATH_SENDMAIL /usr/ucblib/sendmail -t _PATH_AWK /usr/local/bin/awk _PATH_SED /usr/local/bin/sed _PATH_MAILCMD /usr/bin/mailx _PATH_GZIP /usr/local/bin/gzip ##OS: UnixWare 2.1.2 ##COMPILER: cc (supplied) ##MISC: The gzip, awk, and sed in /usr/local/bin are the corresponding GNU utilities. This is with UnixWare 2.1.2 (the latest version at the moment), and the cc that's supplied with the system of course. I have the UnixWare Software Development Kit installed, I don't think it's necessary to compile INN though. The same setup should more or less work for all UnixWare 2.x versions. 1.x would probably be somewhat different... inn-1.7.2/FAQ/INN-faq_part30100644000175100001440000002672106443103542013473 0ustar mdusersNewsgroups: news.software.nntp,news.software.b,news.answers Approved: hwr@pilhuhn.de Subject: INN FAQ Part 3/9: Reasons why INN isn't starting Followup-To: news.software.nntp Summary: This article is part 3 of a multi-part FAQ: Part 3: This includes help with getting innd to start. Posted-By: post_faq 2.10 Archive-name: usenet/software/inn-faq/part3 Last Changed: $Date: 1997/11/04 02:25:53 $ $Revision: 2.18 $ Part 3 of 9 INN FAQ Part 1: General and questions from people that don't (yet) run INN INN FAQ Part 2: Specific notes for specific operating systems INN FAQ Part 3: Reasons why INN isn't starting INN FAQ Part 4: The debugging tutorial (setup of feeds etc.) INN FAQ Part 5: Other error messages and what they mean INN FAQ Part 6: Day-to-day operation and changes to the system INN FAQ Part 7: Problems with INN already running INN FAQ Part 8: Appendix A: Norman's install guide INN FAQ Part 9: Appendix B: Configurations for certain systems ------------------------------ Subject: Table Of Contents for Part 3/9 ===================================================================== TABLE OF CONTENTS FOR PART 3/9 ===================================================================== REASONS WHY INN ISN'T STARTING: 3.1 What runs as what? 3.2 Why does innd just exit right away with no message? 3.3 syslog message: inndstart: inndstart cant bind Address already in use 3.4 syslog message: ME internal no to group 3.5 syslog message: ME internal no control and/or junk group 3.6 syslog message: Can't setup communication (bind failure) 3.7 syslog message: ME bad_newsfeeds no feeding sites 3.8 syslog message: ME cant GetConfigValue 3.9 syslog message: ME cant accept RCreader 3.10 syslog message: ME cant ioctl(TIOCNOTTY) Invalid argument 3.11 syslog message: ME cant fork /some/tool Resource temporarily unavailable 3.12 /usr/local/etc/rc.news: (M-i)^P^L^A.Gd: not found 3.13 syslog message: ME cant dbminit /usr/local/news/history ===================================================================== REASONS WHY INN ISN'T STARTING ===================================================================== ------------------------------ Subject: (3.1) What runs as what? 1. The first "make install" MUST RUN AS ROOT. 2. Other "make install" runs as "root", but sometimes "news" will work. 3. "rc.news" runs as "root" for versions prior to 1.5 and as "news" for INN1.5 and later. 4. "news.daily" runs as "news". 5. ALL CRON JOBS (sendbatch, sendnntp, send-ihave, etc.) run as "news". HOW TO REMEMBER THIS: EVERYTHING RUNS AS "NEWS" EXCEPT: "rc.news" runs as root, since it runs from rc.local (which runs as root) and since it runs things that start out as root but become "news" after doing special things. "make install" runs as "root" because it has to do "chown" to set up files securely. If your innd nevertheless runs as root, then also look at #7.52 ------------------------------ Subject: (3.2) Why does innd just exit right away with no message? First, fix your syslog: innd (nearly) always logs a message before it exits. (The INN distribution includes a version of the current UCB syslog, along with instructions on how to install it. Ultrix systems might want to look at the syslog that is available on gatekeeper.dec.com). If innd doesn't syslog, then it did dump a core file, that you can inspect. Second, the most common cause of this is that you do not have a history file (or no history database). You will see a message like this: ME cant dbminit /usr/local/news/history No such file or directory ( Note that in versions > INN1.5, the word ``ME'' is replaced by ``SERVER'' ). This means that you do not have a history database (or no history.dir and history.pag files). If you are just installing INN for your first time, you might want to run the BUILD script in your INN source tree. Or, you can read about makehistory in doc/news-recovery.8; if you do the latter, make sure to rename the database files (pay attention to the two "mv" commands). Another possibility is a bad active file; e.g. one line only has three fields instead of four. You can find such lines by running expire: expire -n -x -t which will then show you which lines are bad. ------------------------------ Subject: (3.3) syslog message: inndstart: inndstart cant bind Address already in use >I try to start INN but got this error in my syslog file: > inndstart: inndstart cant bind Address already in use >Can anyone give me a hint on how to fix it ? Something else is already using port 119. Comment out the line in /etc/inetd.conf for port 119 and "kill -HUP" the inetd program (which makes it re-read the configuration file). Remember, there are two ways for programs to take control over an incoming port. (1) the program runs and grabs the port (which has to be done as root) and then handles all incoming connections, or (2) the program is listed in /etc/inetd.conf and inetd grabs the port and hands off any incoming connections to the program specified in /etc/inetd.conf (i.e. one process gets started for every incoming connection.) If you do (1) and (2) at the same time, the inetd will grab the port and then anyone else that grabs the port will get an "Address already in use" error. INN's "innd" program is type (1). C News+NNTP uses something that is type (2). Most people that get this error ran C News+NNTP a long time ago and forgot to remove the line from their /etc/inetd.conf file. ------------------------------ Subject: (3.4) syslog message: ME internal no to group If you set MERGE_TO_GROUPS to "DO", you have to have a "to" group listed in your "active" file or you will get the above syslog message and innd will not start. You can edit the active file directly if innd isn't running (see also #6.3). ------------------------------ Subject: (3.5) syslog message: ME internal no control and/or junk group You must have a newsgroup named "control" and a newsgroup named "junk" for innd to start. Since innd isn't running, you can edit the active file directly Add these lines: control 0000000000 0000000000 y junk 0000000000 0000000000 y --tal Also make sure that the directories in the spool either don't exist or are writable by the news user. ------------------------------ Subject: (3.6) syslog message: Can't setup communication (bind failure) The message "Can't setup communication (bind failure) Permission denied" means that the permissions on your _PATH_NEWSCONTROL directory are wrong. You might want to delete the directory and "make install" to create it again. ------------------------------ Subject: (3.7) syslog message: ME bad_newsfeeds no feeding sites (Rich Salz replies:) The syslog message is telling you that you are not feeding news to any sites. You have to have at least one feed. (You may consider this to be a bug, it's just that I'm too lazy to make everything work right if you don't have any newsfeeds.) Until you go into production and start feeding sites, add a line like this: dummy-feed:!*:: ------------------------------ Subject: (3.8) syslog message: ME cant GetConfigValue Jan 12 17:38:06 galaxy innd: ME cant GetConfigValue pathhost Error 0 ^^^^^^^^ This means you don't have "pathhost:" in your inn.conf. GetConfigValue is the routine that gets data out of the inn.conf file. If you get the above error, it means you don't have a particular value in your inn.conf. Run "inncheck -v" usually will tell you what you need to do. Note that there might be a slightly different message: Nov 1 15:39:30 serv nnrpd[5973]: cant getconfigvalue Error 0 In that case the host where nnrpd was running had DNS resolving problems. Getting DNS to work correctly again solved the problem. ------------------------------ Subject: (3.9) syslog message: ME cant accept RCreader Situation: INN 1.4sec on ICS2.0 or Interactive Unix System V Release 3.2 or one of the many SVR4 Unix's. You get syslog messages like: Jul 14 12:07:44 isdn.IFNS.DE innd: ME cant accept RCreader No more Jul 14 12:07:44 isdn.IFNS.DE innd: ME cant accept RCreader Protocol error May 7 12:05:07 salyko.cube.net innd: ME cant accept RCreader Protocol error when you connect to innd from a remote machine, but not from the local host. Problem: Well, that's just another bug in the SVR4 networking code. Chris Munonye reports that this patch fixed the problem: *** RCS/rc.c Sun Jul 18 15:02:50 1993 --- rc.c Sun Jul 18 15:04:35 1993 *************** *** 173,178 **** --- 173,181 ---- /* Get the connection. */ size = sizeof remote; + if (SetNonBlocking(cp->fd, FALSE) < 0) + syslog(L_ERROR, "%s cant un-nonblock %d in RCreader(errno %d) %m :", + LogName, cp->fd, errno); if ((fd = accept(cp->fd, (struct sockaddr *)&remote, &size)) < 0) { syslog(L_ERROR, "%s cant accept RCreader %m", LogName); return; Under Solaris, when accept() fails and sets errno to EPROTO, it means the client has sent a TCP reset before the connection has been accepted by the server. Therefore, the syslog messages Inn produces: innd: ME cant accept RCreader Protocol error can be merely ignored under Solaris. Note that in 2.5.1 with the Internet Server Supplement and also in 2.6 the errno for this case has changed from EPROTO to ECONNABORTED. ------------------------------ Subject: (3.10) syslog message: ME cant ioctl(TIOCNOTTY) Invalid argument Most likely a botched config.data - TIOCNOTTY is a BSDism and probably doesn't work on SVR4-based system. (If you aren't sure if your Unix is SVR4-based, get out of the netnews business). ------------------------------ Subject: (3.11) syslog message: ME cant fork /some/tool Resource temporarily unavailable User news ran out of processes and wasn't able to fork off the specific tool. You need either just raise the limit on the number of processes in the shell which starts innd (e.g in rc.news : unlimit maxproc or if that doesn't help raise the number of processes in the kernelconfig (modt often by raising maxusers and also raising the # of processes per user). ------------------------------ Subject: (3.12) /usr/local/etc/rc.news: (M-i)^P^L^A.Gd: not found Q: rc.news reports "/usr/local/etc/rc.news: (M-i)^P^L^A.Gd: not found" A: Bob Izenberg reports: Here's an unlikely possibility that bit us once. In an almost all-Sun environment, I requested and got /bin/ksh as my shell. When I logged in, I got a burst of control characters and a closed connection after a few seconds. It turned out that ksh followed about fifteen symbolic links to a file that had been moved/removed. Therefore, make sure that the first line in rc.news refers to a shell that really exists. If you run "sh /usr/local/etc/rc.news" make sure you don't have anything else named "sh" in your path. (And if you have something named "sh" in your path that isn't a Bourne Shell or a clone, worry!) ------------------------------ Subject: (3.13) syslog message: ME cant dbminit /usr/local/news/history That means that some of the history files are missing -- See #3.2 There is also a message: cant dbminit ME (Math) argument out of domain of func This means that your history.dir file is not formatted correctly. It should look something like this: (from James Brister) dbz 3 2579 9 C 128 127 24 4 3 2 1 0 4677 1706 1706 0 0 0 0 0 0 0 0 (i.e. two lines of ascii, most of it being numbers). In the latter case you can do: cd /where/the/history/is rm history.dir rm history.pag makehistory -r -f history inn-1.7.2/FAQ/INN-faq_part60100644000175100001440000011616506443103542013500 0ustar mdusersNewsgroups: news.software.nntp,news.software.b,news.answers Approved: hwr@pilhuhn.de Followup-To: news.software.nntp Subject: INN FAQ Part 6/9: Day-to-day operation and changes to the system Summary: This article is part 6 of a multi-part FAQ: Part 6: Day-to-day operational questions. Some big changes you can make, bug warnings for 1.4, 1.3, 1.2. Posted-By: post_faq 2.10 Archive-name: usenet/software/inn-faq/part6 Last Changed: $Date: 1997/07/01 01:25:41 $ $Revision: 2.21 $ Part 6 of 9 INN FAQ Part 1: General and questions from people that don't (yet) run INN INN FAQ Part 2: Specific notes for specific operating systems INN FAQ Part 3: Reasons why INN isn't starting INN FAQ Part 4: The debugging tutorial (setup of feeds etc.) INN FAQ Part 5: Other error messages and what they mean INN FAQ Part 6: Day-to-day operation and changes to the system INN FAQ Part 7: Problems with INN already running INN FAQ Part 8: Appendix A: Norman's install guide INN FAQ Part 9: Appendix B: Configurations for certain systems ------------------------------ Subject: Table Of Contents for Part 6/9 ===================================================================== TABLE OF CONTENTS FOR PART 6/9 ===================================================================== DAY-TO-DAY OPERATIONAL QUESTIONS: 6.1 How do I create all those directories in the newsspool? 6.2 Why is /usr/lib/news/newsgroups not found? 6.3 Safe way to edit the "active" file? 6.4 What's the best way to upgrade to a new version of INN? 6.5 How do I talk to innd from C or Perl? 6.6 After a crash. 6.7 How do I moderate a mailing list? 6.8 How do I configure the /usr/lib/news/moderators file? 6.9 Listing every article 6.10 How does /remember/ in expire.ctl work? 6.11 What does the output of ``expire -v1'' mean? HOW DO I... (Big changes you can make to the system): 6.12 How do I set up a delayed IHAVE/SENDME over NNTP? 6.13 I want compressed news, but do not have uucp 6.14 Can I use gzip with INN? 6.15 What do I do if /var/spool/news is split over multiple partitions? 6.16 Sun Online Disk Suite for news spool? 6.17 Add local newsgroups? 6.18 Archiving expired articles 6.19 How do I restrict access on certain newsgroups (like alt.sex) 6.20 INN on one machine, UUCP modem on a different one 6.21 Setting up proxy-nntp to talk through a firewall 6.22 How do I set up inpaths with INN? 6.23 Fill different types of control messages in different directories? 6.24 Use more than ~100 Feeds on SunOS 4.1 ? 6.25 Speed up NNTP Transfers ("Streaming NNTP") 6.26 I don't want all those reject messages from rnews in syslog BUGS IN 1.4: 6.27 Security Patch 6.28 Looping Select Patch BUGS IN 1.3 and 1.2: 6.29 7-bit encoded batches are not correctly processed. Why is this? 6.30 NOV (overchan) doesn't work well. 6.31 Why doesn't nntpget work? ===================================================================== DAY-TO-DAY OPERATIONAL QUESTIONS ===================================================================== ------------------------------ Subject: (6.1) How do I create all those directories in the newsspool? Q: For example, if you receive comp.sys.amiga.applications, do you have to mkdir /var/spool/news/comp/sys/amiga/applications? A: Nope. innd creates the directory for you the first time you receive an article for that newsgroup. ------------------------------ Subject: (6.2) Why is /usr/lib/news/newsgroups not found? The latest rev is in: ftp://ftp.uu.net/networking/news/config/newsgroups.Z or in ftp://ftp.sunet.se/pub/news/config/ Get it and install it. ------------------------------ Subject: (6.3) Safe way to edit the "active" file? First of all, you could manipulate the active file using the ctlinnd "newgroup", "rmgroup" and "changegroup" commands. However, sometimes you just need to do a lot of editing all at once: The following sequence is the shortest: ctlinnd pause "edit active" [do something to the active file] inncheck ctlinnd reload active "edit active" ctlinnd go "edit active" Simple! No need to "flush" since the "pause" does that. > What if I need to delete 3000 lines from my active file? I would definitely edit the active file manually (using the above procedure). > What if I need to delete 10 lines from my active file? For a couple quick changes, I recommend using "ctlinnd". This is a little slow because all channels are closed and reopened after each "rmgroup", "newgroup", and "changegroup". However, it's easier than remembering the above sequence. DO NOT THROTTLE THE SERVER WHEN DOING MULTIPLE rmgroup COMMANDS. There is a bug in INN (all versions) that will shred your active file if you do multiple "rmgroup" messages while the server if throttled. This is a common mistake. People think the "rmgroup"'s will go faster if the server is throttled. It will go faster, it will also shred your active file. If you have a large number of groups to remove or create, you can use awk to write a script to do the work for you. % cat thelist alt.foo.bar alt.delete.me comp.sys.mac % awk 2){print $3}' < ${HISTORY} | tr . / Sorting the output will improve directory cache efficiency. 2. This lists any article file no matter how many links you have, etc. and even if it is not listed in the history file: cd /var/spool/news gfind . -regex '.*/[0-9][0-9]*$' -print NOTE: GNU find will execute this much faster than the "find" that comes with most versions of Unix (including SunOS). 3. If you need to do something fancier than what find can do, consider using perl's find2perl program. Given a find command line, find2perl will output the perl code to do the same thing. You can then modify the output to do what you want. For example: find2perl . -mtime +30 -name '[0-9][0-9]*$' -exec '/bin/rm {}' outputs a perl script that deletes any article that is over 30 days old (except the regular expression is output as wrong... change it to: /^[0-9]+$/ && and it should work just fine. 4. Another efficient way to scan all articles in the spool, including those that for some reason aren't in the history file, is to read the active file for a list of newsgroup names, and chdir() to each directory to scan for files. Remember *not* to do a recursive treewalk for each directory. ------------------------------ Subject: (6.10) How does /remember/ in expire.ctl work? (from Jerry Aguirre) The /remember/ time specifies how long a history only (i.e. a entry that only is in history, but where the article is no longer there) entry will be kept measured from the arrival time. If the expire value is 14 days and the /remember/ time is 5 then entries will be kept for 15 days. This is because the /remember/ only applies to entries after that articles have expired. It can not force a history entry to be removed before the article is expired. The extra day beyond expire might be considered a harmless bug in expire. ------------------------------ Subject: (6.11) What does the output of ``expire -v1'' mean? (Based on a submission from Chris Johnson ) Running expire with -v1 option produces output like: Removed approximately 764913k Article lines processed 1044872 Articles retained 872883 Entries expired 171989 Files unlinked 239657 Old entries dropped 0 Old entries retained 103038 "Article lines processed": the number of lines in the the history file that were read by the expire program (it reads through the entire history file when it runs) "Articles retained": the lines left in the history file after some of the lines (entries) are dropped. "Entries expired": the number of entries/articles listed in the history file that were deemed old enough to be deleted; this equals "Article lines processed" - "Articles retained" "Files unlinked": the number of files deleted from the file system where 1 file equals 1 article; however, this number can be much higher than "Entries expired" because a single entry can be posted to multiple groups and you get 1 file for each group it is posted to "Old entries dropped": lines deleted from the history file that are only present because of the value of /remember/ in expire.ctl "Old entries retained": lines left in the history file for articles that have already expired (Note that running expire with -t option articles are not deleted from filesystem and the output changes slightly to: Would remove approximately 103623k). Running expire with -z option also does not remove files, but writes a list of files to be removed (see entries about "delayrm" and "fastrm" in this FAQ) See also the manpage for expire ... ===================================================================== HOW DO I... (Big changes you can make to the system) ===================================================================== ------------------------------ Subject: (6.12) How do I set up a delayed IHAVE/SENDME over NNTP? Christophe Wolfhugel writes: Having some of your NNTP newsfeeds delayed by a fixed amount of time is a good way to reduce your bandwidth requirements, or a good way to set up a backup-feed. By including a Wt flag in your newsfeeds file, INN will insert timestamp entries in that batchfile, channels, or exploders. This timestamp can be used to implement delayed ihave/sendme processing. INN's senders (like innxmit) do not use that data yet. However, NNTPLINK does support this delayed IHAVE/SENDME mechanism since release 3.3 (NNTPLINK can be found on shape.mps.ohio-state.edu:/pub/nntplink/nntplink.tar.gz). HOW TO DO IT: The syntax that you would use in your newsfeeds file would be: site:*:Tf,Wtmn: and run this command now and then: nntplink -i batchfile -y 300 -b site news.site.fr The delayed IHAVE/SENDME is expected to allow bandwidth savings in situations where all sites use nntplink in following topology: Your site -- 64k -----------+----------- Site 1 | | | 2mb | | +------------ Site 2 Site 1 and 2 are in the same metropolitan area, you feed them both. With the standard nntplink layout, you generally send all articles twice, which is a waste even if you're at 2 Meg/s link and even if Site 1 and 2 do nntplinks, you're faster. The delayed link would be used between your site and Site 2. A 2 or 3 minute delay allows Site 1 to feed Site 2 before you, and in case of a Site 1 outage the backup starts nearly immediately. Reasonable delays are still kept as You -> 1 -> 2 should take less than one minute (or just 300 ms disk to disk if using nntplink -i ? :)). Experiences seem to show that a 2 to 3 minutes delay is a reasonable choice. Chris ------------------------------ Subject: (6.13) I want compressed news, but do not have uucp There is an extension to the nntp Protocol called XBatch. XBatch lets you tunnel binary data through a nntp connection. The batches will be put in a separate directory on the receiving host, where they can then be fed into rnews. Before trying xbatch make sure, that you can get news via nntp!!! Inn 1.5 has xbatch built in, so you can just read the innxbatch(8) manual page. You can check that a server accepts xbatch (from a host which is in your hosts.nntp): 132 % telnet your.news.host.pilhuhn.de nntp xbatch 3 <-- you type 339 result code abc <-- you type 239 successfully accepted ------------------------------ Subject: (6.14) Can I use gzip with INN? [this was written with the help of Michael Brouwer ] There are three things that can be effected by using gzip: Compression of old logs, compressing batches to send out, and decompressing batches that come in. With INN 1.4 all you need to do is change two lines in config.data to something like this: COMPRESS /usr/local/bin/gzip DOTZ .gz If you rebuild INN with these options set, all logs will be gzipped, and rnews will use gzip to decompress news. gzip will automaticly and transparently decompress UNIX Compress, SCO UNIX Compress (I'm told it's 99% compatible with UNIX Compress), Pack, and gzip. Therefore, you can now receive batches compressed with any of the above listed formats. Let's say your site is now has "a universal decompresser". It has been reported that if you hardlink gzip to be zcat, and make sure that it is the zcat that INN uses, you can get the "universal decompresser" without having to use gzip for your logs. (Though, gzip for your logs is a big win, so why make trouble for yourself?) `send-uucp' will still use compress for outgoing batches, so the sites you feed won't suddenly start getting data they don't understand. Before you can send gzipped batches, you should make sure that the sites that you feed have made the above changes so that they have the "universal decompresser" too. Edit send-uucp to use gzip instead of compress for certain hosts (see example of using compress -b12 for the host esca in send-uucp), outgoing batches will be gzipped. If you use sendbatch, you will have to edit the file so that COMPRESS is set to "gzip" and COMPFLAGS is set to "-9vc". ------------------------------ Subject: (6.15) What do I do if /var/spool/news is split over multiple partitions? READ THIS ENTIRE SECTION BEFORE YOU BEGIN. First of all, you can do this by either mounting a filesystem at /var/spool/news/comp (for example) or by mounting a filesystem anywhere and making /var/spool/news/comp a symbolic link to the new partition. Articles will be written as normal, but cross-posts have to be handled specially now. Usually INN handles crossposts by writing the article to the first newsgroup, and then creating hard links to all the other places where the article should appear. Hard links do not take up additional disk space (except making your directories longer). Hard links also have the advantage that the file data doesn't get deleted until the last hard link is gone (and they can be deleted in any order). Therefore, you can expire each newsgroup at a different rate, but the file data won't delete until it is expired from the last newsgroup. The problem is that two hard linked files must both be on the same filesystem (partition). When INN sees that it can not make a hard link (because an article is cross-posted across two partitions) it will try to make a symbolic link. If your system can not do symbolic links, set HAVE_SYMLINK to DONT in your config.data file. This will make INN write a second (or third, etc.) copy of the file instead. (NOTE: INN 1.4 doesn't make the extra files.) Anyway, even though INN will automatically create symbolic links, you have to give expire the "-l" flag so that it will know to modify its behavior. Suppose that a message is posted to rec.photo and alt.cameras and suppose that rec.photo expires more quickly then the alt group. If this happens, then you will be left with a dangling symlink. The -l flag prevents this from happening by not removing the file from rec.photo until alt.cameras expire time permits it from being deleted. To inform expire that your spool is split across multiple partitions: In news.daily, change: EXPIREFLAGS="-v1" to read EXPIREFLAGS="-v1 -l" In expirerm, change: RMPROC="fastrm -e -u -s ${SPOOL}" to read RMPROC="fastrm -e -s ${SPOOL}" Now edit innwatch.ctl so that it checks all the spool disks, not just ".". See the lines with "No space (spool)". Also edit innshellvars and change the INNDF variable to reflect the innwatch.ctl changes. Lastly, edit innstat (the line with the "df") so that all spool disks are included. After that, you're done! If you ever need to run "makehistory" you should pay attention to the caveat in makehistory(8) (NB: This man page is called "news-recovery" in releases before INN 1.5): MOVING THE FILES: Here is an example of moving /var/spool/news/rec to its own partition: (mount the new disk onto /mnt) cd /var/spool/news/rec tar cf - . | ( cd /mnt && tar xpvf - ) If you are confident you did it right, "rm -rf /var/spool/news/rec" then "mkdir /var/spool/news/rec". umount /mnt mount /var/spool/news/rec If you are moving >50% of the spool, you might use dump instead of tar: dump 0f - /var/spool/news | ( cd /mnt && restore xf - rec) But try it out first if it is really faster - some people had much better success with using a tar-pipe (as above) using GnuTar (10 times faster). If you don't mind about article loss, just deleting the articles would be fastest: cd /var/spool/news mv rec rec.o mkdir rec mount /dev/newdisk /var/spool/news/rec rm -rf rec.o Remember: If you screw up the /etc/fstab, SunOS and many other UNIXs won't boot. fstab can't have any blank lines in many UNIXs either. Double check the file after you modify it. ------------------------------ Subject: (6.16) Sun Online Disk Suite for news spool? Another way under SunOS 4.1.[34] not to use multiple partitions is to use the Sun Online Disk Suite. Several sites use this and have spool capacities up to 12 GB. It has been reported that using a stripe size of 1 cylinder gives the best performance for the article filesystem. Chris Schmidt elaborates more: "You add several physical volumes to get a logical volume. We have a meta partition made out of three 2GB disks with one partition each. df shows: Filesystem kbytes used avail capacity Mounted on /dev/md1a 5878350 4831490 752943 87% /EUnet/news/spool With the Online Disk Suite you also can do striping to balance the load among the used disks: the first cylinder is on the first disk, the second on the second one, the third on the third one and the fourth on the first disk again .." ------------------------------ Subject: (6.17) Add local newsgroups? Q: Does anyone have a cookbook example on how to create a local news group? These are the steps .. 1) Make sure your innd is running 2) Add the group with: ctlinnd newgroup local.group 3) Add entries to newsfeeds to restrict the local groups to your organization: ME:!local.*:: out.going.site:*,!local.*:Tf,Wnm: 4) Add a descriptive entry to newsgroups 5) Ready :) Please consider, that local is a very common name for local groups, so if a user crossposts to local.test and misc.test the article will show up in all local.test over the world. So please choose a 'better' name. ------------------------------ Subject: (6.18) Archiving expired articles In <2hmomh$262@news.iastate.edu> rod@iastate.edu writes: >What options do I have in INN for archiving local newsgroups? >Any help would be appreciated. Any cookbook examples would also help. See doc/archive.8. You could also put "never:never:never" in your expire.ctl file. Here's a cookbook example of an archive feed: # Feed all moderated source postings to an archiver source-archive!:!*,*sources*,!*wanted*,!*.d\ :Tc,Nm,Wn:/usr/local/bin/archive -f -i /usr/spool/news.archive/INDEX Ulf Kieber writes: The INN 1.4 newsfeeds(5) man page show how to set up a /program/ feed for archive. The "archive" program currently does NOT support this method. i.e. do not use Tp in "newsfeeds" for an archive feed. Even if "archive" supported being used as a program feed, you would not want to use it as such if you intended to use the ``-i'' flag as archive does not do any file locking on it's index file. The index file might get corrupted by multiple concurrently running instances of archive, as may happen with a program feed. ------------------------------ Subject: (6.19) How do I restrict access on certain newsgroups (like alt.sex) >If I were running a news server, and some of my users complained that they >didn't want their kids being able to access some of the newsgroups, would it >be possible to block access to specific newsgroups on a per-user basis? >I'm not asking if it's easy, just _possible_. If they are not using NNTP for reading, you can make a /etc/group entry for a group called something special, like "horny" and give only users in group horny access to read that directory: chown news /var/spool/news/alt/sex chgrp horny /var/spool/news/alt/sex chmod 750 /var/spool/news/alt/sex chmod 750 /var/spool/news/over.view/alt/sex # your NOV data chmod 770 /var/spool/news/in.coming chmod 770 /var/spool/news/out.going Now only people in the group "horny" can read that newsgroup. Everyone can subscribe to it, but only horny people can read it. innd (which runs as "news") will still be able to do its business. Inn has an authentication scheme called authinfo for use with NNTP. The user must supply a name and a password. If they match an entry in nnrp.access, then the user may read the groups specific to this entry. An example entry for nnrp.access: ---------- *.pilhuhn.de:R P:::*,!pilhuhn.foo :R P:hwr:XXX:* ---------- Here users from hosts *.pilhuhn.de may read and post in all groups besides pilhuhn.foo. If a user authenticates a user hwr with password XXX, then he or she might also read pilhuhn.foo. In order to be able to authenticate as user ``hwr'' in the above example, the host where this ``hwr'' connects from also must have read rights. So this --------- :R P:hwr:XXX:* --------- as the only entry in nnrp.access won't work, but the following will work: --------- *:R:::*,!pilhuhn.foo :R P:hwr:XXX:* --------- Note that those 'password entries' need to be last in nnrp.access. There is a bug in inn1.4 which allows users to post to such a protected group if they know the name of the group even if they can't read it. nnrp.access-auth.patch (on the usual patch site) cures this. If the newsreader software doesn't support this then you can still restrict access on a per-host basis. To read a specific group you then need to be on a specific machine (but then everybody on that machine can read the group). In 1.5 there is be a better protocol (authinfo generic) for doing this and it should gain better acceptance than the current protocol. Also in 1.5 you can use entries from the password database if you use the following entries: --------- *:R:::*,!pilhuhn.foo :R P:+::* --------- In order to get authentication with Netscape to work, you need a slightly different way of authentication; Netscape (and other newsreaders) don't send authentication info on startup ("active authentication"), but only then when the server requests it by sending a "480 Authentication required for command" reply ("passive authentication"). A entry like the following will do this: --------- :R P:user1:pass1:*,!pilhuhn.foo :R P:test:test:pilhuhn.foo snert.pilhuhn.de:R P:user2:pass2:* tritta.pilhuhn.de:R P:user3:pass3:*,!ka.test --------- Here all users (in this case only from host {snert,tritta}.pilhuhn.de allowed) have to authenticate. If they do as ``user2'' then they can read and post all groups. If they do as user ``test'' then they can only read pilhuhn.foo and if they do as ``user1'' then they will be able to read all groups except pilhuhn.foo. Note that in the above example if the user comes from e.g. snert.pilhuhn.de then he she will nevertheless be able to authenticate as ``user3'' even if this is marked as host tritta. That means at the stage where a ``authinfo {user|pass}'' command is sent to the server, the host is no longer checked and every valid combination of user and pass will authenticate; so password security is here as important as in the normal password database. Note that passive authentication will only take place if there is a hostname match with security fields filled in. If authentication is needed for a protected/secure newsgroup in an environment where no authentication is required for all other newsgroups, and users access the news server from many different hosts (ie; dial-up), then there must be a hostname entry to force passive news agents/clients to authenticate; this may result, however, in every user having to authenticate for ALL newsgroups, even when they don't attempt to access the secured newsgroup; in most cases, this will be accomplished by using a wildcard hostname entry For those that now ask how they can directly go to a newsgroup that needs authentication ... use Many thanks to Jim Dutton for his valuable comments. ------------------------------ Subject: (6.20) INN on one machine, UUCP modem on a different one Say you have a machine named "newsy" and "modemhead". "newsy" runs INN but only "modemhead" has any modems. A quick overview: config.data has a variable called "RNEWSLOCALCONNECT". If it is set to "DO", "rnews" will expect to be running on the same machine as "innd". On the other hand, if "RNEWSLOCALCONNECT" is set to "DONT" then "rnews" will connect to the machine listed in "inn.conf". Sending batches is a little more complicated. Receiving batches on modemhead: Make sure config.data has "RNEWSLOCALCONNECT" set to "DONT", recompile, and copy /bin/rnews and /usr/lib/news/inn.conf to modemhead. The unbatching will be done on modemhead, but the articles will be sent to newsy. It will work like magic. When /bin/rnews runs, it will open an NNTP connection to newsy and feed the batch (one article at a time) to newsy... newsy thinks it's just getting a regular NNTP feed. (which means modemhead has to be listed in hosts.nntp). If newsy and modemhead are different platforms (i.e. Ultrix vs. SunOS) you can use the MakeRnews script (mentioned in Install.ms) to generate just rnews for the modemhead machine. Sending batches via modemhead: The "sendbatch" program calls $(UUX). Change ${UUX} to be something like "rsh modemhead uux" instead of "uux". You'll have to do a little hacking on sendbatch. For example, the part that checks to see if the queue is full might have to be re-written. Anyway... now the batches will be generated and send via modemhead's UUCP system. Pretty neat, eh? Other advice: I set UUX to 'rsh uucphost uux' (note no pipe [|]). Also, we have no 'uuq' command, but even if we did, it would have returned bogus info as $SITE is not known to UUCP on newshost. Thus I created a stupid 'uuq' that does 'echo 0 0 0 0 0 0 0' to satisfy the awk script. However, we have no way to monitor queue length (though its of little importance to us as we only have 3 feeds and they are partial) Finally, the /etc/passwd entry for 'news' on 'uucphost' MUST list /bin/sh; /bin/csh results in 'rnews: event not found' and escaping the '!' inside sendbatch had no effect. ------------------------------ Subject: (6.21) Setting up proxy-nntp to talk through a firewall Try ftp://ftp.cs.cmu.edu/misc/dnntpd/dnntpd.tar.Z or look at backends/rcompressed.c in the INN distribution. ------------------------------ Subject: (6.22) How do I set up inpaths with INN? inpaths should work just fine with INN as it ships. However, you can make it run faster by using the following shell script. Edit it to your tastes. It replaces the long "(cd /var/spool/news ; /usr/local/bin/gfind . -type f -print | /usr/lib/news/local/inpaths sdl | /usr/ucb/mail admin,pathsurvey@pathsurvey.eu.org)" which people usually use. #!/bin/sh . /usr/lib/news/innshellvars cd ${SPOOL} awk '(NF > 2){print $3}' < ${HISTORY} | tr . / | sort | \ inpaths `innconfval pathhost` | \ ${MAILCMD} newsmaster,pathsurvey@pathsurvey.eu.org If the inpaths people would include this information in the README, I could delete it from this FAQ. ------------------------------ Subject: (6.23) Fill different types of control messages in different directories? If you want to keep newgroup messages longer and expire cancel messages after half a day you can do the following: Create the groups control.newgroup and control.cancel ctlinnd newgroup control.newgroup ctlinnd newgroup control.cancel Add the following to expire.ctl: control.*:A:1:2:4 control.sendsys:A:10:15:21 control.newgroup:A:10:15:21 so all control messages typically expire after 2 days, but sendsys and newgroup messages are normally kept for 15 days. You should also change newsfeeds appropriately to reflect the changes that control now is a group and a hierarchy. ------------------------------ Subject: (6.24) Use more than ~100 Feeds on SunOS 4.1 ? SunOS 4.1 normally has a limit of 256 file descriptors per process. But unfortunately there is a bug in stdio (the use of a _signed_ char ) which lets one only use 128 file descriptors. One way would be to use an exploder feed (like bufchan). The other is: There is a stdio replacement called sfio which you can get from http://netlib.att.com/netlib/attgifts/sfio.shar.Z Just compile it as indicated in the package. After that, you must tweak config.data a bit to use sfio: DEFS -I../include -I/usr/local/include/sfio CC gcc CFLAGS $(DEFS) -O2 DBZCFLAGS $(CFLAGS) -DMMAP LDFLAGS (empty) LIBS -L/usr/local/lib/sfio -lsfio VAR_STYLE STDARGS (important! sfio doesn't like varargs if compiled ANSI) NOFILE_LIMIT -1 EXITVAL volatile void _EXITVAL volatile void Just recompile inn then and go for it. If you even need more than 256 descriptors, then you can use SunDBE (the Sun Databese Excelerator) which raises the limit from 256 to 1024. Thanks to Christopher Davis for this tip. ------------------------------ Subject: (6.25) Speed up NNTP Transfers ("Streaming NNTP") Normal NNTP uses the following scheme to transfer articles: Sender Receiver ---> Ihave Ok send it to me <--- ---> sends the actual message Says 'this was ok' <--- This procedure uses 2*RTT on the link (rtt = round trip time) plus time for the actual article transfer. Jerry Aguirre has rewritten NNTP code so that it now sends a list of message ids to remote which checks it and returns a value if it is to be sent. With each message sent Streaming NNTP also sends a new message-id to check so that the flow of news keeps streaming. Advantages of Streaming NNTP are - Fast even on lines with a high rtt (e.g. satellite links) - faster than normal nntp - compatible as innxmit has a autofallback to normal nntp Disadvantages are - INN gets more compute intensive - Streaming NNTP can fill a 64kB line that much that working over it via telnet gets a real pain. ------------------------------ Subject: (6.26) I don't want all those reject messages from rnews in syslog Rnews is logging those rejects via syslog. The level is determined at compile time via what you tell it in config.data: # Informational notice, usually not worth caring about. ### =()@>()= L_NOTICE LOG_WARNING So in this case you need to tell you syslogd to log only messages above level warning. ===================================================================== INFO ABOUT 1.5 ===================================================================== INN Version 1.5 has been released. For how to get it look at part1 of this FAQ. ===================================================================== BUGS IN 1.4 ===================================================================== UNOFFICIAL patches for INN 1.4 are available via anonymous FTP at ftp://ftp.isc.org/isc/inn/unoff-patches The ones that are highly recommended are: 1.4-to-1.4sec -- Fixes the major security hole in INN. 1.4sec-to-1.4sec2 -- Fixes the remaining known security hole in INN. select-loop-bug.patch -- Under some circumstances innd can lose track of a file descriptor and end up sitting in a select() loop. If your INN suddenly is using up tons of CPU time and not getting much done, install this UNOFFICIAL patch. Some OSs are more susceptible to this bug. THERE ARE MANY MORE at that site, many add some useful features. There is a replacement for innwatch that is written in Perl. Get it from "ftp://ftp.univ-lyon1.fr/pub/unix/news/inn/contrib/innwatch-beta2.pl.gz". This directory is mirrored on ftp://ftp.isc.org/isc/inn/unoff-contrib ===================================================================== BUGS IN 1.3 and 1.2 (Hey, it's 1997! Upgrade already!) ===================================================================== ------------------------------ Subject: (6.29) 7-bit encoded batches are not correctly processed. Why is this? Chris Schmidt replies: The decode program that comes with INN up to version 1.3 is broken. Because of that the last article in a 7bit encoded batch will not correctly be decoded (the last characters are screwed up). This is fixed in INN 1.4. ------------------------------ Subject: (6.30) NOV (overchan) doesn't work well. Correct. The NOV support in 1.3 didn't have all the bugs worked out. Don't use NOV under INN 1.3. Better yet, upgrade to at least 1.4sec and get all the benefits! ------------------------------ Subject: (6.31) Why doesn't nntpget work? The nntpget in INN 1.2 doesn't work. Period. Upgrade to the latest version of INN. inn-1.7.2/FAQ/INN-faq_part50100644000175100001440000006650506443103542013501 0ustar mdusersNewsgroups: news.software.nntp,news.software.b,news.answers Approved: hwr@pilhuhn.de Subject: INN FAQ Part 5/9: Other error messages and what they mean Followup-To: news.software.nntp Summary: This article is part 5 of a multi-part FAQ: Part 5: A list of error messages and what they mean. Posted-By: post_faq 2.10 Archive-name: usenet/software/inn-faq/part5 Last Changed: $Date: 1997/11/18 02:25:35 $ $Revision: 2.26 $ Part 5 of 9 INN FAQ Part 1: General and questions from people that don't (yet) run INN INN FAQ Part 2: Specific notes for specific operating systems INN FAQ Part 3: Reasons why INN isn't starting INN FAQ Part 4: The debugging tutorial (setup of feeds etc.) INN FAQ Part 5: Other error messages and what they mean INN FAQ Part 6: Day-to-day operation and changes to the system INN FAQ Part 7: Problems with INN already running INN FAQ Part 8: Appendix A: Norman's install guide INN FAQ Part 9: Appendix B: Configurations for certain systems ------------------------------ Subject: Table Of Contents for Part 5/9 ===================================================================== TABLE OF CONTENTS FOR PART 5/9 ===================================================================== OTHER ERROR MESSAGES AND WHAT THEY MEAN: 5.1 ld.so: Undefined symbol: _dbzwritethrough 5.2 Bad file number writing history file -- throttling 5.3 log file fills with " 436 No space" 5.4 Why does my innd often die with the message "Can't sync history..." 5.5 Reply from ctlinnd: Can't send XXX command (sendto failure) 5.6 syslog msg: ME cant sendto CCreader bytes 4 No such file or directory 5.7 syslog: cant symlink 5.8 syslog: cant read Connection reset by peer 5.9 inews says "bad message-id" 5.10 Why do all these "readclose" messages show up in my syslog? 5.11 "File exists writing symlinking article file -- throttling" 5.12 "cant fopen /.thread No such file or directory" 5.13 news.daily reports: "Expire had problems removing articles" 5.14 syslog: nnrpd[22560]: ? cant gethostbyaddr 198.3.24.3 Permission denied 5.15 syslog: ME cant nonblock 15 Operation not supported 5.16 innd: ME cant renumber ... lo too wide 5.17 innd: ME cant update_active control 5.18 syslog message: innxmit[1234]: max connect failed Error 0 5.19 Can't open "/usr/local/news/shlock955", Permission denied 5.20 INND: PID file exists -- unclean shutdown! 5.21 cant fopen /usr/lib/news/distributions 5.22 cant fopen /usr/lib/news/distrib.pats 5.23 ME cant exec in /usr/lib/news/capture No such file or directory 5.24 ME cant remalloc xx bytes Cannot allocate memory 5.25 innxmit says: Ignoring line "news/group/name/art_num art_id" 5.26 innxmit says; Can't connect to news.foo.bar Permission denied 5.27 innd: s (s might be replace by other letters) (in syslog ) 5.28 innd: site: closed 5:closed seconds 12 accepted 3 rejected 4 refused 5 5.29 syslog: nnrpd[13]: '1.2.3.4' bad_auth 5.30 Not a directory writing article file -- throttling 5.31 syslog: nntpd[13]: cant open ...../subscriptions ... 5.32 syslog: nntpd[13]: post ok ^A 5.33 news.daily: Can't open a/b/.LCK.overview, No such file or directory 5.34 syslog: innd: site buffered 5.35 syslog: innd: cant bind RCreader Permission denied ===================================================================== OTHER ERROR MESSAGES AND WHAT THEY MEAN ===================================================================== ------------------------------ Subject: (5.1) ld.so: Undefined symbol: _dbzwritethrough > Everything compiles correctly, but when I try to test rc.local I get: > > hermes# sh /usr/local/etc/rc.news > ld.so: Undefined symbol: _dbzwritethrough > > What am I doing wrong? This means that you are using a $INN/lib/dbz.c file that hasn't been patched with the $INN/lib/dbz.pch patch. The patching is automatic. Running "make" should do the patch without you even noticing. To force the code to be re-patched (i.e. copy the original to dbz.c and apply the patch to it), simply delete $INN/lib/dbz.c and run the usual "make". The Makefile does everything for you. Why might the patch fail and leave you with an unpatched dbz.c? 1) You don't have Larry Wall's (or the FSF's) "patch" program installed. It is available at ftp://prep.ai.mit.edu/pub/gnu/patch-2.1.tar.gz 2) Most C++ compilers based on USL's cfront come with a program called "patch" that does something completely different than Larry Wall's (or the FSF's) "patch" program. If your path is configured so that this program is found before Larry Wall's (or the FSF's) "patch" program, you will get an unpatched dbz.c. To fix this, delete $INN/lib/dbz.c, change your path, and do the usual "make". If this file is deleted the Makefile will do everything for you. See also section "5.2 The DBZ package" of the Install.ms document. ------------------------------ Subject: (5.2) Bad file number writing history file -- throttling The system ulimit was set restrict files from growing beyond a certain size and the history file was to large for the limit. Check the ulimit setting for the news user. The ulimit should be set to infinite. You need to figure out how to set this for user "news" no matter if the user logged in, is running from cron, or was run at boot up. ------------------------------ Subject: (5.3) log file fills with " 436 No space" innd issues this message if it cannot create a directory for a group, _no matter what the reason for the failure_. In most cases, /usr/spool/news (and the mount point it is symlinked to, if any) accidentally has permissions and ownerships that do not permit write access by innd (which runs as "news"). After chowning them to news, and setting the permissions to 755, everything should work fine. ------------------------------ Subject: (5.4) Why does my innd often die with the message "Can't sync history, interrupted system call" Are you running SunOS? See "Known Problems" section of the installation manual." To the best of my knowledge, nobody has seen this problem on any other system. ------------------------------ Subject: (5.5) Reply from ctlinnd: Can't send XXX command (sendto failure) The socket sendto wants to write to isn't available. This can either come from a dead server (e.g. send a ctlinnd shutdown twice) or from a process (find -exec rm{} comes to mind) that removed the socket from the filesystem. Look after _PATH_NEWSCONTROL in config.data and find out if all components of the path exist and are accessible. (inncheck could be of help ...) This condition will occur whenever news.daily is run as root, leaving the ownership of history, active, etc files as root. Change ownership of these files back to news and then restart. ------------------------------ Subject: (5.6) syslog msg: ME cant sendto CCreader bytes 4 No such file or directory (Rich Salz replies:) It usually means that some ctlinnd command timed out and gave up before innd could get around to replying. Always a problem with datagrams. :-) Usually not a problem in real life however. In INN1.3, the timeout stuff is handled better so most of these should go away. You can ignore the messages, but if it bothers you, edit news.daily and find this line: ctlinnd -s -t`wc -l <${ACTIVE}` renumber '' 2>&1 You can rewrite it to be something like this: COUNT=`wc -l <${ACTIVE}` ctlinnd -s -t`expr ${COUNT} \* 5` renumber '' 2>&1 ------------------------------ Subject: (5.7) syslog: cant symlink This usually means an intermediate directory doesn't exist. Usually "ctlinnd renumber" clears this problem, but doesn't remove the cause. This is usually an indication of some larger problem. Often it means that you have opted to use MMAP on an operating system (like Ultrix) that doesn't have a working mmap() function. However, this would only be the cause if you ignored the Install.ms *and* part 2 of this FAQ. So, obviously, this isn't the cause :-). Another cause might be that "ctlinnd renumber" fails because of fields in the active being too narrow. See #5.17 for how to deal with this. ------------------------------ Subject: (5.8) syslog: cant read Connection reset by peer This means that the client vanished or deliberately aborted the nnrpd TCP stream rather than closing it gracefully. This is a common situation, and it does not normally indicate a problem. Most, or all, of these messages are due to clients crashing or being aborted in the middle of a dialogue with nnrpd. For example, a PC or Mac user shuts off their machine at 5pm. Or, you are seeing the results of a bad design decision in the NewsWatcher newsreading program for the Mac. Future versions of NewsWatcher will be (hopefully) more graceful about closing connections. In other words, they should send "QUIT\r\n" on the socket, then close it. ------------------------------ Subject: (5.9) inews says "bad message-id" If this is a Solaris 2.x system, you didn't delete the lines mentioned in "SVR4, Solaris 2.x, and SCO ODT 3.0" in part 2 of this FAQ. ------------------------------ Subject: (5.10) Why do all these "readclose" messages show up in my syslog? Chris Schmidt says: The "readclose" message indicates that a remote connection to your server was not correctly terminated with the server-command "quit". This can have two reasons. First the line your feed uses to connect to you might be instable so that the connection drops every now and then. Solution: either ignore theses messages or find out why the line is unstable. The second reason for these messages could be a missconfigured client-program at your feed. This means the program (e.g nntplink) does close the connection without sending the "quit" first. If you configure a lower number for the exit-timeout (-e) than the close-timeout (-C) in nntplink then exactly this will happen. Solution: ask your feed to fix its nntplink-setup. Let me repeat that: If you are using "nntplink" your -e value must be higher than your -C value. ------------------------------ Subject: (5.11) "File exists writing symlinking article file -- throttling" QUESTION: I'm running INN 1.4, and the server throttles itself, saying "File exists writing symlinking article file -- throttling". Why? I have no clue, other than to note that the message is being emitted while innd/art.c tries to link a crossposted group. ANSWER: Innd wrote the article to comp/foo/123 and then tried to symlink it to alt/bar/128 and found that the symlink failed with errno == EEXIST. This generally only happens when your active file does not match your file/directory use. The three most common cases of that are: Trying to use MMAP on Ultrix Trying to use MMAP on (older) Linux Some strange interaction with tind. If you are using Ultrix or Linux, turn off MMAP. You don't have a choice in this. The Ultrix mmap() function does something completely different than the Sun/BSD mmap() function. The Linux function gives you some of the functionality that Sun/BSD mmap() function has, but not enough. (The Linux people expect to have it fully up to spec eventually, yeah right.) At least one person has reported problems with ICL DRS6000 SVR4 Unix when using MMAP. Try turning off MMAP if you find problems. Some people have also seen this, when the filesystem has problems. Shutting down the system and running fsck helped in that case. It has been reported that tind writes to the active file and this confuses innd (innd assumes it is the only process writing to the active file). If you are using tin, upgrade to the newest version of tin, it can read the NOV database rather than the "tin" database. To fix the active file (which may be corrupted), make sure nobody else is writing to the active file, then do ctlinnd renumber '' to get things synchronized again. If your history file is corrupt, you should do: ctlinnd renumber '' makehistory -buv (or -bunv see #6.6 for it) ctlinnd renumber '' (Note: the "makehistory" will take hours to run. See #7.53 on this.) IF YOU IGNORE THIS PROBLEM LONG ENOUGH (by issuing the "go" command via ctlinnd) you will eventually get a "innd: ME cant update_active control" message in syslog. The cause of this error is dealt with elsewhere in this FAQ (#5.17). ------------------------------ Subject: (5.12) "cant fopen /.thread No such file or directory" Q: nnrpd logs "cant fopen /.thread No such file or directory" hundreds of times a day although I installed trn-3 and maintain an overview database. Why doesn't trn use overview files instead of mthreads data? A: trn-3 tries to open .thread files (or use XTHREAD) first because $spooldir/db.init still exists. Delete it. ------------------------------ Subject: (5.13) news.daily reports: "Expire had problems removing articles" This message tells you that you need to look in the file ${MOST_LOGS}/expire.log to find out what really happened. On the other hand... Expire reports this if it goes through the entire expire process and didn't find any articles to remove. It is normal to get this error the first few days you are running INN. For example, if the smallest integer that appears in the 4th field of your expire.ctl is a "4", then you're sure to see this error the first four days you get an news.daily report. However, those first four days are when you are still learning the system and it can be very shocking to see the error. "Eeek! Did I do something wrong?" Nope, news.daily is just telling you that you have a virginal system. Rich writes a more technical explanation: | When using the "delayrm" keyword, news.daily calls expirerm to | actually remove the articles that expire listed in its "-z" file. | As distributed, expirerm calls fastrm with the "-e" flag. This | flag says "exit non-zero if nothing was removed." In the normal | case, it is an error if expire doesn't find anything to remove. ...and a system being 4 days old isn't the normal case. So you get the error. Ignore it. ------------------------------ Subject: (5.14) syslog: nnrpd[22560]: ? cant gethostbyaddr 198.3.24.3 Permission denied When someone connects to nnrpd, nnrpd does a reverse lookup on the clients IP address so it can look up the hostname in nnrpd.access. If the client's DNS information is incorrect, you will get this error. Make sure your SOA record is correct, as well as your in-addr.arpa data. Derek adds that another cause for this problem, at least under SunOS 4.1.x, is that nnrpd wasn't linked with the proper resolver library (statically or dynamically). Even when you've replaced Sun's fershlugger libresolv.a you've still gotta remind yourself to _use_ it properly. ------------------------------ Subject: (5.15) syslog: ME cant nonblock 15 Operation not supported I get the following "syslog" message in /var/adm/messages: Dec 2 20:40:04 venus innd: ME cant nonblock 15 Operation not supported Answer: (from paulr@umbc4.umbc.edu (Paul Riddle)) It turns out that this is happening because /usr/spool/news on the machine running innd is an NFS-mounted filesystem, and innd is trying to do an FIONBIO on my feed file, which is under /usr/spool/news/out.going. (tal@plts.org adds:) All news transports (INN, C news, B news) want the spool partition to be local. Newsreader can read from an NFS mounted partition without any problems but innd should only see local partitions. NFS has a blatant disregard for many of the file semantics that are needed for a good netnews implementation. If you don't agree, please feel free to prove the authors of B news, C news, and INN wrong. Include source code. :-) Greg Andrews adds: The spool can certainly be kept on an NFS filesystem without anything breaking, as the FAQ suggests. I've kept the spool on an NFS server, split between two NFS servers, and split between a local filesystem and two NFS servers. Reads and writes over NFS tend to be slower than over local disk, even if the NFS backbone is 100BaseT or CDDI. The out.going filesystem can be put on an NFS server, but the file locking becomes a problem on some Unixes. I bypassed that by borrowing the lockfile technique I saw in the old "cleanup" release of C-News, and writing a replacement for nntpsend in Perl. I also eliminated the numerous 'ctlinnd flush' commands that can choke a busy server. The lockfile technique is pretty simple and seems to work well for multiple machines mounting a common out.going filesystem via NFS. The nntpsend replacement script creates a lockfile unique to itself (using the machine name and PID), and locks sites by hard linking site lockfiles to its own lockfile. The newslib filesystem can also be put on the NFS server, though the only advantage is a minor one: If everything's on the same NFS server, you only need to mount one filesystem on the client machines. Systems without unix-domain sockets sometimes see this error. Just ignore it. ------------------------------ Subject: (5.16) innd: ME cant renumber ... lo too wide When you try to renumber your active there are articles in your spool with numbers higher than what will fit in the fields in the active. Look under innd: ME cant update_active control below for how to fix it. ------------------------------ Subject: (5.17) innd: ME cant update_active control What does "innd: ME cant update_active control" mean? Look at your active file. One of the fields is "99999" and has to be incremented to "100000" but there is no space. Shut down innd ("ctlinnd shutdown x"). Edit your active file (see the "Safe way to edit the "active" file?" question in INN FAQ part 6) to add more leading zeroes to all the numbers. You can use the following for this: 1. ctlinnd throttle 'updating active' 2. awk '{printf "%s %.10d %.10d %s\n", $1, $2, $3, $4}' active > active.new if your awk printf spaves instead of leading zeroes in this step, then try the following instead of step 2: awk '{printf "%s %010d %010d %s\n", $1, $2, $3, $4}' active > active.new or perl -lane 'split;printf "%s %.10d %.10d %s\n", @F' active > active.new 3. mv active.new active 4. ctlinnd reload active updated 5. ctlinnd go 'updating active' See also #5.11. ------------------------------ Subject: (5.18) syslog message: innxmit[1234]: max connect failed Error 0 John Line writes: If you get syslog messages like "innxmit[1234]: max connect failed Error 0" when using nntpsend, it probably means you messed up a line in nntpsend.ctl (specifically, missed out one of the first two fields). While nntpsend.ctl is an obvious place to look for an nntpsend problem, there is nothing obvious to link the error message directly to the problem, because the text "max" is actually something invented by nntpsend when processing the file, and doesn't exist in nntpsend.ctl. It means the next-to-last field was null, but was the second field when it should have been the third! NB Remember to try inncheck when you have problems like this. I only just thought of it, after finding the problem the hard way, and it immediately reported "nntpsend.ctl:18: malformed line." ------------------------------ Subject: (5.19) Can't open "/usr/local/news/shlock955", Permission denied This usually means you don't have /usr/local/news owned by "news". The first time you run "make install" it should set the proper ownership if you run "make install" as "root". ------------------------------ Subject: (5.20) INND: PID file exists -- unclean shutdown! This just means your machine crashed or you didn't shutdown innd properly and THEREFORE rc.news is doing a bit of cleanup work before it starts innd. There is not much for you to do. You might run makehistoy or fixhist.pl to find articles that are on disk, but not in history. ------------------------------ Subject: (5.21) cant fopen /usr/lib/news/distributions Step 1: Can you "cat" this file? Step 2: You can't? Does it exist? Step 3: It doesn't? That's because you have to create it yourself. It should list every distribution your users might want to know a description of, starting with the local one. Step 4: Here's a sample file to start from. It's appropriate for a New Jersey site: nj New Jersey ny New York nyc New York City ne North East, USA usa United States of America na North America ------------------------------ Subject: (5.22) cant fopen /usr/lib/news/distrib.pats A sample distrib.pats comes with the distribution and should be in your $inn/site directory automatically. The sample needs the following modification: Remove the line: 10:news.software.nntp:inet News.software.nntp has moved from inet groups to normal groups end 1994/begin 1995. If you get this error it sounds like something was badly configured on your machine. ------------------------------ Subject: (5.23) ME cant exec in /usr/lib/news/capture No such file or directory The newsfeeds file includes lines that looks like this: ## Capture all Foo, Incorporated, postings #capture\ # :*/foo\ # :Tp,H2:/usr/lib/news/capture %s That's just a sample of how one might capture articles. There is no capture program that comes with INN. It's just an example of how to use the Tp,H2 flags. Don't uncomment anything that you don't want to activate! ------------------------------ Subject: (5.24) ME cant remalloc xx bytes Cannot allocate memory This probably means that innd wants to grow bigger than what the actual limit for a single process is. To solve this either rebuild your kernel with a different default max, or add "unlimit datasize" to the beginning on your rc.news file. On some OS (e.g. FreeBSD 2.1.x) there might be some problems when using the supplied malloc. Linking with -lgnumalloc helped (after Joe Greco ). For HP-UP see also 'HP-UX tips' in part2 of the FAQ (#2.6). ------------------------------ Subject: (5.25) innxmit says: Ignoring line "news/group/name/art_num art_id" Q: Innxmit logs the above error message - what does this mean? You set the parameters for the feed wrong in newsfeeds - try Wnm instead of Wmn. See also newsfeeds(5) and innxmit(8) for further information. ------------------------------ Subject: (5.26) innxmit says; Can't connect to news.foo.bar Permission denied If you get this error, then first look if permissions of all files are correct. If yes try out innxmit foo.togo If this works you have some problems with name resolution. You might use the ip-number in nntpsend.ctl instead of the hostname next time. ------------------------------ Subject: (5.27) innd: s (s might be replace by other letters) (in syslog ) Q: What do these innd: s (or other innd: ) mean? Innd logs to syslog when it receives a command from ctlinnd. The letter corresponds to the command that is send to innd. For a list of commands, refer to include/inndcomm.h ------------------------------ Subject: (5.28) innd: site: closed 5:closed seconds 12 accepted 3 rejected 4 refused 5 This isn't really an error but an informative message of inn. It also appears with 'checkpoint' instead of 'closed'. This message tells you how long a connections from the remote existed, how many articles were accepted from this remote site, how many innd already had of those offered and how many were rejected of some reason (see below). If you get a lot of rejects from a site then you should investigate, as there might be some problems. Erland Sommarskog, explains further: Rejected articles are articles in groups that you don't have in your active file, or you ban in hosts.nntp. This could be groups you have missed to add, it could be groups you don't want. Also articles which are already too old for you to accept (-c switch to innd) fall in this part. If you get many rejects then you might also check out the clocks on the sender and receiver machines as it might be that with wrong clock settings articles get refused which seem to be to old or posted in future. Refused articles are articles that are already present in your history file, and which for some reason are being offered to you again. If you have more than one incoming feed, you are likely to get a fairly high number in the Refused column. If you are a leaf site with only one incoming feed you can still get high numbers in this column, if you have a longer expiration time (including /remember/) than you feed has. ------------------------------ Subject: (5.29) syslog: nnrpd[13]: '1.2.3.4' bad_auth A Newsreader that could be allowed via nnrp.access did send bad authinfo commands. This could either be that the client has a password in nnrp.access and sends a wrong one or the client needs no password and sends one even if it does not need to. ------------------------------ Subject: (5.30) Not a directory writing article file -- throttling This typically means that in the spool there is a directory in the spool that thinks it is a file. This seems to happen when the machine running innd crashes, and the spool gets corrupted. Fsck then tries to make sense of the mess it finds; sometimes it guesses wrong. Here is a little script that finds the offending file and disposes of if: #!/bin/sh # # change this line to your news spool NEWS_LOC=/var/spool/news find ${NEWS_LOC} -type f -print | # list all files tr -d [0-9] | # get rid of numbers grep -v "overview" | # get rid of .overview files egrep -v "/$" | # everything w/ / at end of line sed -s "s/^/rm /" | # put rm in front of file sh -s # it's history or alternatively: find ${NEWS_LOC} -type f -name "[a-z]*" -print | xargs rm (From: Carlso Castro and Matthias Urlichs ) ------------------------------ Subject: (5.31) syslog: nntpd[13]: cant open ...../subscriptions ... This is a new option in unoff4. First look if _PATH_NNRPSUBS is correctly set. If yes, then just fill it with information ... . The subscriptions file contains what the NNTP "LIST SUBSCRIPTIONS" command returns. Some newsreaders, such as tin, use this command to get a default set of groups that people are subscribed to if they do not have a .newsrc. If you don't want to use it, there are no side-effects that I know of beyond the messages in your log. ------------------------------ Subject: (5.32) syslog: nntpd[13]: post ok ^A Q: What is this? Normally posting lines look like nntpd[13]: post ok . A: Your posting was posted to a moderated group and is now sent by mail to the moderator who will (or not) post it to news. See also: #6.7, #6.8 ------------------------------ Subject: (5.33) news.daily: Can't open a/b/.LCK.overview, No such file or directory Expireover goes through the active file and tries to remove old entries of overchan records from the spool. If now a group exists, that is new i.e. that exists in active, but for which no articles have been received, then there is no spool dir for that group. Expireover tries to make a lock file in the directory, which fails, so it prints the above message. See also #4.19, #6.30, #7.21 ------------------------------ Subject: (5.34) syslog: innd: site buffered I run INN 1.5 and see the following in syslog - what does it mean? | Jan 9 03:10:02 cactus innd: news.foo.bar.com buffered It means either your newsfeeds file has too many entries to handle in the normal way, or you've run out of file descriptors. This isn't fatal, but a warning message. ------------------------------ Subject: (5.35) syslog: innd: cant bind RCreader Permission denied This means that innd can't bind to port 119 as either inndstart is not suid root or not started as root. Normally the install should take care of this. inn-1.7.2/FAQ/INN-faq_part70100644000175100001440000015370206443103542013477 0ustar mdusersNewsgroups: news.software.nntp,news.software.b,news.answers Approved: hwr@pilhuhn.de Followup-To: news.software.nntp Subject: INN FAQ Part 7/9: Problems with INN already running Summary: This article is part 7 of a multi-part FAQ: Part 7: Day-to-day operational questions. This includes general questions asked once INN is running for a while. Posted-By: post_faq 2.10 Archive-name: usenet/software/inn-faq/part7 Last Changed: $Date: 1997/09/16 01:25:57 $ $Revision: 2.25 $ Part 7 of 9 INN FAQ Part 1: General and questions from people that don't (yet) run INN INN FAQ Part 2: Specific notes for specific operating systems INN FAQ Part 3: Reasons why INN isn't starting INN FAQ Part 4: The debugging tutorial (setup of feeds etc.) INN FAQ Part 5: Other error messages and what they mean INN FAQ Part 6: Day-to-day operation and changes to the system INN FAQ Part 7: Problems with INN already running INN FAQ Part 8: Appendix A: Norman's install guide INN FAQ Part 9: Appendix B: Configurations for certain systems ------------------------------ Subject: Table Of Contents for Part 7/9 ===================================================================== TABLE OF CONTENTS FOR PART 7/9 ===================================================================== INN IS RUNNING, BUT I HAVE THIS SMALL PROBLEM...: 7.1 XHDR says Bad Article Number 7.2 Everything I receive, I re-feed to the feeder 7.3 Suddenly my active and history files are owned by root! 7.4 How come my host name comes out twice in the Path line? 7.5 Expire had problems and won't run again after fixing the problem 7.6 Expire says "Group not matched (removed?) -- Using default ..." 7.7 Expire reports 'Can't replace history files, Cross-device link' 7.8 Why doesn't this newsfeeds entry do what I want? 7.9 Why am I forwarding cancel messages for articles in comp.foo 7.10 Debugging someone that is feeding you. 7.11 Feeds suddenly can't connect anymore! 7.12 I'm getting groups sent to me that I don't want. 7.13 When my feeder connects, I get articles but they don't take what's waiting for them. 7.14 Directories are being created with wrong permissions. 7.15 Why am I getting alt.sex.pictures even though I have... 7.16 More about the "to.*" groups 7.17 What's a decent syslog.conf configuration? 7.18 INN batcher writing "#!rnews 0" separators 7.19 Posting while throttled doesn't work 7.20 I am not getting all the articles, but my feeder is sending a full feed 7.21 overchan can't keep up. 7.22 "newgroup" control messages aren't being executed 7.23 What do these history.n.* files do? 7.24 Out of inodes but still space left on disk 7.25 Server throttled No space left on device writing article file 7.26 Is there a automatic way to update newsfeeds? 7.27 Reloading hosts.nntp is slow. 7.28 What are these "xforte" or "xindex" commands that appear in my logs? 7.29 My active is not updated frequently enough 7.30 Feedentries in newsfeeds are ignored 7.31 Help, my active file got corrupted (or deleted)! 7.32 Help, my history file is getting real big! 7.33 Help, INND gets real big 7.34 Help, my history file got deleted! 7.35 I'm seeing duplicate message-id's in my history database! 7.36 Getting lots of duplicate articles 7.37 Inn send mail to 'rmgroup' or 'newgroup' 7.38 Ctlinnd cancel doesn't cancel my articles .. 7.39 Inn hangs during renumbering the active file 7.40 Some local postings don't make it to remote, but others do 7.41 Expire does no longer work 7.42 news.daily complains about unknown entries from syslog 7.43 Innd writes to syslog: DEBUG ERROR SITEspool: trashed 7.44 My feed does have different groups in active 7.45 INN is only slowly responding 7.46 What does 'Reserved Expiring process xxx' mean? 7.47 What happens to cancels if they arrive before the article ? 7.48 I use funnel feeds and INND dumps core 7.49 NNTP-Posting-Host is localhost.do.main even if host has a name 7.50 uuxqt says: rnews exit status 1 7.51 innd get a non-zero ``nice'' value? 7.52 innd runs as root, even if configured to run as 'news' 7.53 Makehistory is slow on inn 1.x , x<5.1 7.54 Expire is slooooooow 7.55 Why are multiple innwatch's running? 7.56 I upgraded to INN 1.5.1, and peers have trouble feeding me. 7.57 I upgraded to INN 1.5.1, and it takes clients a long time to connect. 7.58 My server gets slower and is busy doing io ===================================================================== INN IS RUNNING, BUT I HAVE THIS SMALL PROBLEM... ===================================================================== ------------------------------ Subject: (7.1) XHDR says Bad Article Number Q: When I do a XHDR command the INN NNTP server may give me article numbers which is not valid (get 403 Bad Article Number when requesting the article text). Is this normal? A: Absolutely not! Perhaps DIR_STYLE is wrong? ------------------------------ Subject: (7.2) Everything I receive, I re-feed to the feeder "It seems that all the articles sent to me are resent back to my provider. I only want to post those articles which have been locally generated at my site back to my news feed provider." or "I feed a site named foo.bar, but it puts something besides foo.bar in their Path: header" Let's look at a typical Path: line: Path: plts!sdl!newsgw.mentorg.com!uunet!gatech!howland.reston.ans.net!agate!barrnet.net!jfrank.com!usenet As a post goes from system to system, each site prepends their sitename to the line. Usually a site uses their FQDN, but sometimes they register something with the UUCP Mapping Project which makes sure no two sites use the same name. In the above, we see a couple FQDN's and a couple sites that are registered with the UUCP Mapping Project. INN will not feed this article to any feed who's name appears in the Path: header. Suppose you have a feed to/from barrnet.net that looks like this: netnews.barrnet.net:*,!control,!junk:Tf,Wnm: This means "send all newsgroups except control and junk, but not if the Path: line includes 'netnews.barrnet.net'". That's fine, but as we see in the above Path: example, BarrNet puts "barrnet.net" in the path, even though their netnews machine is called "netnews.barrnet.net". Therefore, we change the newsfeeds file to include a "/barrnet.net" which means "exclude posts that have gone through barrnet.net". netnews.barrnet.net/barrnet.net:*,!control,!junk:Tf,Wnm: Now you won't feed to netnews.barrnet.net articles that have already gone through barrnet. The best way to solve this problem is: 1. Read the Path: line from an article that has passed through that site already. 2. Insert that sitename into the feeds description in newsfeeds. 3. "ctlinnd reload newsfeeds fixed_feed" OTHER USES: Suppose two sites have very reliable NNTP feeds from uunet and psinet but still want a feed between each other to increase redundancy. They might set up feeds like: othersite/uunet,uupsi:... so that they aren't sending articles that have already reached two of the biggest sites on Usenet (and therefore must have gotten good distribution already), but will pass on everything else. ------------------------------ Subject: (7.3) Suddenly my active and history files are owned by root! rc.news runs from root. After that, everything else should run as news. It sounds like you've run news.daily as root by mistake. Make sure all your cron jobs run as news and you'll be fine. If you have an old "cron" system, you might consider replacing yours with one of the many public domain replacements. If you can't create a different "crontab" for each user, the idiom is: 0 * * * * * su news -c '/do/this/as/news' ------------------------------ Subject: (7.4) How come my host name comes out twice in the Path line? The INN server puts its name in the Path line of every article that it receives. Obviously, it has to do this. The default configuration has inews put the local host in the Path header. If nobody posts on the server and you use fully-qualified domain names on your workstations, then everything works the right way. (If `hostname` doesn't give an FQDN on your machine, you can work-around this by setting the "domain" value in inn.conf; remember that innd never re-reads inn.conf. You must "ctlinnd shutdown x" and then re-start the server). Many people don't want the client machines to put their name in the Path header. To do this, set INEWS_PATH to DONT. Finally, let me say that it is probably a mistake to have a "pathhost" line on any machine other than your server if you set INEWS_PATH to DO. If you doubt this, please trace the article flow for yourself. If you are curious about the effect of INEWS_PATH, read the nroff source -- not the formatted output -- of doc/inews.1 ------------------------------ Subject: (7.5) Expire had problems and won't run again after fixing the problem When expire starts up it "reserves" the server so that nobody else can pause or throttle it. This prevents anyone else from coming in and modifying the history database. If expire bails out because of a bad error (e.g., your expire.ctl has syntax errors) it leaves the server reserved so that no maintenance will be done until a good expire run has occurred. To unblock the server, use the ctlinnd "reserve" command with an empty string argument. See also #7.46. ------------------------------ Subject: (7.6) Expire says "Group not matched (removed?) -- Using default ..." Expire says: Group not matched (removed?) alt.techno-shamanism -- Using default expiration Group not matched (removed?) misc.computers.forsale -- Using default expiration Group not matched (removed?) de.rec.sf.startrek -- Using default expiration YOU DID NOTHING WRONG! That just means that you've removed those newsgroups groups and expire is slowly removing articles from the spool as they expire. Eventually the articles will all have been deleted and so will these messages. Here's a neat trick to make deleted groups go away at the next expire instead of hanging around waiting for their articles to expire in a timely manner. Using this combination of lines at the *start* of expire.ctl: *:A:0:0:0 *:U:0:7:31 *:M:0:14:365 will cause groups which are neither moderated nor unmoderated to be discarded - the only such groups are deleted ones. Thanks to Ian Phillipps for this tip! ------------------------------ Subject: (7.7) Expire reports "Can't replace history files, Cross-device link" If your directory where your history is does not have enough space left for two copies of the history, you can also expire in another directory. But you must tell expire to do so - failing to do so produces the above message. You can either tell it news.daily by adding a expdir=/some/dir flag or by adding the -d flag when starting expire. In news.daily, there is a variable called 'EXPDIR' which you can set. This way you never accidentally run an news.daily by hand and forget the expdir option. ------------------------------ Subject: (7.8) Why doesn't this newsfeeds entry do what I want? "foo.com:alt,!alt.sex" A newsfeeds entry is not a sys file (C News) entry. Please read newsfeeds.5. You might also find the sys2nf program in the frontends directory useful, as well as the inncheck Perl script that is found in the samples directory. The INN Configuration FAQ has cook-book examples of the steps required to install a NNTP feed, UUCP feed, and NNTP via nntplink feed. ------------------------------ Subject: (7.9) Why am I forwarding cancel messages for articles in comp.foo when I explicitly have !comp.foo in the newsfeeds entry? Control messages can be explicitly forwarded, so a control message to comp.foo is forwarded to sites that receive either comp.foo or control. Please see the "Control Messages" section of innd.8. As that documentation says, you probably want to put "!control" in the subscription list for most of your newsfeeds. ------------------------------ Subject: (7.10) Debugging someone that is feeding you. David Myers suggests that if a neighbor complains that their feed to you doesn't work: (1) make sure they've read the man pages, and (2) have them send a copy of their newsfeeds file. Truly sage advice! ------------------------------ Subject: (7.11) Feeds suddenly can't connect anymore! Q: How come feeds tell me they can't connect to me any more? A: When innd starts up it reads the hosts.nntp file and looks up the IP addresses for all the entries mentioned there. The problem is that this data is dynamic (sometimes people change IP addresses), and innd never goes back to check. If your system stays up for days and one of your feeds changes their IP address (or has a new CNAME), innd will reject them. Rich planed to handle this in INN1.5, but for now you might find it useful to do a "ctlinnd reload hosts.nntp" out of cron every day or so or when you notice there's a problem. Here is a sample crontab entry to use: (news should run this) 55 7,12,17,22 * * * /usr/local/newsbin/ctlinnd -s reload hosts.nntp crontab I hope people vary the time this runs. If a huge number of INN hosts, many running NTP so their clocks are within a few ms., all kick off DNS lookups at exactly the same time, the internet traffic could get "interesting". Try setting the minutes value to the time you added this entry to crontab rather than everyone using "55". In fact, if everyone used their birthday plus 1 if they are born on an odd month, that would spread it out just fine. ------------------------------ Subject: (7.12) I'm getting groups sent to me that I don't want. Tell the system administrator(s) of the machine(s) that feed news to you to stop sending those groups. There is no other way to do it. (In B or C News, the groups would end up in junk; at least with INN they are not taking up space. You should compile with WANT_JUNK set to DONT). If the people that feed you use B news or C news, remember that they don't use a "newsfeeds" file. They use a file called "sys" which has a completely different format for specifying newsgroups. ------------------------------ Subject: (7.13) When my feeder connects, I get articles but they don't take what's waiting for them. I hate to say this, but this really shows that you haven't RTFMed very much. News is not automatically bidirectional (it's like SMTP, not UUCP). If you want to send things out you will have to make sure that you run send-nntp or nntpsend from cron. nntpsend is easier and elsewhere in this document there are cookbook examples of what to add every time you set up a new feed. James Brister is thinking about adding a 'turn' command to nntp to initiate turning sender to receiver and vice versa. ------------------------------ Subject: (7.14) Directories are being created with wrong permissions. > Question: >When I received news for /var/spool/news/foo/bar for the first >time, the directories got created: > ># ls -lgR foo >total 1 >d-wx-w-rwx 2 news news 512 Feb 9 00:03 bar/ > >What did I do wrong? > >## Mode that directories are created under. >#### =()@>()= >GROUPDIR_MODE 2775 Answer: You forgot a zero in front of this number, for the C compiler to interpret it as octal instead of decimal. ------------------------------ Subject: (7.15) Why am I getting alt.sex.pictures even though I have "ME:!alt.sex.pictures" in my newsfeeds file? The active file is the definitive list of what newsgroups you receive. INN's ME entry is different from C News and B News; please see newsfeeds.5. If you do not want to receive alt.sex.pictures, ask the system(s) that send you news not to send it to you. (You would have to do that no matter what news system you are running.) ------------------------------ Subject: (7.16) More about the "to.*" groups (Thanks to jmalcolm@sura.net (Joseph Malcolm) for supplying these answers.) >1) Why did my local INN act on the sendsys posted to to.neighbor? to.* groups aren't magic to INN. Your system received the message, it acted on it. >2) Why did my neighbor send the cmsg to all of his neighbors? See 3. >3) Is is related to having the "control" group in our newsgroups patterns? Yes. > The INN docs say you probably don't want to do this, but they don't say > why. Actually, they do. This is from innd(8): Sites may explicitly have the ``control'' newsgroup in their subscription list, although it is usually best to exclude it. If a control message is posted to a group whose name ends with the four characters ``.ctl'' then the suffix is stripped off and what is left is used as the group name. For example, a cancel message posted to ``news.admin.misc.ctl'' will be sent to all sites that subscribe to ``control'' or ``news.admin.misc''. There is also a pointer to this in newsfeeds(5). > But I still need it in my active file, right? Yes. ------------------------------ Subject: (7.17) What's a decent syslog.conf configuration? The configuration will be different for each site, but here is what Greg Earle recommends as the lines for the "news.*" related part. Remember that most syslog's require tabs, not spaces. Greg's canonical SunOS 4.1.x INN-related syslog.conf entries (which can be merged into your current configuration): # # INN stuff # ## Send critical messages to everyone who is logged in and to the console. news.crit * news.crit /dev/console ## Log news messages to separate files. ## Note that each level includes all of the above it. ## =()@/news.crit>()= news.crit /var/log/news/news.crit ## =()@/news.err>()= news.err /var/log/news/news.err ## =()@/news.notice>()= news.notice /var/log/news/news.notice If you don't want /var/log/messages to be crowded by messages from news add the following to the line, where /var/log/messages get logged: news.none so that the line reads (as an example): *.err;kern.debug;auth.notice;mail.crit,news.none /dev/console On some systems you can add a flag to some entries in order to instruct syslog not to sync after each write. This might help raising throughput. Or else move the logs from busy file systems if that flag is not available. ------------------------------ Subject: (7.18) INN batcher writing "#!rnews 0" separators >Outgoing UUCP batches from here are going out with "#!rnews 0" at >the head of each article. Most common cause: your newsfeeds entry has "Wnm" not "Wnb". (If only "Wn" is specified, the batcher gets the size itself, but this is a performance loss). Other reasons: batchfiles have something other than a single space between article filename and size batchfiles lack size information (all the articles sizes will be read from the batch file as zero) ------------------------------ Subject: (7.19) Posting while throttled doesn't work >I want to be able to allow my users to be able to post articles when >innwatch has throttled the system when the spool disk is "full". Cannot be done in 1.4. In 1.5 nnrpd will spool the post for the user. When the server is running again, then running rnews -U will feed them to innd. ------------------------------ Subject: (7.20) I am not getting all the articles, but my feeder is sending a full feed (From Carlos Castro ) Either your feeder is not keeping up with its feeders, or you are not keeping up with the news flow. Disk IO is probably the biggest news bottleneck. Usually a full feed is more than a single Fast SCSI II disk can handle. Having 2 or more disks for the spool is suggested in either a striped configuration (using ODS for Solaris or MD for Linux) or a split spool. It is also recomended to have the disks spread out over multiple controllers. It is best to compile your system with MMAP if it can support it. Run innd at a priority of -5 or -10 and see if it performs better. Setting NICE_KIDS to 10 will also give innd more CPU on news servers heavily loaded with many nntplinks and nnrps. If you have many outgoing feeds you might want to keep the size of the out.going files relatively small.... It takes quite a bit of effort to write to the end of a very long file. ------------------------------ Subject: (7.21) overchan can't keep up. > About once a month or so, I get the following warning messages: > > Jan 20 07:20:22 optima innd: overview!:31:proc:9193 cant flush count 14639 Operation would block > Jan 20 07:20:22 optima innd: overview! spooling 14639 bytes or > there's a file "overview!" in /usr/spool/news/out.going with stuff in it. > > Should I be doing anything more with this than ignoring it, and maybe > occasionally deleting it (it just grows)? This happens because innd is feeding info to overchan faster than overchan can process it. The overflow is sent to the file "overview!". This file can be deleted, as nnrpd will grab the missing data out of the articles "manually". The slow-down won't be noticed, much. You can "expireover -a" to "fill in the holes". To prevent this in the future, you need to make overchan run faster. This is easy to do. There are two things to do: 1. Increase the size of many of your kernel buffers. In particular, increase buffers relating to directory caches (the "namei" cache", to mention one). If you use SunOS, change "maxusers" to 200. Ignore the variable's name. This variable is used to calculate most of the other buffer sizes, etc. and 200 is good for a system that is as overworked as, say, a machine running netnews. Do this only if you have enough RAM. I can't exactly say what is 'enough' but for a machine with 48MB 200 seems to be too big (64 is ok here). The problem seems to be that the kernel then needs too much space and runs out of it. 2. (this is more important than #1) Move the .overview files out of the /var/spool/news hierarchy. For example, moving the overview files into /var/spool/news/over.view made things fast enough on one machine that the problem went away. To do this: change "_PATH_OVERVIEWDIR" in "config.data", recompile, and "make install". You will need to recompile any newsreaders that read via NFS or off the local disk. For really great performance, put the NOV files on a separate disk. (Not just a separate partition, a separate disk or spindle.) This one-liner will generate a shell script that will move your NOV files: awk '{ print $1 }' /usr/lib/news/active | tr . / | awk '{ print "mkdir -p /new/location/" $1 ; print "mv " $1 "/.overview /new/location/" $1 "/.overview" }' WHY THIS WORKS: Why does doing all this speed up overchan? overchan works by opening the proper ".overview" file, appending 1 line to it, then closing the file. If you have the ".overview" file in the same directory as 10000 articles then opening the ".overview" file will take a huge amount of time. The open() call literally searches though about 5000 (half of 10000) file names to find ".overview". If you move your ".overview" files so that each one is in it's own directory, (say, /usr/spool/news/over.view/{group}/{name}/.overview) then open() is searching through 3 files ( ".", "..", and ".overview") to find 1 file. ( O(N/2) where N=10000 vs. N=3... and you thought those first year CS classes would never be useful!) There isn't much you can do to make the "append" and "close" steps much faster, except maybe install a PrestoServe or similar write-cache, and that won't help very much. Profiling overchan (with PureSoft's Quantify product) found that the open() call was around 80% of the execution time of overchan. That was reduced to 40% when I moved the ".overview" files to their own directory. With the change, overview's profiling statistics are pretty flat. (which is good). IF YOU CAN'T DO THE ABOVE CHANGES: Run "expireover -a" to fix the problem temporarily. However, it will come back. DO NOT try feeding the "overview!" file to overchan manually. (1) overchan doesn't do any locking and you'll have two overchan's running at once. (2) overchan only appends to the ".overview" files. If you've gotten any articles since the "overview!" file was created (you will have) then you'll be appending told old entries that are out of order. Your ".overview" files must be in sorted order for the other utilities to work right. See also #4.19, #5.33, #6.30 ------------------------------ Subject: (7.22) "newgroup" control messages aren't being executed > "newgroup" control messages aren't be executed The usual blame for this is _PATH_EGREP points to a grep that doesn't understand regular expressions. For example, GNU grep only understands regular expressions if it is called "egrep" (i.e. not "gnuegrep" or "egnugrep"). Make sure you have a link or symlink between egnugrep and egrep. You then need to modify config.data so that _PATH_EGREP is /your/local/path/egrep and NOT /your/local/path/egnuegrep. Then recompile and "make install" to have the new binaries and shell scripts installed. You also want to check the syntax of your control.ctl file. ------------------------------ Subject: (7.23) What do these history.n.* files do? Q: There are history.n, history.n.dir and history.n.pag lying around - what are they good for? These files come from expire and are the new history. Without errors these files should disappear after expire is done. If they stay after expire is finished, you most certainly have a problem with disk space on the disk where history.* is or if not a broken line in history, which caused expire to bail out. ------------------------------ Subject: (7.24) Out of inodes but still space left on disk If you have still space on your disk but no more inodes then you should consider rebuilding the partition on which your spool is. Default options for filesystems are mostly to use 4k / inode. For a newsfs this isn't appropriate, as articles are in average under 3k. So create your newsspool with 2k per inode. If you rebuild you also could adjust the values for block-/fragsize to 4096/512 so you'll get more space out of your disk than on 8192/1024 (this will be a bit slower than 8k/1k for articles bigger than 4k, which are a minority so don't use it on a partition dedicated to alt.binaries) ------------------------------ Subject: (7.25) Server throttled No space left on device writing article file If df still shows you plenty of space then look if you have enough inodes free. If not then refer to "Out of inodes but still space left on disk" ------------------------------ Subject: (7.26) Is there a automatic way to update newsfeeds? >Does anyone know of a way to automatically update the newsfeeds file? >I'm looking for something that will allow a site to send a request We use gup at various locations with big success. You can find it in ftp://ftp.isc.org/isc/inn/unoff-contrib One sends a mail to gup, which gets processed and a new group list for the site is written. Then from cron gupdate runs and gathers all site files to your newsfeeds. ------------------------------ Subject: (7.27) Reloading hosts.nntp is slow. >" but I need to reload hosts.nntp each time I add >a feed. That takes about 15-25 minutes to happen. Write a small script/program that parses hosts.nntp.txt and writes only IP addresses to hosts.nntp and innd will reload it nearly instantaneously. or you can lookup on each of the hosts before doing a ctlinnd reload. Then it should be almost instantaneous. One could write up a script for that. Somebody has to take the time to convert FQDN's to IP addresses, but there's no requirement that it be innd. ------------------------------ Subject: (7.28) What are these "xforte" or "xindex" commands that appear in my logs? Q: I see "xforte" commands in syslog as unknown commands - where do they come from? Version 0.55 of Forte Free Agent uses this to make it so a news server will not timeout even if the user is idle. It appears to happen once per minute when the user is idle. After Version 0.55 Forte uses the help command as the anti-idle command. So if you are just annoyed by the messages in syslog, encourage your users to upgrade to a newer version. In versions 1.0 and 0.99+ this feature can be turned off. These anti-idle commands are a very bad behaviour, as the news reader does not disconnect, but occupies resources. Pine seems to do this behaviour via 'NOOP'. Xindex,Xuser,spooldir and xmotd come from tin. It is documented in the sources that these commands don't work with inn. You can disable them via -DDONT_HAVE_NNTP_EXTS (tin 1.2) -- look in the INSTALL document. In tin1.3 they are disabled by default. ------------------------------ Subject: (7.29) My active is not updated frequently enough This is on hp9000/350 with MMAP enabled, but could surely also be used with other configurations: >the active file does not seem to flushed to disk frequently enough. >So that when I use nn to access the newserver through nntp it does >not see the new articles posted until a few (up to 5) hours later. First of all check the value of ICD_SYNC_COUNT in config.data. froh@devnull.franken.de (Frohwalt Egerer) writes: In the source look for the place where INN would write the active file back to disk if MMAP was turned off. At that place I added a 'msync()' to the 'MMAP' branch to make it work on my university's HPs. ------------------------------ Subject: (7.30) Feedentries in newsfeeds are ignored > I have the following newsfeeds and INND says no feeding sites: ## xlink/xlink.net,xlink1,xlink1.xlink.net,blackbush.xlink.net:\ xlink/xlink.net,xlink1:comp.*:Tf,Wnm: The solution is that - although the first line of the two is a comment - the line continuation at the end still works -- so the valid entry for xlink is within the comment and therefore ignored. ------------------------------ Subject: (7.31) Help, my active file got corrupted (or deleted)! First off, do NOT run makeactive(8) to make a new one! Not only does this command take a long time to run, but the result is usually garbage. Groups that should be marked as moderated aren't, and you'll usually create lots of spurious groups which were deleted previously or didn't exist. You'll end up spending a lot of time cleaning up your active file when you're done. Every time news.daily runs, it saves a compressed copy of the current active file in _PATH_MOST_LOGS/OLD/ (e.g. /var/log/news/OLD). Also, every time a newgroup or rmgroup command is issued, the previous copy of the active file is saved as "active.old". Should your active file get corrupted or deleted, you have lots of backup copies lying around. You should also include your _PATH_NEWSLIB in your daily backups, so that your history and active files get backed up to tape. If you get a catastrophic disk failure, you can get back in business much much faster if you have tape backups of these files. The easiest way to recover from a corrupted active file is this: 1. Shut down INN 2. mv active active.corrupt 3. cp active.old active OR cp /var/log/news/OLD/active.1.Z . (or .gz if you use gzip) uncompress active.1 (or gunzip if you use gzip) mv active.1 active 4. Restart INN If INN does not do a renumber on startup (you'll know if it does if 'ctlinnd mode' hangs for several minutes on startup), then force a renumber of the active file with: 5. ctlinnd renumber '' ------------------------------ Subject: (7.32) Help, my history file is getting real big! It's supposed to be big. You want it to be big. Don't ever run makehistory to build a new database! It will take hours or days to run. The resulting database will be smaller, but that's because you have removed entries for expired articles, leaving yourself vulnerable to duplicates. It's hard to estimate exactly how much you'll need, since it depends a lot on how much news you carry as well as for how long. The partition which holds your history datebase must have at least enough room for two copies of the database, since expire(8) needs to build a new one while the old one is still in use. If you can't afford free space on this partition for two copies, but have plenty of space elsewhere, then you might use the "-d" flag to expire. ------------------------------ Subject: (7.33) Help, INND gets real big Q: Innd gets real big over time - is there any way to prevent this? This comes at least partly from the design goal to get it fast, so it trades memory vs. I/O. There are some configuration options and patches which could reduce this a bit. If you have lots of stdin nntplinks, you should incorporate the innd.spool.pathc which is in unoff[23] already. Then the value of DBZINCORE also changes the way INND behaves: ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 Both innd and nnrpd have the option of keeping the DBZ hash table in memory, under the control of the INND_DBZINCORE and NNRP_DBZINCORE_DELAY parameters, respectively. This can consume lots of RAM proportional to the size of your history database, but it can also avoid a great deal of disk I/O. You should probably see the DBZ manpage in the doc directory for some (brief) additional discussion of this issue. (From Rich Salz) Matthias Urlichs adds: If you still find that INND grows beyond all bounds, eg. after a week days it's twice as big than after three days, you may have a problem with your system malloc. Many malloc implementations try to coalesce free blocks, and to split big chunks into smaller ones. It can be shown that no matter what strategy you use to split and combine blocks, there's an allocation sequence which lets your used-up space grow without bounds. To fix this problem, use the malloc that comes with INND. It wastes a bit more space initially (around 25%, to be exact), but behaves a lot better -- INND allocates more memory pages, but actually needs fewer to do its job. ------------------------------ Subject: (7.34) Help, my history file got deleted! One way to get back in action is to restore the history file from last night's backup and run 'makehistory -bu'. That will add back the articles that arrive since the backup to the database. You can even add the '-n' option to not throttle the server and you can do this while still accepting news, however you'll probably get some duplicate articles (which may not be all that bad given the alternative of extra downtime). What, you don't have a backup? Too bad. If you still have the news articles on disk, you can do one of two things: run makehistory to make an entirely new database, or newfs the news spool and start over. The first option will probably take at least a day or more, the second option a few minutes. [ One neat idea in this case would be to write a program which took the output of findmissing.pl and into another program which read each article (a la makehistory) and sent "ctlinnd addhist"'s. This would be a lot faster since 'makehistory -bu' still opens every article in the spool. ] ------------------------------ Subject: (7.35) I'm seeing duplicate message-id's in my history database! Something is wrong with your history database. This is one of those things that "can never happen". In order to verify that something is really wrong with your database, run the following command: awk -F' ' '{ print $1 }' < history|grephistory -i (that first thing in quotes is a tab, not a space) This will take a while to run, but the result _should_ contain no output. If it does output anything then the dbz database is hosed. You'll need to rebuild the dbz files from the history file using the "-r" flag to "makehistory" using the process as described in the news-recovery(8) man page. If you still have problems after this, then it could be due to some garbage in your history file which is causing problems with dbz. There really isn't a good tool (yet!) to fix this. What needs to be written is a history file "sanitizer", which examines each line of the file and checks it for nulls, wacko dates, huge lines, and the like. ( Some of this already has been integrated into expire(8) in the "1.4unoff" release, however more could be done. At least now expire doesn't crash when it encounters garbage. ) If you do write such a program, please submit it to barr@cis.ohio-state.edu (Dave Barr) If you do fix your database, but problems re-appear later then perhaps your O/S is at fault. Make sure your O/S has been patched to fix any bugs related to mmap(). In your config.data try turning off -DMMAP in DBZCFLAGS and recompile. If you still have problems, reset DBZINCORE to 0. ------------------------------ Subject: (7.36) Getting lots of duplicate articles Q: I have lots ot 437 - Duplicate article messages in my logfile - I thought nntp would prevent this? I have /remeber/ set to 14. This usually happens when you have some heavily lagged sites feeding you. Increase /remember/ to 15 days or start up innd with the c flag set to 13. When i had both set at 14, it appeared that most old articles arrived shorly after expire finished writing the new history file. this is probably due to inaccurate date headers, now if everyone used NTP ..... (from: rr@eel.ufl.edu (Mahesh Ramachandran)) ------------------------------ Subject: (7.37) Inn send mail to 'rmgroup' or 'newgroup' On some installations the newssystem sends mail to a user newgroup. This is the case if the mailer used in PATH_MAILCMD does not understand the '-s' option which is used to specify a subject on the command line. On some Linux /bin/mail seem to miss this option, as on some Sys V. Try using /usr/ucb/Mail instead (if it exists). ------------------------------ Subject: (7.38) Ctlinnd cancel doesn't cancel my articles .. Q: I did cancel an article with ctlinnd cancel , but it is still in spool Dave Barr: Did you sufficiently quote the message-id (with ''s) so that your shell (whatever it is) doesn't interpret any metacharacters? Try using "echo ''" to see if ctlinnd is getting the characters you think it is getting. ------------------------------ Subject: (7.39) Inn hangs during renumbering the active file Q: Is it normal for INN to hang during a renumber? Yes. Innd doesn't accept incoming articles as they might change the contents of a directory / the number count in active while renumber tries to adjust these numbers. If it would accept these articles then you would get '400 File exists writing article file' errors, which you could get rid of by ctlinnd renumber ... Internally, renumber is a loop the calls NGrenumber on each group in active. NGrenumber then renumbers the group. So while Innd is in this loop it can't accept connections. If you are worried by the long time the server does not accept connections, then do something like (from news.daily): while read GROUP hi lo flag ; do ctlinnd -s renumber ${GROUP} 2>&1 sleep ${RENUMBER} done <${ACTIVE} This will renumber separately each group leaving the possibility to get connections while sleep()ing. ------------------------------ Subject: (7.40) Some local postings don't make it to remote, but others do Q: My feeds are set up and postings that come from tin make it to the remote while others e.g. from nn or netscape don't. I have the following in newsfeeds: news:*:Tf,Wnm:news.foo.bar.com A: nn and netscape produce the following path line: >Path: host!news while tin gives >Path: host!user Now the entry ``news'' in newsfeeds collides with the news in the Path: header. Change your newsfeeds entry to news.some.com:*:Tf... and it should work. ------------------------------ Subject: (7.41) Expire does no longer work Q: Expire suddenly stops with : Can't store key There were some cancel articles posted recently that tried to cancel more than one message at a time. Dbz code doesn't like this. One solution is the following: Grab the Perl 'fixhist' script off http://www.cis.ohio-state.edu/~barr/INN.html and follow the instructions at the top of the file. That will clean out the cruft from your history database and allow expire to run without crashing. ------------------------------ Subject: (7.42) news.daily complains about unknown entries from syslog Q: news.daily complains: Syslog summary: Unknown entries from news log file: Mar 25 06:46:57 xx innd: some.do.main:9 NCmode "mode stream" received What's wrong? A: Inn1.4unoff4 now logs when a site connects that is able to send streaming nntp. This is for debugging purposes, but the local version of innlog has not been changed to catch up with this. Try to use the innlog.awk that comes with unoff4. ------------------------------ Subject: (7.43) Innd writes to syslog: DEBUG ERROR SITEspool: trashed Dave Barr: This is apparently due to the innd.spool patch. As far as I can tell the message is "mostly harmless". I have tracked it down as far as WCHANflush() getting called with the handle of a channel (which is a socket), except as the comment to the function says it's only supposed to be used on file channels. ------------------------------ Subject: (7.44) My feed does have different groups in active Q: The groups in my active are not in sync with those of my feeds A: Matt Midboe wrote a script to get the active in sync whith the feeds you can find it via ftp in ftp://ftp.isc.org/isc/inn/unoff-contrib/sync-active.tar.gz In v1.5 of INN there will also be actsync, actsyncd for this job. ------------------------------ Subject: (7.45) INN is only slowly responding (From: Erland Sommarskog ) Q: We started a new news server just a month ago. SS-20, lots of memory, 23 GB of news spool. The first week it ran fast as a jaguar, but now it crawls like a snail. It takes forever to connect, we can't keep up with our feeds which have to flush our queues, it takes to forever to connect. When we monitor the box it spends an awful lot of time in kernel mode, and seems to be doing a tremendous amount of disk access. Where did we go wrong? If it matters, we're not running expire, but dexpire and histtrim. A: The problem is with the history database. This database consists of three files: history, history.pag and history.dir. The dir files contains a hash table. For optimal performance, the hash file must not be too small, or you will get many collisions. The initial size of the history database is based on Usenet traffic as it was a couple of years ago, and no one was considering a 23 GB spool. Now, for people who is running expire this is not a problem, because when you run expire, the history file is rebuilt, and the size for the new database is taken from the old one. But if you are running dexpire and histtrim, this never happens, and innd will spend most of its time reading overflow buckets. What to do then? Rebuild the history database. And the simlpest way to do it, is to run expire. A simple approach is to run expire every now and then, with an expire.ctl that safe won't expire very many articles. (But add a short expiration time on some junk group, so that expire get something to work with.) A better approach is to discontinue use of histtrim, and run expire daily basis. Dexpires produces an output which you easily can trans- form into an expire.ctl. I discourage use of histtrim, since it may delete articles from history and yet are on the system. (From: James Brister ) A good indicator of your performance characteristics would be how much smaller is the number generated by this, head -1 /var/news/etc/history.dir | perl -ane 'print 2 ** $F[7], "\n";' than the size of your history text file. If it's bigger you're OK. if it's smaller, then lookups for the message ids at the tail of the history text file (past the byte indexed by the number just generated) will be much slower than for those at the front. See also: #7.6, #7.7 and #7.41 ------------------------------ Subject: (7.46) What does 'Reserved Expiring process xxx' mean? Q: While trying 'ctlinnd mode' I get this line : Reserved Expiring process 23386 Any idea about what does it mean exactly and how to correct this problem? A: When expire is running it reserves the server so that it can safely pause and unpause it. This prevents other processes from grabbing the server and rendering (some parts of) expire worthless. While expire is running this is no problem. If expire is no longer running and the server is still reserved, then you type "ctlinnd reserve ''". See also #5.13, #7.5, #7.7. ------------------------------ Subject: (7.47) What happens to cancels if they arrive before the article ? Q: What happens if a cancel message arrives before the article it is supposed to cancel? A: (From Rich $alz) | If VERIFY_CANCELS is set to DO, then early cancel messages are ignored. | If it is not set to DO, then early cancel messages cause a history line | to be written for the article being cancelled. Subsequent offers of the | real article will be rejected. ------------------------------ Subject: (7.48) I use funnel feeds and INND dumps core When the target of a funnel feed is dropped and the funnel feed that pipes into it is not, then innd will dump core. E.g. newsfeeds : foo:*:Tm:bar bar:!*,Tf,Wnm*: If you now issue a ``ctlinnd drop bar'' then innd will soon drop core. There is at the moment no fix other than dropping foo before bar in the above example. ------------------------------ Subject: (7.49) NNTP-Posting-Host is localhost.do.main even if host has a name Q: When I post an article on the host innd is running then the header ``NNTP-Posting-Host'' is set to localhost.do.main instead of the real fqdn. A: Local connections often go through the loopback interface so the ip-number is the one of the localhost (127.0.0.1). In /etc/hosts (or if you are running bind in that config) just add the name of your machine e.g. change from 127.0.0.1 localhost to 127.0.0.1 machinename localhost ------------------------------ Subject: (7.50) uuxqt says: rnews exit status 1 The problem is that news batches coming in via uucp get saved fine by uucp, but rnews isn't able to process them and uuxqt either throws them away or puts them to a .Failed directory. This seems to happen often with newer versions of Taylor uucp. Taylor uucp saves batches as owner uucp mode 600. So when rnews (as it is installed by make is news.uucp and mode r-sr-sr-x then it gets user news which is not able to read the batches and exits right away. Changing rnews to 50 -r-sr-s--- 1 uucp news 24724 Dec 10 14:59 /bin/rnews helped in all cases that I had this specific problem. The s-Bit on group news assures that if rnews fails (e.g. server throttled), then it can put the batches to in.coming/bad. ------------------------------ Subject: (7.51) innd get a non-zero ``nice'' value? Q. Why does innd end up with a non-zero ``nice'' value? A. Some systems (usually BSD-based) will automatically renice a process to a value of 4 if the process is not a root process and if it has a nice value of 0 and if it has accumulated more than 10 minutes of CPU time. On BSD/OS systems this can be defeated by configuring a kernel with AUTONICETIME set to 0. ------------------------------ Subject: (7.52) innd runs as root, even if configured to run as 'news' We had a little debuging session due to inn 1.5.1 starting as root instead of the configured value news. The problem was caused by _PATH_INNDDIR and the following lines of inndstart.c: /* Make sure INND directory exists. */ if (stat(INNDDIR, &Sb) < 0 || !S_ISDIR(Sb.st_mode)) { syslog(L_FATAL, "inndstart cant stat %s %m", INNDDIR); exit(1); } NewsUID = Sb.st_uid; NewsGID = Sb.st_gid; So inndstart takes user and group values from _PATH_INNDDIR, and our dir was owned by root =). ------------------------------ Subject: (7.53) Makehistory is slow on inn 1.x , x<5.1 From: "Otto J. Makela" There is a rather serious bug in the standard distribution inn 1.4 (and all unoff versions, but has been fixed in inn 1.5.1) makehistory, which affects innd performance very much. Makehistory can be used to create the history dbz database files from the raw text file and for example dexpire does this with every histtrim operation. The problem is that makehistory is given just one parameter specifying the size of the expected dbz database in lines, but it uses this parameter also for the dbzfresh() tagmask parameter where the maximum key value is expected to be given. This means the dbz database is built with a very small hash table causing most of the history database to be accessed without hashing, a very serious performance hit. As noted in the inn FAQ section 7.45, you can check the size of your dbz hash table with the following commands: head -1 history.dir | perl -ane 'print 2 ** $F[7], "\n";' if the number returned is smaller than your history text file, you are being affected by this problem. The problem becomes worse as the history file grows, so an indication of this problem is that your news server worked fine at first (small history file) but started really beating the living daylights out of the hard disk where history is after it grew a bit larger. This problem can be patched with the following extremely simple change to makehistory, which just multiplies the number of lines in the dbzfresh call with 70 which is (supposedly) an average number of characters per history text file line. This same fix has been implemented in inn 1.5.1 makehistory. -- diff -u expire/makehistory.c{.orig,} --- expire/makehistory.c.orig Mon Jul 31 22:18:46 1995 +++ expire/makehistory.c Wed Apr 23 11:26:50 1997 @@ -125,7 +125,8 @@ /* Open the new database, using the old file if desired and possible. */ (void)dbzincore(1); if (IgnoreOld) { - if (dbzfresh(p, dbzsize(size), HIS_FIELDSEP, 'C', dbztagmask(size)) < 0) { + /* Assume average history line length of 70 characters */ + if (dbzfresh(p, dbzsize(size), HIS_FIELDSEP, 'C', dbztagmask(size*70)) < 0) { (void)fprintf(stderr, "Can't do dbzfresh, %s\n", strerror(errno)); if (temp[0]) ------------------------------ Subject: (7.54) Expire is slooooooow Q: Expire takes 20 hours on my system to complete. First of all you should call news.daily with the delayrm option (see also #2.12, #4.18, #4.19, #5.13). If this is still too slow, then it could be that the list passed to "fastrm" is too large to be sorted by the sort(1) command, typically because /tmp is too small. Try setting TMPDIR in innshellvars. ------------------------------ Subject: (7.55) Why are multiple innwatch's running? From: Jim Dutton Currently, "nobody" seems to verify whether an innwatch task is already executing before innwatch is started up in rc.news. Also, when innd is terminated via ctlinnd shutdown, innwatch is not affected (eg; it is left running). Since rc.news always starts an innwatch task, if innd is shutdown for maintenance, it is necessary to remember to ALSO kill the innwatch task and its attendant "sleeper" task, thus ensuring that there is no innwatch running when rc.news is executed to restart innd (assuming that this is how innd is restarted, of course). ------------------------------ Subject: (7.56) I upgraded to INN 1.5.1, and peers have trouble feeding me. INN 1.5.1 (and some versions of INN 1.4unoff) support streaming NNTP (see #6.25). Jerry Aguirre (who authored the streaming support) has this to say about streaming NNTP: > One of the fallouts of streaming was that a streaming feed tends to hog > the resources. (I consider it a feature but ...) Basically streaming > is more efficient so it is going to send more articles and thus consume > greater resources. The scheduling algorithm of INN's server aggravates > this so that the non-streaming connections suffer. There is code in INN > 1.5.1 to limit the work a streaming channel will do on a single pass. > It helps but perhaps not enough. More advanced methods have been > discussed but require greater changes to the code. (Jerry Aguirre, May > 9 1997) If you upgraded to INN 1.5.1 from a version of INN which didn't support streaming NNTP (e.g., INN 1.4sec), and have streaming support enabled, incoming feeds which are configured to attempt streaming mode by default will now be streaming articles to you. The incoming feeds which are not capable of streaming will get less and less of INN's attention (depending on how many incoming streamers are connected at the same time). Thus, the incoming feeds which can't stream will see a performance degradation, and may develop appreciable backlogs for you. There are several things which can be done. If the non-streamers switch to an outgoing feed program which supports streaming NNTP, then they will be able to get more of INN's attention. Current versions of innxmit and innfeed (see #4.21) support streaming NNTP. Another possibility is to disable streaming NNTP for incoming connections, which can be done in the hosts.nntp file (see the man page for hosts.nntp for more information). A third possibility is to apply the following patch by Alan Barrett: ftp://ftp.isc.org/isc/inn/unoff-patches/inn-patch-apb-19970129 This patch attempts to limit the amount of work INN does for each channel at one time. Several sites have experienced success with it, but at this point, it is not an official patch. ------------------------------ Subject: (7.57) I upgraded to INN 1.5.1, and it takes clients a long time to connect. This may be caused by streaming NNTP (see #7.56). Since INN handles all incoming NNTP connections (even the ones which are passed off to nnrpd), incoming streaming NNTP feeds may cause INN to take a long time to respond to a newsreader client's initial connection. The solutions in Subject #7.56 should be equally effective in reducing initial connection latency for newsreaders. Or as another alternative move innd away from port 119 and accept nnrpd connects port 119 using inetd. ------------------------------ Subject: (7.58) My server gets slower and is busy doing io Under Unix, when directories are getting too large, operations on them are also getting slow. Most likely candidate is control or if you have control.cancel in active control/cancel in the spool. Rebuilding the directory from time to time helps (e.g. mv /news/control/cancel /news/control/bye.bye && rm -fr /news/control/bye.bye). There is also somewhere a patch floating around that divides control/cancel in further subdirectories which makes each of those smaller. inn-1.7.2/FAQ/INN-faq_part10100644000175100001440000005052406443103542013467 0ustar mdusersNewsgroups: news.software.nntp,news.software.b,news.answers Subject: INN FAQ Part 1/9: General Information Followup-To: news.software.nntp Approved: hwr@pilhuhn.de Summary: This article is part 1 of a multi-part FAQ: Part 1: Common questions about INN itself, useful to people that do not currently run INN. Posted-By: post_faq 2.10 Archive-name: usenet/software/inn-faq/part1 Last Changed: $Date: 1997/11/04 02:25:51 $ $Revision: 2.37 $ Part 1 of 9 INN FAQ Part 1: General and questions from people that don't (yet) run INN INN FAQ Part 2: Specific notes for specific operating systems INN FAQ Part 3: Reasons why INN isn't starting INN FAQ Part 4: The debugging tutorial (setup of feeds etc.) INN FAQ Part 5: Other error messages and what they mean INN FAQ Part 6: Day-to-day operation and changes to the system INN FAQ Part 7: Problems with INN already running INN FAQ Part 8: Appendix A: Norman's install guide INN FAQ Part 9: Appendix B: Configurations for certain systems ------------------------------ Subject: Table Of Contents for Part 1/9 ===================================================================== TABLE OF CONTENTS FOR PART 1/9 ===================================================================== QUESTIONS FROM PEOPLE THAT DON'T (YET) RUN INN: 1.1 What is INN? 1.2 I thought Rich Salz maintains INN ... 1.3 What's the future of unoff releases? 1.4 Where can I get the INN software? 1.5 Where can I get the latest copy of this FAQ? 1.6 Where may I find additional information? 1.7 What machines does it run on? 1.8 INN must be really complicated since this FAQ is so long! 1.9 Can I run C News with INN? 1.10 Can I run NNTP with INN? 1.11 Can I run the reference implementation (NNTP1.5) with INN? 1.12 Can I run INN on my UUCP-only machine? 1.13 Suppose I have a 286 machine? 1.14 Does INN implement NOV, xthread (trn) or xuser/xmotd (tin) commands? 1.15 Is an ident or authorization protocol supported? 1.16 Does INN do UUCP batching like C News? 1.17 Help! How do I configure this beast? 1.18 How do I thank the FAQ maintainer? 1.19 What has Netscape's Newsserver to do with INN? 1.20 How do I submit additional informations for the FAQ? The FAQ was written by Rich $alz , was maintained for a long time by Tom Limoncelli and is now maintained by Heiko W.Rupp These documents would not exist if it weren't for the people that have submitted questions and (most importantly) answers. THANK YOU ALL! ===================================================================== QUESTIONS FROM PEOPLE THAT DON'T (YET) RUN INN ===================================================================== ------------------------------ Subject: (1.1) What is INN? For a complete answer, why not read the Usenix paper that introduced INN to the world? It's available as ftp://ftp.uu.net/networking/news/nntp/inn/inn.usenix.ps.Z InterNetNews is a complete Usenet system. The cornerstone of the package is innd, an NNTP server that multiplexes all I/O. Think of it as an nntpd merged with the B News inews, or as a C News relaynews that reads multiple NNTP streams. Newsreading is handled by a separate server, nnrpd, that is spawned for each client. Both innd and nnrpd have some slight variances from the NNTP protocol (although in normal use you will never notice); see the manpages. INN separates hosts that feed you news from those that have users reading news. If you need to support a mixed environment you will have to do some extra work; the installation manual gives some hints. ------------------------------ Subject: (1.2) I thought Rich Salz maintains INN ... Rich did for a very long time .. From an announcement (<4k5pn3$ii9@paperboy.osf.org>) : | I am pleased to announce that the Internet Software Consortium | (http://www.isc.org/isc) will be responsible for future official INN | releases, starting with INN1.5. I am sure they will be posting a notice | about their plans here fairly soon. | The interest and support (both financial and emotional) they have given | me over the past few years has been immeasurable. It was this interest, | as much as their ability to commit top-flight engineering talent, that | makes me feel confident that I'm leaving "my baby" in good hands. | I will still be involved with INN development, although more in an archi- | tectural and philosophical role (i.e., "do it this way") rather than | programming (i.e., "here's the code"). | If you've found INN useful, I'm glad. (By my count several thousand people | still owe me a postcard. :) If you expect to find it useful in the future, | please support the ISC and their efforts. I know I will. | /rich $alz For the postcards, Rich adds in (<565e4r$5v2@paperboy.osf.org>): | No no no. James gets the postcard. This means you have to track down | his current physical address; perhaps in-care-of the ISC would work. :) | The rules are actually pretty complicated: | If you're installing 1.4sec2 or earlier, send yourself a postcard | saying you should upgrade. | If you're installing 1.5 or later, for the first time with INN, | send James the postcard. | If you're upgrading from 1.4 to 1.5, pro-rate your news volume | and send us each the appropriate fraction. :) Dave Barr added that the postcards for him also should be sent to the ISC. ------------------------------ Subject: (1.3) What's the future of unoff releases? Q: As Rich no longer does inn - what's the future on unoff releases? Dave Barr wrote: | As it stands now I have decided to stop releasing any more unoff versions | unless someone can convince me otherwise. I am redirecting my efforts | towards helping 1.5 see the light. The code base has drifted enough | already -- releasing unoff5 while 1.5 is trying to integrate unoff4 | stuff would be counterproductive. | To put it another way, consider the INN1.4unoff to be under a | code freeze. Only bug fixes (and even then only to unoff-specific | code, like streaming) will be accepted. ------------------------------ Subject: (1.4) Where can I get the INN software? The official archive site was ftp.uu.net in the directory networking/news/nntp/inn. Archie current lists over 30 archive sites; three other international sites are ftp.univ-lyon1.fr in pub/unix/news/inn, munnari.oz.au in pub/news/inn, and src.doc.ic.ac.uk in computing/usenet/software/transport The latest version is INN 1.7 available from ftp://ftp.vix.com/pub/inn/ or mirrors which are indicated on http://www.isc.org/inn.html one mirror in Europe is ftp://ftp.xlink.net/pub/mirror.inn/ !! Note that INN1.5.1 has a security vulnerability. You can find a !! first patch to this at http://miquels.www.cistron.nl/inn/ Patches for older versions are available from: Patches for INN are at: ftp://ftp.isc.org/isc/inn/unoff-patches and ftp://ftp.isc.org/isc/inn/unoff-patches/OLD Add-ons for INN are at: ftp://ftp.isc.org/isc/inn/unoff-contrib ("Add-ons" include "Gup" and other interesting tools) ------------------------------ Subject: (1.5) Where can I get the latest copy of this FAQ? 0. If you are reading this document, then you already have part 1 of it. So look around where you found this if the other parts are also there. 1. This nine-part FAQ is available via FTP at any FTP site that carries INN itself. 2. This FAQ is also posted to news.software.nntp, news.software.b and news.answers about every week. 3. If you don't find it in one of the above places, then try ftp://ftp.xlink.net/pub/news/docs/ (on this server I put the newest FAQ after posting it -hwr). 4. A htmlized version can be found under http://www.cis.ohio-state.edu/hypertext/faq/usenet/usenet/software/inn-faq/top.html These are grabbed from news.answers - so they might be a bit out of date :-( ------------------------------ Subject: (1.6) Where may I find additional information? The Usenix paper from Rich $alz: ftp://ftp.uu.net/networking/news/nntp/inn/inn.usenix.ps.Z The Web site of the new maintainers, the Internet Software Consortium http://www.isc.org/inn.html A good overview for those not familiar with news (from Tom Podnar ): ftp://bones.wcupa.edu/pub/misc/nntp.ps A FAQ in french - maintained by Fabien Tassin at http://www.eerie.fr/~news/faq.html A Usenet/INN hypertext documentation effort by Forrest J. Cavalier III at http://www.mibsoftware.com/userkt/userkt.html A FAQ in Japanese - maintained by Toshio Hori at ftp://etlport.etl.go.jp/pub/People/toshi/INN/J/ Jeff Garzik started to write a ``INN tuning page'' which is oriented towards the Intel/Linux platform (but not only of interest for Linux users) at http://www.spinne.com/usenet/inn-perf.html RFC's important to News: RFC 977: NNTP (Phil Lapsley and Brian Kantor) RFC 1036: Standard for Interchange of USENET Messages (M.Horton, Rick Adams) The O'Reilly Book (only for C News ; new version is in work) Managing UUCP and Usenet (Tim O'Reilly and Grace Todino) This book seems to be no longer in print, so O'Reilly probably has no book about Usenet at the moment. The newsgroup news.software.nntp; please look around in this group. Often you'll find there the answer to the question you were going to ask. But don't hesitate to ask. If you can't post to news.software.nntp you can send mail to inn-questions@pilhuhn.de which will post the your mail in that group. Dave Barr has put together some information about his unoff releases. This page is also a entry for the patch archive: The overview database with its XOVER nntp extension is described in ftp://ftp.internic.net/internet-drafts/draft-barber-nntp-imp-01.txt This is superseded by draft-barber-nntp-imp-02.txt on the same site. and will be superseded by version 3 soon, which you also might get from ftp://ftp.academ.com/pub/nntp/private/nntp.extensions.draft.txt (This one is now at the 4th update) There is a book from Addison-Wesley called 'Administering Usenet News Servers' by Jim McDermott and John Phillips (ISBN 0-201-41967-X) which seems to cover INN and Dnews. This is not clear from the aw web site though. There is no special book on INN out at the moment, but it is said, that Dave Lawrence and Henry Spencer are currently writing one for O'Reilly. ------------------------------ Subject: (1.7) What machines does it run on? If you have socket() and select() then INN will probably run on your machine. In addition to the common platforms found around the Internet (SunOS and Ultrix, for example), INN runs on IBM's AIX, Apple's A/UX, NeXT, Solaris 2.x, most SVR4 platforms, BSDI, most free BSD systems (NetBSD, FreeBSD, ...) and a host of others. It might require a little bit of tweaking of some free BSD platforms that have really bad shells. INN has not been ported to Windows NT. There are no plans to do so. However, someone has written a package called NNS (Usenet Network News Server) which is a NNTP-compliant news server for Windows NT. For information write to nns@jeck.wa.com. ------------------------------ Subject: (1.8) INN must be really complicated since this FAQ is so long! No, it's just that the FAQ is very complete. A lot of the material could be integrated into the Install.ms doc. Please post questions to news.software.nntp. Do not send email to Heiko W.Rupp directly. By posting your question, a group of 10 or so people will be trying to help you. On the other hand -- if you have a solution that should be included, then send it to the maintainer, so that he can't miss it in the news. See also #1.20 and #9.1. ------------------------------ Subject: (1.9) Can I run C News with INN? No. INN handles all article reception, filing, forwarding, and expiration. You will get a corrupted database if you try to run INN with any other news system. For testing, you can probably shut down your old system, bring up INN, and then reverse the process. (INN uses the C News history file and DBZ database, so if you don't run C News you will have to do some fiddling around with those files.) ------------------------------ Subject: (1.10) Can I run NNTP with INN? There's a confusion here. NNTP is a protocol, defined in RFC 977. There is also an implementation of the protocol, NNTP1.5, that many people call NNTP. When there was only one implementation of the protocol, that was okay, but now that there are other implementations (for example, INN) it is getting confusing. It would be as if "sendmail" were named "smtp." Please try to be clear -- do you mean the NNTP protocol, or the NNTP reference implementation currently maintained by Stan Barber? ------------------------------ Subject: (1.11) Can I run the reference implementation (NNTP1.5) with INN? The quick answer is no. INN listens on the NNTP port and handles all incoming traffic. It receives articles, files them, and arranges for them to be forwarded to your peers. If a site connects that is not listed as a peer (e.g., a local workstation that does newsreading) then the INN server hands the connection off to another program that handles just the NNTP commands that newsreaders use. By default, this is nnrpd (notice the "r"), which implements the NNTP protocol for newsreaders (for example, it includes the POST command but not the IHAVE command). You can run the reference implementation server instead of nnrpd if you want. Doing this can be useful if you have clients that want to do both reading and article transfer. ------------------------------ Subject: (1.12) Can I run INN on my UUCP-only machine? Sure. While not designed for this, several people are running INN on machines that do not have IP-connectivity (such as UUCP-only hosts) and are quite happy with it. You might want to give it a try, especially if you think you will be joining the Internet some day. ------------------------------ Subject: (1.13) Suppose I have a 286 machine? Won't work. INN is designed to be a memory hog; a server that has been up for a few days while will have a working set size of a few to several megabytes, although not all of it will be resident. For example, the server keeps the active file and list of who gets what in memory, as well as all articles that it is receiving. Unless you can do things like "malloc(64 * 1024)" without pain, INN won't work on your machine. ------------------------------ Subject: (1.14) Does INN implement NOV, xthread (trn) or xuser/xmotd (tin) commands? Newsreaders all need some way to quickly grab data from a range of articles. trn, tin, nn, and others each developed their own database format, and their own extensions to the NNTP protocol for clients to read the database. Then, Geoff Collyer invented NOV, the database to end all other databases. Rather than support a different database format for each newsreader, INN supports Geoff Collyer's news overview database, NOV. INN includes everything you need to create/maintain/expire NOV's .overview files. You only need Geoff's distribution (available via FTP on ftp.std.com src/news/nov.dist.tar.Z) if you want to see how he implements things, or to get his client library (useful when building some newsreaders). It is very easy to configure INN to use NOV. Read Part 4/9 of this faq: Subject: Cookbook example of setting up NOV ("overchan") NB: The NOV code in INN 1.3 is buggy. Use 1.4 or higher. The xover command is used for querying the NOV database. The xover command is very smart in that if the article has been canceled, the data isn't given out. If the article is so new that it's data isn't in the NOV database, nnrpd opens the article and digs out the data. xhrd and xpat make every effort to use NOV data before they dig the data out of the actual articles, thus making them considerably faster than other implementations. The "xoverview" command does not exist. If your server supports this command you need to upgrade. What about TRN's xthread command? The xthread command has code but it is not supported; look at $inn/nnrpd/nnrpd.h. This code will probably vanish after 1.4. What about TIN's many commands? Tin commands are not supported. However, other people have added TIN support. See the next section. ------------------------------ Subject: (1.15) Is an ident or authorization protocol supported? An unsupported patch for nnrpd to add ident support can be found via FTP at ftp://ftp.csie.nctu.edu.tw/pub/News/packages/nnrpd-ident.tar.gz It includes patches to add tin's xuser and xmotd commands as well as a list subscription system. (skhuang@csie.nctu.edu.tw) Remember: ident information is only as valid as the server you connect to. Any fool with root access (or anyone with a PC or Mac) can create a bogus ident server that will give out whatever information they want you to see. It's not an authorization or identification protocol, it's just informational. The authd protocol is added to nnrpd by . This unsupported patch can be found in ftp://ftp.eos.hokudai.ac.jp/pub/network/news/inn/patches/authd-patch-1.3.tar.gz The documentation is in Japanese. Good luck. In a future release, you will be able to log all POST commands with ident information if you so choose. (Maybe INN 1.5) ------------------------------ Subject: (1.16) Does INN do UUCP batching like C News? Not as part of the standard distribution. The batching system right now is better than B News, but Rich has said he will be working on improving that part of INN in a future release. Christophe Wolfhugel has written a package that is very much like the C News batching system, however. You can find it at ftp://ftp.univ-lyon1.fr/pub/unix/news/inn/contrib/ Version 3 of Christophe's package includes a shell version and a Perl version. Version 4, not yet planned will only be in Perl. The configuration file has evolved from older releases in order to support new features like "minimum batching". ------------------------------ Subject: (1.17) Help! How do I configure this beast? READ AND FOLLOW THE "Install.ms" FILE. This FAQ is meant to add to what Install.ms says not replace it. Even if a already configured or pre installed INN comes with your OS, you should at least glance at Install.ms to see where is what and why. Many people that thought the Install.ms doc was incomplete later re-read the "First Time Installation" portion and were amazed how much they missed (or just plain skipped) the first time. You should also purchase the O'Reilly And Associates book on Managing Usenet to give yourself a good grounding on how to run a site. ------------------------------ Subject: (1.18) How do I thank the FAQ maintainer? If you find this document useful, please consider making a donation to the maintainer's favorite charity: | The Personal Liberty Fund | PO Box 11335 | New Brunswick, NJ 08906-1335 | USA The PLF is a legal and educational organization which helps people in New Jersey, USA. They have many on-going projects which range from combating youth suicide to legal advocacy. Their Anti-Violence Project runs a phone hotline for reporting gay-bashing which helps hundreds of people a year. The PLF is an all-volunteer organization and couldn't survive without donations. The PLF is recognized by the IRS as a 501(c)3 tax-exempt charity. Donations are tax deductible to the fullest extent of the law (U.S. citizens only). Please write "INN" in the memo field of the check. Fifteen, fifty, or five hundred dollars... every penny is appreciated! ------------------------------ Subject: (1.19) What has Netscape's Newsserver to do with INN? Netscape took INN as the original source base for their server and added their own extensions. As revisions go by they will differ more. Rich $alz adds: | netscape did not get any special consideration for INN. Anyone who | wants to commercialize it is free to do so.Read the COPYRIGHT file. You can get answers to problems with the Netscape Server in snews://secnews.netscape.com/netscape.server.news ------------------------------ Subject: (1.20) How do I submit additional information for the FAQ? If you have an addition to the FAQ then send it to the actual maintainer Heiko W.Rupp . Please try to bring your submission in the style of the actual FAQ (Especially if you submit an entry for part9 then please follow #9.1). If you put (along others) 'inn' in the subject, you will get an automatic acknowledge of receipt. inn-1.7.2/FAQ/INN-faq_part80100644000175100001440000006177406443103542013507 0ustar mdusersNewsgroups: news.software.nntp,news.software.b,news.answers Approved: hwr@pilhuhn.de Subject: INN FAQ Part 8/9: Appendix A: Norman's install guide Followup-To: news.software.nntp Summary: This article is part 8 of a multi-part FAQ: Part 8: Norman's quick guide to getting started (assumes SunOS and other things), and misc. other things. Posted-By: post_faq 2.10 Archive-name: usenet/software/inn-faq/part8 Last Changed: $Date: 1996/01/30 21:44:45 $ $Revision: 2.3 $ Part 8 of 9 INN FAQ Part 1: General and questions from people that don't (yet) run INN INN FAQ Part 2: Specific notes for specific operating systems INN FAQ Part 3: Reasons why INN isn't starting INN FAQ Part 4: The debugging tutorial (setup of feeds etc.) INN FAQ Part 5: Other error messages and what they mean INN FAQ Part 6: Day-to-day operation and changes to the system INN FAQ Part 7: Problems with INN already running INN FAQ Part 8: Appendix A: Norman's install guide INN FAQ Part 9: Appendix B: Configurations for certain systems This is a separate guide for installing INN addressed to UNIX and System Administration novices. It is written for installation of INN 1.4 on a Sun SPARCstation running SunOS 4.1.x with some additional comments for Solaris 2.x. This guide is maintained by Norman J. Pieniazek (norman@giardia.pdb.cdc.gov). Please send updates and corrections to him. This guide is composed of following parts: I. SYSTEM REQUIREMENTS II. INSTALLATION OF INN 1.4 III. UPGRADING FROM INN 1.3 TO INN 1.4 IV. MAINTENANCE OF INN V. INSTALLATION OF XVNEWS, A SUN OPENWINDOWS NEWSREADER I. SYSTEM REQUIREMENTS 1. INN will not install nor run on Sun SPARCstation under plain Solaris 1.1 or 2.x unless you install some additional software packages and utilities (fortunately, they are free). Also, your machine's IP number (of the news server) has to be entered in a Domain Name Service database (DNS) to be resolvable. Ask your Network Administrator about DNS or read the O'Reilly & Associates, Inc. book: "DNS and BIND" by Paul Albitz & Cricket Liu, ISBN 1-56592-010-4. Further, test the resolver on your machine by pinging a hostname not entered in your /etc/hosts file. For example, type: "ping ftp.uu.net" The response should be: "ftp.uu.net is alive". If you get: "unknown host ftp.uu.net", consult the O'Reilly's book. (Solaris 2.x - the most common problem with DNS results from not switching on DNS support. Check the line "hosts:" in the /etc/nsswitch.conf file. It should read: "hosts: files dns"). 2. Be sure to su to root before performing tasks outlined below. Next, check if you have a directory /usr/local and about 90 Mb of space in the partition where this directory is located. Create directories: /usr/local/bin, /usr/local/lib and /usr/local/man if you do not have them. Add /usr/local/bin to your path and /usr/local/man to your MANPATH. On Solaris 2.x, create /opt/local tree and make a symbolic link from /usr ("ln -s /opt/local /usr/local"). 3. INN uses gnu versions of grep, awk and sed. Moreover, it is recommended to compile INN with the gnu versions of make and the gnu gcc compiler instead of the Sun's Solaris 1.x unbundled cc compiler. (C compiler is not included with Solaris 2.x. The cc in /usr/ucb is bad. Be sure to remove it from path.) If you don't have the gnu software package, create a directory /usr/local/gnu, cd to this directory and ftp to prep.ai.mit.edu (18.71.0.38). Go to directory /pub/gnu and get the newest version of the following programs: bison bison-x.x.tar.gz flex flex-x.x.x.tar.gz gawk gawk-x.x.x.tar.gz gcc gcc-x.x.x.tar.gz grep grep-x.x.tar.gz gzip gzip-x.x.x.tar (Note: no .gz) make make-x.x.tar.gz patch patch-x.x.tar.gz perl perl-x.x.tar.gz sed sed-x.x.tar.gz tar tar-x.x.x.tar.gz texinfo texinfo-x.x.tar.gz Installation of these programs is not complicated, and is really beneficial both for Solaris 1.x and Solaris 2.x users. After you complete the installation, check if older versions of these programs are not present somewhere in your path. Delete or rename these old versions. Solaris 2.x: First, after connecting through ftp to prep.ai.mit.edu, cd to directory: /pub/gnu/sparc-sun-solaris2 and get the file INSTALL.gcc. Follow the instructions for installing binaries for gcc and gzip (installed in /opt/gnu). Next, follow the instructions for Solaris 1.1, but read the doc file for gcc-x.x.x. To avoid problems, rename /usr/ucb/cc to something else, or remove it from path. Make a symbolic link in the /opt/gnu/bin directory from gcc to cc. When you finish the installation, the new utilities will be installed in the /usr/local tree. Delete and remove from path the /opt/gnu tree. As the binaries you downloaded are pretty old, it is advisable to start with the new gcc and to compile all the gnu utilities with this new gcc. NOTE: it makes no difference, if you install gnu stuff in /opt/gnu or in /usr/local. The installation scripts for gnu utilities default to the /usr/local directory tree, so I find it simple to use this path. Whatever you do, be sure to have the gnu utilities in your path before /usr/bin and /usr/ccs/bin. Solaris 2.x: be sure to include /usr/ccs/bin and /usr/ccs/lib in your path. Important utilities (e.g. - ar, cpp) are located there. Please note, that the /usr/ccs stuff is only installed, when you do a full install of Solaris. If you do not have e.g. - /usr/ccs/bin/ar, re-install Solaris 2.x! a. Start with gzip. In /usr/local/gnu type: "tar xvf gzip-x.x.x.tar". A directory gzip-x.x.x will be created. Change to this directory and type: "sh ./configure". Next, edit the Makefile with the vi editor and change the line starting with "CC" to read: "CC = cc". Then, type: "make". Compilation should complete without errors. Finally, type: "make install" to complete installation of gzip, gunzip, and other utilities in /usr/local/bin. b. Compile and install texinfo - info, makeinfo, the GNU hypertext system. Makeinfo is needed for error-free installation of many GNU programs and utilities. In /usr/local/gnu type: "gunzip texinfo-x.x.tar.gz". Next, type: "tar xvf texinfo-x.x.tar". A directory texinfo-x.x will be created. Cd to this directory and type: "sh ./configure". Next, edit the Makefile as described above for gzip. Now, type: "make" and ignore any non-fatal errors. Finally, type: "make install". With newer versions of texinfo, you will get a lot of messages about "emacs", "*.elc", and "*.el" files. Just ignore these messages. c. Installation of the gnu version of tar is beneficial. You will be able to use "tar -Zxvf .tar.Z" or "tar -zxvf .tar.gz" to uncompress and untar files in one step. Uncompress, compile and install tar as above. Be sure that /usr/local/bin is the first directory in your path. d. Uncompress, compile and install gnu make. Follow the steps described for texinfo. Gnu make will install in /usr/local/bin. To disable Sun's make, cd to /usr/bin (/usr/ccs/bin for Solaris 2.x) and type: "mv make make.sun". e. Compile and install bison following the procedure described for texinfo. f. Uncompress gcc. Cd to /usr/local/gnu/gcc-x.x.x and type: sh ./configure Next type: make This step will take about 17 minutes to complete. Ignore warnings reported for insn-emit.c. Next, type: make stage1 Ignore reported non-fatal errors. Next, type: make CC="stage1/xgcc -Bstage1/" CFLAGS="-g -O" This step will take about 19 minutes to complete. Next, type: make stage2 Ignore reported non-fatal errors. Next, type: make CC="stage2/xgcc -Bstage2/" CFLAGS="-g -O" In this step, which lasts about 13 minutes, you will make the final stage 3 compiler. Now type: "make compare". No errors should be reported here. Finally, type: make install CC="stage2/xgcc -Bstage2/" CFLAGS="-g\ -O" (NOTE: backslash "\" is used in this FAQ to break the line for formatting purposes. You can use the backslash for the same purpose in a command line. Please read Sun documentation, if you need more information.) to install the gcc compiler. It is advisable to recompile patch, gzip, texinfo, make and bison with gcc. It will be a good test for proper gcc functionality. g. Uncompress gawk. Cd to directory gawk-x.x.x and type: sh ./configure sunos41 (for Solaris 2.x: sh ./configure solaris2.cc) Next type: "make". When gawk will compile, type: make install Finally, disable Sun's awk by typing: mv /usr/bin/awk /usr/bin/awk_sun and create a link to gawk for awk by typing: ln -s /usr/local/bin/gawk /usr/bin/awk h. Uncompress grep. Cd to directory grep-x.x and type: ./configure Next type: "make" and "make install". Grep will also be installed in /usr/local/bin as fgrep and egrep. Finally, as some programs expect to find grep, egrep and fgrep in /usr/bin, disable Sun's grep and create appropriate links, just like described for awk. INN expects to find a program "egnugrep" in /usr/local/bin. Create it by typing: cp /usr/local/bin/egrep /usr/local/bin/egnugrep i. Uncompress sed and patch. Compile and install these utilities following the instructions for grep. j. INN comes with some scripts written in the perl language. Uncompress perl, cd to directory perl-x.xxx and type: sh ./Configure and hit Return for default answers to all questions. Next, type: "make depend", then "make". Now type: make test to check, if perl works without errors. Finally, type: make install to complete installation of perl. Solaris 2.x: answer "none" for -I/usr/ucbinclude and add libraries: -lm -lnsl -lsocket II. INSTALLATION OF INN 1.4 1. As root, create directories: /usr/local/inn1.4 (this will be your $inn directory) and /usr/local/news. (Solaris 2.x, you have to create a user "news", good choice is UID=6, GID=13, home directory=/var/spool/news, shell /bin/csh, no password - account is locked, * in password field in /etc/shadow. Be sure, to create a new group in /etc/group "news" with GID=13.) 2. Cd to $inn. Get the newest version of inn from: ftp.uu.net (192.48.96.9). This file is in the directory: /networking/news/nntp/inn. As for all binary files, please remember to set the file type in ftp to binary. 3. From the same source and directory get the Frequently Asked Questions (FAQ) files: faq-inn-1.Z faq-inn-2.Z faq-inn-3.Z faq-inn-4.Z (this file) faq-nov.Z and any other files that may contain patches or information. 4. To uncompress the FAQ files type: "uncompress faq-*.Z. Print the FAQs and read them before proceeding further. 6. In $inn type (with gnu tar): "tar -Zxvf innx.x.tar.Z This will extract inn files for compilation. 7. Change directory to $inn/config, and type: cp config.dist config.data chmod 644 config.data Now use the vi editor to edit config.data. You should select gcc as the compiler by changing the line that starts with "CC" to read "CC gcc". Many lines in config.data define the location of various files and directories. It's OK to leave defaults, but check if you have ample space in the directory where the articles will be stored (/var/spool). More information on where INN expects to find certain files is in: $inn/samples/innshellvars. If necessary, edit the config.data and innshellvars to reflect your configuration. Please make sure that specified directories and utilities exist on your system. 8. Change directory to $inn. Type: "make world". Now type: cat */lint (Solaris 2.x - there is not lint included with Solaris 2.x. One way to get Solaris 2.x version of lint suggested to me, is to get a 30 day trial package of the SunPro C compiler from Sun. However, lint is not really needed, except for testing new code. You can make a symbolic link from /bin/echo to lint.) lint will give you a list of compiler warnings and errors. In addition, "make" creates in this step a file: "$inn/Install.ms". Print it by typing: nroff -ms Install.ms | lpr Install.ms is a manual for installation of INN written by Rich Salz, the author of INN. There is a lot of important and interesting information in his manual. 9. If you got no fatal errors from make, go to the $inn/site directory and type: "make all". 10. There are some scripts and control files listed in inn-faqs and Install.ms that may be modified at this point. For most installations, the default settings are OK. 11. Now cd to $inn and type: "make install" to complete basic installation of INN. 12. To finish installation of INN, run the BUILD script in the $inn directory by typing "sh BUILD". This script will ask a series of configuration questions that are easy to answer. Please note that if your have "history.*" files in your /usr/local/news directory from a previous or failed installation of INN, the BUILD script will not complete. Rename them to "old.history.*" and re-run the BUILD script. 13. You need a site that will feed news to you. This will depend on your geographic location and organization. Ask a System Administrator of a site close to you for hints. 14. Ftp to your newsfeeding site and get the "active" file from there. Place this file in your /usr/local/news directory and edit it to your taste. Remember to include the "control" and "junk" newsgroups. Also, you have to edit the following files in /usr/local/news: newsfeeds, hosts.nntp, nnrp.access, inn.conf. Be careful with editing the "active" file with vi or textedit. A common error is to leave a blank line at the top. This error causes INN to crash with the message: "ME bad_active". Depending on your setup, you will get this message in the syslog or on the console. 15. To check for syntax errors in INN control files, file ownership, permissions and other things type: /usr/local/bin/perl /usr/local/news/bin/inncheck and correct any errors reported by inncheck. If your paths are set, it is sufficient to change to the /usr/local/news/bin directory and type: "perl ./inncheck" or "./inncheck". 16. Look at the file "rc.news" in /usr/local/etc. It's advisable to enable the innwatch utility. Innwatch will throttle the newsserver when your disk will get full and prevent crashes. Change the line starting with "DOINNWATCH" to read "DOINNWATCH=true". (Solaris 2.x: edit the innwatch.ctl file and replace df with /usr/ucb/df. Default Solaris 2.x /usr/sbin/df doesn't understand the -i option.) Now type: "sh /usr/local/etc/rc.news" and look in /var/log/syslog for errors. Also, type: ps -aux| grep news and check, if the innd process owner is news. On Solaris 2.x, the syntax is a bit different: ps -fu news 17. In /etc/aliases create an entry: "usenet: ". Next type: "/usr/ucb/newaliases" to inform the sendmail program that the aliases file has changed. If you are running YP (NIS) on your network, you may optionally add the "usenet" alias to your YP aliases file. If the machine you are installing INN on is the YP master and the file "/etc/aliases" is the source of the YP aliases map, you should type: "cd /var/yp" followed by "make". Reboot and restart innd (see #16). 18. To get daily reports on the newsserver activity from the "news.daily" script and to enable the "expire" utility type: "/bin/crontab -e news" and insert the following line: 40 23 * * * /usr/local/news/bin/news.daily delayrm or, if you are using overchan (in newsfeeds): 40 23 * * * /usr/local/news/bin/news.daily delayrm\ expireover 19. To set-up complete logging of the server activities and have them ready for a report by the "news.daily" script, you have to edit your /etc/syslog.conf file. Insert at the end of this file the content of the syslog.conf file written by Rich Salz. This file is in: $inn/syslog. Please check, if you have the directories and files mentioned in Rich's syslog.conf. 20. Run tests from your machine to the server (to your machine at telnet port 119). See inn-faqs for details. 21. After completing these test, be sure to delete the entry for your machine from the hosts.nntp file. If you will not do it, your machine will be treated as a "feeder" and not as a "reader". 22. Set posting. a. Edit the /usr/local/news/newsfeeds file and add: /\ :*\ (for all local postings) :Tf,Wnm: (standard entry) b. Edit /usr/local/news/nntpsend.ctl file and add: :::\ -T1800 -t300 c. Type: "/bin/crontab -e news" and insert a line: 0,10,20,30,40,50 * * * *\ /usr/local/news/bin/nntpsend d. Run inncheck (see #15). e. Post to misc.test and include "reply" in the Subject line, automatic responses will be mailed to usenet (see #17) within a few minutes. 23. To start innd automatically at bootup, include at the end of your rc.local the following lines: # # Start INN news service - Internet News Daemon (innd) # if [ -f /usr/local/etc/rc.news ]; then /usr/local/etc/rc.news; echo "Starting INN news service" fi (In Solaris 2.x there is no rc.local. If you want to start INN automatically, you should create a script in /etc/rc2.d). NOTE: Please send me your solutions for boot time starting and shutdown closing of INN on Solaris! 24. Watch the news.daily reports in your mail for any additional errors. To run the news.daily script at any time manually, first su from root to "news" and type: "/usr/local/news/news.daily". A mail to "usenet" should arrive within a couple of minutes and may report important configuration problems. III. UPGRADING FROM INN 1.3 TO INN 1.4 1. Stop the server. Type: ctlinnd shutdown "upgrade" 2. Create a directory /usr/local/inn1.4, this will be your $inn directory. cd to $inn. Next, ftp to ftp.uu.net, cd to directory: /networking/news/nntp/inn and get the following files: inn1.4sec.tar.Z faq-inn-1.Z faq-inn-2.Z faq-inn-3.Z faq-inn-4.Z (this file) faq-nov.Z Uncompress and print the FAQs. Next, type (with gnu tar): tar -Zxvf inn1.4sec.tar.Z Print the README file. To print the Install file, type: "make Install.ms" followed by: nroff -ms Install.ms | lpr 3. Now, cd to $inn/config and type the following commands: make subst cp config.dist config.data ./subst -f {OLDFILE} config.data where {OLDFILE} is the location of config.data in your INN 1.3 directory. Be sure to check, if in your old config.data the "CC" line reads "CC gcc". Ignore warnings about new lines. Next, type: make sedtest No errors should be reported here. Now, cd to $inn and type this series of commands: make quiet cd ../lib make libinn.a lint cd ../frontends make all cd ../innd make all cd ../nnrpd make all cd ../backends make all cd ../expire make all cd ../site make all cd .. make update 4. Restart innd. IV. MAINTENANCE OF INN 1. Adding new groups - see also Part IV, Section 3.b,: a. Type: "ctlinnd pause 'edit active'" b. Edit the active file. The format is: groupname himark lomark flag. Set himark to 0000000000 and lomark to 0000000001. For detailed description of flags, read the man page for active. Editing the active file by hand is easy, but will not update the information in that file active.times that some newsreaders require to trace new newsgroups. Using ctlinnd command "newgroup" takes care of this problem (see below). Editing the active file with an editor has one drawback - the file active.times is not automatically updated. This creates problems for some newsreader (Trumpet being one of them) that use this file to alert users to new groups. Using ctlinnd command "newgroup" (see Part IV.3.b) corrects this problem. c. Run inncheck (see #11) to check the new active file for errors. d. Type: "ctlinnd reload active 'new active'". e. Type: "ctlinnd go 'edit active'". 2. New groups are sometimes added automatically through a control message. A mail message to usenet will alert to such an automatic change to the active file. If you do not want to subscribe to a particular news group, change directory to /usr/local/news and type: ctlinnd rmgroup 3. Sometimes, a mail message will arrive for usenet with a checkgroups file. Remove header, save the body of the message in: /usr/local/news/bin/control/news_control/news_control_ todaysdate cd to that directory and type: ../docheckgroups todaysdate_pre Read the output file (todaysdate_pre) and carry out all the instructions that you think pertain to your situation. Read the man pages for "active" and "ctlinnd" for more info. To implement the changes, you will have to change to the directory: /usr/local/news and: a. remove a discontinued group: type: "ctlinnd rmgroup " b. add a group: type: "ctlinnd newgroup flag " c. mark a group correctly: type: "ctlinnd changegroup flag" Run inncheck and repeat the docheckgroups command from the /usr/local/bin/control/news_control directory by typing: ../docheckgroups todaysdate_after Correct any reported problems. Also, you may have to edit the /usr/local/news/newsgroups file to reflect any changes you introduced. 4. Read the reports mailed to usenet (you) by the news.daily script. Most errors are reported here and should be easy to fix. 5. Subscribe to and read the following newsgroups: news.software.nntp news.software.readers 6. IMPORTANT!!! Never run fsck on the drive where the /spool/news files are located while running INN. Innd has a lot of active disk I/O going on and you could corrupt your drive. Use ctlinnd to throttle, pause, or shutdown innd first - see the manual page for ctlinnd. V. INSTALLATION OF XVNEWS, A SUN OPENWINDOWS NEWSREADER 1. Create a directory /usr/local/xvnews and cd to this directory. 2. Ftp to ftp.twi.tudelft.nl and get the file xvnews.tar.gz from directory /pub/news. 3. Ungzip and untar xvnews. With gnu tar type: tar -zxvf xvnews.tar.gz 4. Use your vi editor and edit the file xvnews.h You will need to enter your settings for: DOMAIN (on my machine: "pdb.cdc.gov") ORGANIZATION (on my machine: "Centers for Disease Control Atlanta, GA, USA") NNTPSERVER (on my machine: "giardia.pdb.cdc.gov") Preferred method is to override these defaults by specifying environment variables DOMAIN, ORGANIZATION, and NNTPSERVER in your .cshrc or .profile files (see the xvnews man page). In this way, you will be able to change default settings quickly. 5. Compile xvnews by typing: "make -f Makefile.dist" This command will show you, how to enter defaults for your operating system (e.g. - "sunos5" for Solaris 2.x, "sunos4" for SunOS 4.1.x). I get some compilations warnings on my system, but the program runs OK. Copy xvnews to /usr/local/bin and xvnews.man to directory: /usr/local/man/man1 as xvnews.1. inn-1.7.2/FAQ/INN-faq_part20100644000175100001440000013154006443103542013466 0ustar mdusersNewsgroups: news.software.nntp,news.software.b,news.answers Approved: hwr@pilhuhn.de Subject: INN FAQ Part 2/9: Specific notes for specific operating systems Followup-To: news.software.nntp Summary: This article is part 2 of a multi-part FAQ: Part 2: Advice specific to certain operating systems. Posted-By: post_faq 2.10 Archive-name: usenet/software/inn-faq/part2 Last Changed: $Date: 1997/09/23 01:25:52 $ $Revision: 2.34 $ Part 2 of 9 INN FAQ Part 1: General and questions from people that don't (yet) run INN INN FAQ Part 2: Specific notes for specific operating systems INN FAQ Part 3: Reasons why INN isn't starting INN FAQ Part 4: The debugging tutorial (setup of feeds etc.) INN FAQ Part 5: Other error messages and what they mean INN FAQ Part 6: Day-to-day operation and changes to the system INN FAQ Part 7: Problems with INN already running INN FAQ Part 8: Appendix A: Norman's install guide INN FAQ Part 9: Appendix B: Configurations for certain systems ------------------------------ Subject: Table Of Contents for Part 2/9 ===================================================================== TABLE OF CONTENTS FOR PART 2/9 ===================================================================== SPECIFIC NOTES FOR SPECIFIC OPERATING SYSTEMS: 2.1 BASH tips 2.2 GNUS tips 2.3 AIX tips 2.4 SunOS 4.1.1 tips 2.5 Ultrix tips 2.6 HP-UX tips 2.7 UnixWare tips 2.8 Linux tips 2.9 A/UX 3.0 (Macintosh) tips 2.10 Alpha OSF tips 2.11 SGI IRIX 5.x tips 2.12 Systems where only root can have "cron" jobs. 2.13 System V based Unixes (SVR4, Solaris 2.x, SCO ODT 3.0, AIX, A/UX, DELL, ...) 2.14 Solaris 2.x special needs 2.15 Slackware Tips 2.16 BSDi 2.0 / FreeBSD / NetBSD 2.17 3Com Router users 2.18 NOV problems on a Pyramid 2.19 Warnings to people that must set HAVE_UNIX_DOMAIN to DONT 2.20 INN for SNI RM400 2.21 INN on NeXT-/OpenStep Note: See also Appendix B (Part 9 of the FAQ) ====================================================================== SPECIFIC NOTES FOR SPECIFIC OPERATING SYSTEMS ====================================================================== ------------------------------ Subject: (2.1) BASH tips If you are using a Unix who's /bin/sh is a hardlink to bash, you'll find problems using nntpsend. nntpsend uses a variable named PPID, which is a read-only variable in BASH. You'll get errors that look like this: sh: PPID: read-only variable You can fix it using the the following patch: *** nntpsend~ Thu Aug 12 03:36:16 1993 --- nntpsend Sat Oct 23 15:54:11 1993 *************** *** 1,4 **** ! #! /bin/sh ## $Revision: 2.34 $ ## Send news via NNTP by running several innxmit processes in the background. ## Usage: --- 1,4 ---- ! #!/usr/local/bin/bash ## $Revision: 2.34 $ ## Send news via NNTP by running several innxmit processes in the background. ## Usage: *************** *** 130,140 **** chmod 0660 ${LOG} exec >>${LOG} 2>&1 fi ! PPID=$$ ! echo "${PROGNAME}: [${PPID}] start" ## Set up environment. ! export BATCH PROGNAME PPID INNFLAGS ## Loop over all sites. cat ${INPUT} | while read SITE HOST MAXSIZE FLAGS; do --- 130,140 ---- chmod 0660 ${LOG} exec >>${LOG} 2>&1 fi ! CPID=$$ ! echo "${PROGNAME}: [${CPID}] start" ## Set up environment. ! export BATCH PROGNAME CPID INNFLAGS ## Loop over all sites. cat ${INPUT} | while read SITE HOST MAXSIZE FLAGS; do *************** *** 240,246 **** fi ## Start sending this site in the background. ! export SITE HOST LOCKS BATCHFILE PROGNAME PPID SIZE TMPDIR sh -c ' BATCHFILE=${HOST}.nntp LOCK=${LOCKS}/LOCK.${HOST} --- 240,246 ---- fi ## Start sending this site in the background. ! export SITE HOST LOCKS BATCHFILE PROGNAME CPID SIZE TMPDIR sh -c ' BATCHFILE=${HOST}.nntp LOCK=${LOCKS}/LOCK.${HOST} *************** *** 247,253 **** trap "rm -f ${LOCK} ; exit 1" 1 2 3 15 shlock -p $$ -f ${LOCK} || { WHY="`cat ${LOCK}`" ! echo "${PROGNAME}: [${PPID}:$$] ${HOST} locked ${WHY} `date`" exit } if [ -f ${SITE}.work ] ; then --- 247,253 ---- trap "rm -f ${LOCK} ; exit 1" 1 2 3 15 shlock -p $$ -f ${LOCK} || { WHY="`cat ${LOCK}`" ! echo "${PROGNAME}: [${CPID}:$$] ${HOST} locked ${WHY} `date`" exit } if [ -f ${SITE}.work ] ; then *************** *** 254,259 **** --- 254,260 ---- cat ${SITE}.work >>${BATCHFILE} rm -f ${SITE}.work fi + if [ -s ${SITE} ] ; then mv ${SITE} ${SITE}.work if ctlinnd -s -t30 flush ${SITE} ; then cat ${SITE}.work >>${BATCHFILE} *************** *** 260,273 **** rm -f ${SITE}.work test -n "${SIZE}" && shrinkfile -s${SIZE} -v ${BATCHFILE} if [ -s ${BATCHFILE} ] ; then ! echo "${PROGNAME}: [${PPID}:$$] begin ${HOST} `date`" ! echo "${PROGNAME}: [${PPID}:$$] innxmit ${INNFLAGS} ${HOST} ..." eval innxmit ${INNFLAGS} ${HOST} ${BATCH}/${BATCHFILE} ! echo "${PROGNAME}: [${PPID}:$$] end ${HOST} `date`" else rm -f ${BATCHFILE} fi fi rm -f ${LOCK} ' & sleep 5 --- 261,275 ---- rm -f ${SITE}.work test -n "${SIZE}" && shrinkfile -s${SIZE} -v ${BATCHFILE} if [ -s ${BATCHFILE} ] ; then ! echo "${PROGNAME}: [${CPID}:$$] begin ${HOST} `date`" ! echo "${PROGNAME}: [${CPID}:$$] innxmit ${INNFLAGS} ${HOST} ..." eval innxmit ${INNFLAGS} ${HOST} ${BATCH}/${BATCHFILE} ! echo "${PROGNAME}: [${CPID}:$$] end ${HOST} `date`" else rm -f ${BATCHFILE} fi fi + fi rm -f ${LOCK} ' & sleep 5 *************** *** 275,278 **** wait rm -f ${INPUT} ! echo "${PROGNAME}: [${PPID}] stop" --- 277,280 ---- wait rm -f ${INPUT} ! echo "${PROGNAME}: [${CPID}] stop" ------------------------------ Subject: (2.2) GNUS tips In article <3g82ll$mr4@tid.tid.es> Emilio Losantos writes: > I have to use GNUS 4.1 to read news from a nntp server running INN 1.4, but > whenever I try to select a group I receive the message: > "GROUP" not implemented; try "help" > Could anybody tell me how to fix this problem? jbryans@csulb.edu (Jack Bryans) replies: Patch your nntp.el something like this: *** 72,77 **** --- 72,79 ---- (set-process-sentinel nntp/connection 'nntp/sentinel) (process-kill-without-query nntp/connection) (let ( (code (nntp/response)) ) + (nntp/command "mode reader") + (nntp/response) (or (eq code 200) (eq code 201)))) (defun nntp-server-opened () Note that your line numbers may vary. There's a lot of nntp.el's out there. ------------------------------ Subject: (2.3) AIX tips Q: Is there a config.data for AIX 4.1 ? A: In you will find one for AIX 4.1.4 and INN1.5.1. If you want to use this with older INN versions, then you have to remove some lines from it. Note that it might be that in the sample CLX_STYLE is set to IOCTL. You might change this to FCNTL as described below (#2.13) if you get many overchan processes. Q: In config.data, should ACT_STYLE be set to READ or MMAP? A: Gee, some say MMAP works, some say it doesn't. I recommend you use READ. After you've been running for a month, try MMAP for a day and see what happens. Kurt Jaeger adds: On 3.2.5, MMAP works if one makes some patch to the innd so that it allocates one byte more than filelength(active) or filelength(history [or whatever is mapped by innd]). Reason: If filelength(active/whatever file) on AIX is a multiple of page size (4096 bytes), searching for a trailing NUL byte in a MMAPed file will kill the process with SEGV or the AIX equivalent. Q: What compiler should I use? A: Most people use what's listed in Install.ms, though we have one report of a AIX 3.2.5 user that found bsdcc worked better. Q: When I run news.daily, there's always a few lines of error messages at the end of the output: | compress: bad file number A: AIX /usr/bin/compress has a bug when compressing files with zero length. Then it spits out this error. Solution: Ignore it or use a different compress program and change config.data accordingly. (from Kurt Jaeger ) Q: innwatch doesn't work well from /etc/inittab, does it? A: Nope. Instead, you can create a "subsystem" with this command: mkssys -s innwatch -p /usr/local/news/bin/innwatch \ -u `id -u news` -G news -S -n 15 -f 9 Note that your path to innwatch may differ, depending on where you decided to install the inn components. You also need to enter the command as one long line. This will create a subsystem named "innwatch" belonging to an SRC group named "news". The "-S" means that it uses signals for SRC to tell it when to stop and the "-n" is the SIGTERM signal, for normal shutdown, and the "-f" is the SIGKILL signal, which is sent if the process does not stop within 20 seconds. Then, modify rc.news to issue the command startsrc -s innwatch to get innwatch going. That's it! Shane Castle Q: When I compile I get something like: 0706-317 ERROR: Unresolved or undefined symbols detected: Symbols in error (followed by references) are dumped to the load map. The -bloadmap: option will create a load map. .dbzwrit cd frontends ; make all ; cd .. Target all is up to date. A: That means you don't have a program called "patch" installed on your machine. Refer to "Subject: ld.so: Undefined symbol: _dbzwritethrough" Q: What can I change in innwatch.ctl to make it work right? A: The "df" command in AIX has a funny output that requires you to modify innwatch.ctl. The FTP site has an install.ctl that uses "df -i" (some AIX versions) and another one that uses "df -v" (recommended by someone with AIX 3.2.5). Q: Can I use a compressed filesystem? A: (From Kurt Jaeger): On AIX 4.1.x, use compressed filesystems with 512 bytes per fragment and 2048 bytes per inode. This is the best space optimazation I could find up to now. News is I/O bound, so doing some more compression to save on head seeks and reads will better balance your system. I currently have a 100/60% yield: If the disk would be 100% full, 60% of the inodes would be used. ------------------------------ Subject: (2.4) SunOS 4.1.1 tips SunOS 4.1.1 (but not 4.1.2 or 4.1.3) broke the write system call but a patch is available. Any write could fail "half way", it is just more likely to happen when writing large files and in-core DBZ writes the history file out in one chunk. The "Known Problems" section of the installation manual says to install Patch 100293-01, but that has been replaced by 100622-01. ------------------------------ Subject: (2.5) Ultrix tips Tip #1: Ultrix has a "mmap()" function, but it doesn't do the same thing as the SunOS/BSD mmap() function. Therefore, do not configure INN to use mmap() on a Ultrix system. INN wants to find a mmap() function that is like the one on SunOS/BSD systems. Tip #2: The sendsys script breaks Ultrix 'nawk'. You can make a 1-line change or you can switch to 'awk' or "gawk". Original line: ${AWK} "/^$1"'[/:\\]/,/[^\\]$/' ${NEWSFEEDS} >${TEMP} Modified line: ${AWK} "/^$1"'[\/:\\]/,/[^\\]$/' ${NEWSFEEDS} >${TEMP} The original line will work with awk, gawk, but not nawk. The modified line will work with awk, gawk, or nawk. If you have gawk running on your machine use it. Otherwise, switch to awk. Tip #3: The syslog on Ultrix sucks rotten eggs and Digital refuses to fix it. (source: everyone that uses Ultrix and has ever used other systems) Luckily, you can replace it with the routine that comes with INN. However, some people have had better luck installing the syslog that can be found on "gatekeeper.dec.com:/pub/DEC/jtkohl-syslog-complete.tar.Z". It still works with old clients but does new-style syslogging, too. Works great for me so far. (this information from: nelson@reed.edu (Nelson Minar)). The syslog that is shipped with INN works pretty well but there have been some claims that some old clients don't like it. ------------------------------ Subject: (2.6) HP-UX tips Q. My logs keep telling me there is no space for articles A. Edit innwatch.ctl to use "bdf" instead of "df". Q. I am running inn on an HP machine. INN won't start up automatically. I can start it manually. There is no problem with news or INN once it is started. A. Try adding a "sleep 10" to the bottom of /etc/rc.news, or in /etc/rc, right after /etc/rc.news is invoked. On some machines, including HP, the shell started by "#!/bin/sh" when /etc/rc is executed will exit before innd has disassociated itself from that shell. This causes innd to exit, sometimes without printing an error message. (source: pjoslin@mbvlab.wpafb.af.mil (Paul Joslin )) This problem goes away if you set HAVE_SETSID to "DO". Something to do with Posix Session Leader concepts. Ick. (source: Steve Howie ). You can also do something like: echo /usr/lib/etc/rc.news | at now + 2 minutes or else nohup su news -c /usr/local/etc/rc.news& HP-UX 8.x and 9.x users might find a problem with getting innwatch to start up. People have found that having "at" start it seems to work more reliably than other methods: ${DOINNWATCH} && { echo "${INNWATCH} &" | su ${NEWSUSER} -c 'at now + 2 min' > /dev/null } The '&' in the command line prevents innwatch from taking up an at-job slot. SysV-style crons have a per-category and overall limit on the number of jobs executing simultaneously. Q: INN-1.4sec running on an HP9000 s700 with HP-UX 9.01 leaks memory like crazy. The innd process grows and grows, then stops with: "ME cant remalloc 8192 bytes Not enough space" A: The cause turns out to be a memory leak in the standard C library (both /lib/libc.a and /lib/libc.sl). Installed patch PHCO_5056 (or the latest libc patch). ------------------------------ Subject: (2.7) UnixWare tips UnixWare 1.1.2 works with domain sockets. Install ptf149 "unix domain sockets" and ptf678 "fix for sockmod's incorrect handling of disconnect indication" Otherwise, configure like any SVR4 system. ------------------------------ Subject: (2.8) Linux tips Get inn-1.4-linux-0.1.tar from ftp://sunsite.unc.edu/pub/Linux/system/News It contains instructions for installing INN on a Linux system and a working config.data file. (from ghio@myriad.pc.cc.cmu.edu) If you don't follow the directions in inn-1.4-linux-0.1.tar, here are some of the problems you might have: > nntpsend.log says the following. > nntpsend: [214:222] innxmit -a -t300 -T1800 > travelers.mail.cornell.edu ... > Ignoring line "cornell/test/13 805 ..." > sh: PPID read-only variable Tomasz Surmacz writes: If you are using INN under Linux or have your /bin/sh a symlink to /bin/bash the above problem appears (in nntpsend precisely speaking, not innxmit) The problem is that bash already defines the PPID variable and nntpsend is trying to use it too. To fix this: 1. comment out line PPID = $$ 2. change all occurrences of PPID to say PARENTPID I have also noticed that changing first line of nntpsend from '#!/bin/sh' to "#!/bin/bash" helps in such occasions. Slackware 3.0 seems to have a different incarnation of df than others - so if you want to run innwatch change the following in innwatch.ctl: From: < ## =()@ ! throttle ! No space (spool inodes)>()= < !!! df -i . | awk 'NR == 2 { print $3 }' ! lt ! 200 ! throttle ! No space (spool inodes) To: > ## =()@ ! throttle ! No space (spool inodes)>()= > !!! df -i . | awk 'NR == 2 { print $4 }' ! lt ! 200 ! throttle ! No space (spool inodes) (from Jim Kerr ) ------ Linux 2.x complains at compiling: gcc -O -o nnrpd article.o group.o commands.o misc.o newnews.o nnrpd.o post.o loadave.o ../libinn.a loadave.o(.text+0x3b): undefined reference to `nlist' You can either add /usr/lib/libelf.a as missing library to the Makefile or apply the following patch (with some fuzz ... ) from coneill@premier1.premier.net (Clayton O'Neill) : --- /usr/local/news/INN/nnrpd/loadave.c Fri Jan 29 10:51:58 1993 +++ loadave.c Wed Jul 17 15:36:30 1996 @@ -1,8 +1,28 @@ -/* $Revision: 2.34 $ +/* $Revision: 2.34 $ ** */ #include "nnrpd.h" #if NNRP_LOADLIMIT > 0 +#ifdef linux + +/* +** Get the current load average as an integer. +*/ +int +GetLoadAverage() +{ + FILE *ProcLoadAve; + float load; + + if ((ProcLoadAve=fopen("/proc/loadavg", "r"))==NULL) + return -1; + if (fscanf(ProcLoadAve,"%f", &load)!=1) + return -1; + fclose(ProcLoadAve); + return (int)(load+0.5); +} + +#else #include [...] + #endif /* linux */ #endif /* NNRP_LOADLIMIT > 0 */ ------ In some newer versions of Linux, nnrpd seems to seg fault. Reason is the size of fd_set (1024 bit), but the macros FD_??? operate on 256bit). This happens if HAVE_UNISTD is set to DONT, so set it to DO. If it still happens, then include at the top of include/clibrary.h ------ It might be that rc.news never terminates in unoff4 (and probably other versions), when having DOINNWATCH=true. If this happenes then include a '&' in rc.news as shown: : ${DOINNWATCH} && { : ( sleep 60 ; ${INNWATCH} & ) & ^^^ ------------------------------ Subject: (2.9) A/UX 3.0 (Macintosh) tips Tip #1: Use the INN malloc. Tip #2: If you are running INN 1.4 on a Mac running A/UX 3.0.1, Every so often, (generally when someone fires up a reader), INN goes berserk. Syslog says: innd: ME cant select Bad file number This message repeats about 20 times per second. It freezes up my computer and I need to reboot. That's a kernel bug. You do have to reboot. If you compiled inn with gcc, don't. My experience was that somehow, if INN was compiled with GCC the kernel bug is triggered, but that doesn't happen with cc. ------------------------------ Subject: (2.10) Alpha OSF tips: To compile INN for the DEC Alpha, follow the instructions in the INN patch archive on ftp://ftp.isc.org/isc/inn/unoff-patches A config.data file for OSF1.3a is in: ftp://infinite.cs.swt.edu/pub/usenet/inn/ A config.data file for OSF3.0 is in: ftp://infinite.cs.swt.edu/pub/usenet/inn/ In rc.news you need to start $INNWATCH using the following: ${DOINNWATCH} && { echo "${INNWATCH} &" | su ${NEWSUSER} -c 'at now + 2 min' > /dev/null } The '&' in the command line prevents innwatch from taking up an at-job slot. SysV-style crons have a per-category and overall limit on the number of jobs executing simultaneously. ------------------------------ Subject: (2.11) SGI IRIX 5.x tips Some people have reported that IRIX 5.1 isn't very reliable and that it is worth it to run 5.2. 5.3 is even better, but it is still not perfect. (In other words: IT WORKS FINE AS Install.ms DESCRIBES!) Robert Keller has some tips for filesystem layout: NOTE: For efs filesystems, you want to be sure that you mount your news spool using the lbsize option (/etc/fstab) set to 4096, eg: /dev/dsk/dks1d5s7 /spool efs rw,raw=/dev/rdsk/dks1d5s7,lbsize=4096 0 0 This tells efs to only preallocate 4K worth of space on the first write of a file to disk. The default of 32K causes a terrible waste of effort for the writing of an average 2K news posting. This also can Innd slow down quite a bit, as the efs is searching for spare 32kB blocks on disk. If you can use xfs then do so. For the new xfs filesystems, you want to be increase the default filesystem block size from 512 bytes to about 2K for maximum performance. I just setup a 8 Gig xfs news spool on a Challenge L using 2K blocks and the performance is absolutely incredible. See also for more tips on running INN on SGI platforms. Another note to the 5.3XFS: (From: olson@anchor.engr.sgi.com (Dave Olson)) The ordering/location of files in a directory can change when files are unlinked, with xfs, and some of fastrm's assumptions therefore break. So if you get files which are to be expired with fastrm, but which stay in spool, then try to use normal expire or edit expirerm to remove -s option from RMPROC: old: RMPROC="fastrm -e -s ${SPOOL}" new: RMPROC="fastrm -e -u ${SPOOL}" 6.2XFS has been changed to respect the traditional readdir() behaviour (after rck@fangio.asd.sgi.com (Robert Keller)). Jack Bryans writes: Both ACT_STYLE and DBZCFLAGS may use MMAP. If you use either, you'll need the following patch: *** include/clibrary.h.orig Thu Mar 18 13:04:07 1993 --- include/clibrary.h Sat Mar 9 14:13:40 1996 *************** *** 103,109 **** --- 103,111 ---- extern POINTER malloc(); extern POINTER realloc(); #if defined(ACT_MMAP) + #ifndef __sgi extern char *mmap(); + #endif /* not sgi */ #endif /* defined(ACT_MMAP) */ ------------------------------ Subject: (2.12) Systems where only root can have "cron" jobs. Your cron jobs may not work if you use: su news -c /usr/lib/news/bin/news.daily delayrm expireover Instead, you must put the entire command in quotes. Like this: su news -c "/usr/lib/news/bin/news.daily delayrm expireover" Look for "Pyramid" later in this FAQ for the interesting details. ------------------------------ Subject: (2.13) System V based Unixes (SVR4, Solaris 2.x, SCO ODT 3.0, AIX, A/UX, DELL, ...) NOTE: Solaris 2.x is based on SVR4.0. These tips are useful in a limited way. Read this section for general advice, but follow the "Solaris 2.x" section details. If you are running any non-BSD (i.e. System V based) Unix you MUST have the following option set: ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE FCNTL This includes SVR4, Solaris 2.x, A/UX and SCO ODT 3.0. (SVR4 means systems based on System V Release 4 from USL. Please check your manual to see if your operating system is based on SVR4.) This CLX_STYLE setting is clearly stated in the Install.ms file and repeated here since so many people post to news.software.nntp after ignoring the warnings. If CLX_STYLE isn't set to FCNTL, you'll get tons of overchan processes hanging around. With SCO ODT 3.0 and MOST systems, innd will link and run if you use IOCTL but eventually will stop answering incoming calls. Don't be fooled. Just because it compiles doesn't mean it's going to work. If you start innd on an AT&T SysV Rel 4.0 machine and get syslog messages like: localhost:15 cant setsockopt(SNDBUF) Protocol error localhost:15 cant setsockopt(RCVBUF) Protocol error then you should FIRST try to change HAVE_UNIX_DOMAIN to "DONT" in config.data. If that doesn't fix the problem, you should add "-USO_SNDBUF" to your DEFS parameter in config.data. Or, you can comment out the "setsockopt()" calls. This is also mentioned in the Install.ms file (which means if you needed to read it here, you weren't paying attention when you read Install.ms) Many SVR4 for i486 binaries (sendmail, mh, vmail, innd, rnews are now on ftp.germany.eu.net in pub/comp/i486/svr4/*.SVR4.tgz But remember that some of the above need site specific changes, so their usefulness may be limited. If you get syslog messages that say, "ME cant accept RCreader" please refer to Part 3 of this FAQ. DELL ships their Unix with /dev/log chmod'ed to 0644 which means nobody can syslog anything. Pretty stupid, eh? INN uses syslog extensively. If you find that you don't get any syslog messages check to see if you need to: "chmod 0666 /dev/log". Nobody knows why SVR4 boxes often give error messages like, "innd: accept: SIOCGPGRP failed errno 22". There's some sort of obscure bug with the SVR4 accept() call that can lead to these messages, if the executable is linked a certain way. I suspect that the same symbol -- for two totally separate variables or routines -- is defined in two different libraries, so if you link in certain ways you get the "wrong" thing. This error drove me crazy when I first built sendmail V8 on our NCR 3000 box. But I re-linked it a different way and I haven't seen the error since. Good riddance. I suggest you play around with your link libraries and/or order of linkage. kevin@cfc.com (Kevin Darcy) says he never gets these messages since he started using (in config.data): LIBS -lsocket -lnsl -lelf If your SVR4 system still doesn't run correctly, check the Solaris 2.x suggestions. ------------------------------ Subject: (2.14) Solaris 2.x special needs Solaris 2.5: Sun assures that Solaris 2.5 does no longer have the socket bug (see fix #7 below) and Dave Zavatson writes that the bug still exists ... So if you see "'resource temp unavailable' errors, you have to apply it. Joe St Sauver submitted the following: | Symptom: One of the topologically distant sites notices far lower than normal | article throughput. Further investigation by the remote site (using netstat) | identifies a large number of "completely duplicated packets" originating | with the Solaris feed host. | Resolution: The local Solaris 2.5 host had not applied Sun patches 103169-05 | ("ip driver and ifconfig fixes") and 103447-03 ("tcp patch") as can be | obtained from ftp://sunsolve1.Sun.COM/pub/patches/patches.html | (Solaris 2.5.1 users, see 103582-01 and 103630-01). | Without these patches, when working with hosts that are topologically | remote, TCP/IP throughput reportedly can drop to as little as 5% of | what it should be. | For further information, see: <199607140422.VAA04495@yorick.cygnus.com> | quoting a 7 June 1996 article posted to comp.unix.solaris by Cathe A. Ray | (Manager of Internet Engineering for Sun). | Thanks to Howard Goldstein for the detective work in | isolating and resolving this problem! SOLARIS 2.4: Install the Recommended cluster patch from Sun. The Recommended cluster patch is: ftp://sunsolve1.sun.com/pub/patches/2.4_Recommended.tar.Z The README is: ftp://sunsolve1.sun.com/pub/patches/2.4_Recommended.README Then follow the directions in ftp://ftp.isc.org/isc/inn/unoff-patches/OLD/solaris-2.4.patch. The patch needs to be applied BY HAND, it is not in the correct format to work with Larry Wall's patch program. Also, do *not* link with the /usr/ucblib stuff, and HAVE_WAITPID should be set to "DO". On 3/25/95 Sun introduced patch 101945-23 which fixes bug #1178506 titled "INN wounded after upgrade to SunOS 5.4". This fixes the "cant read Resource temporarily unavailable" bug that some have reported. But Even if the Sun Patch mentions "1186224 socket select hangs in NON-BLOCKED mode", this seems not to be totally fixed. Ian Dickinson doesn't notice it on his lightly loaded server. But on heavily loaded machines, it occurs occasionally (<5 times a day). See below for a patch (Solaris Fix #7 ) It seems that the last version of the kernel patch for Sparc is 19945-36; 191945-29 is known to work. For x86 the latest version is 101946-29, which has problems with Unix domain sockets, so 101946-12 seems to be the last usable one here ... Include /opt/SUNWspro/bin and /usr/bin in your path before /usr/ucb as /usr/ucb/sed does not work well. SOLARIS 2.3: If you install the "Recommended cluster patch" I *think* you will only need to pay attention to Fix #5 listed below. It would be helpful if people sent an update about this. The Recommended cluster patch is: ftp://sunsolve1.sun.com/pub/patches/2.3_Recommended.tar.Z The README is: ftp://sunsolve1.sun.com/pub/patches/2.3_Recommended.README (note: If you trust other people to compile programs for you [especially ones that run as root] you can get inn1.4sec pre-compiled w/gcc at ccnews.ke.sanet.sk:/pub/solaris/inn1.4sec-src+bin.tar.gz) INN works with Solaris 2.[0123]. It's not easy, but it will work. The problem is that depending on which Solaris patches you have installed, you have to install various INN patches. There are too many combinations of Sun patches and INN patches to be able to say what is required and what isn't. (See the "SOLARIS 2.3" tip above for one tried and tested configuration). Here is the general guide: Step 1: Use the info for config.data for Solaris 2.x that is included Install.ms. Step 2: As you go, if you get any of the problems listed below, try the fix listed. Eventually you will be up and running with only the fixes you need. If you try to install ALL the fixes at once, things will definitely not work. COMPILER TIPS: Use gcc or /opt/SUNWspro/bin/cc. Do *not* use /usr/ucb/cc. In fact, remove /usr/ucb from your path when you compile. For directory structure - be careful about /var/news, as the news(1) tool also writes in this area an might damage your files. (Need more input on this). The patch program supplied with Solaris 2.5 appears to not understand the "new-style" context diffs which virtually everyone uses these days so you have to fetch the gnu-patch as described in part8 of this FAQ. Also it doesn't know -p0 option ; it wants -p 0 and the file to patch has to be writable. ---------- Solaris Fix #1 Under Solaris 2.[012] (SunOS 5.0, 5.1, 5.2) you must add the following at the beginning of each file using gethostbyname(): #define gethostbyname __switch_gethostbyname Under Solaris 2.3 gethostbyname() might work without changes depending on your configuration. We haven't figured out when they work and when they don't. If you run into problems, try to change "gethostbyname()" to "solaris_gethostbyname()" and then use the gethostbyname() listed in the Solaris Porting FAQ. This isn't a perfect solution, because you now need a different binary for Solaris 2.[012] systems. It also seems to be a good idea to put dns in front of nis in /etc/nsswitch.conf hosts: dns nis files It would be great if someone were to submit a solaris_gethostbyname() function who's binary works under all Solaris revs and gives all the semantics of BSD gethostbyname(). In particular, one that doesn't have the problems discussed in sun bugid #1126573 or #1135988. It would be amazing if this was submitted by one of the many Sun employees that flame the INN FAQ maintainer in comp.sys.sun.admin every time he bitches about how much he hates Solaris 2.x. :-) ---------- Solaris Fix #2 Under all Solaris 2.* versions there is a problem with innwatch.ctl. It expects to use "df -i" to find out how many inodes are free on your disk. /usr/{sbin,5bin,bin}/df doesn't support the "-i" option, it has a "-e" option that outputs the info you want, but in a different format. You should use "/usr/ucb/df -i" instead, since this version of df includes the "-i" option. If you have too much space left on your disks (;-)) you will see the following: Filesystem iused ifree %iused Mounted on /dev/md/dsk/d10 103495213433720 7% /var/spool/news So awk will print 7% as number of free inodes ... Ian Dickinson wrote a inndf which can be found at the usual place. This inndf compiled with gcc and -DHAVE_STATVFS seems to work though (after Nash E. Foster ). A new version of this is available which works with large filesystems is available from ftp://ftp.csv.warwick.ac.uk/pub/usenet/inn/inndf.tar.gz If you have your news spool NFS mounted from another box, which is absolutely not recommended (see #5.15 , ME cant nonblock), then the following might help: rsh other_box /usr/ucb/df -u /var/spool/news /usr/ucb/df is part of the BSD Compatibility stuff. If you loaded Solaris 2.x without that, you can replace innwatch.ctl's disk checks with these lines: ## If load is OK, check space (and inodes) on various filesystems ## =()@ ! throttle ! No space (spool)>()= !!! /usr/bin/df -k . | awk 'NR == 2 { print $4 }' ! lt ! 8000 ! throttle ! No space (spool) ## =()@ | awk 'NR == 2 { print $4 }' ! lt ! @@ ! throttle ! No space (newsq)>()= !!! /usr/bin/df -k /news2/spool/out.going | awk 'NR == 2 { print $4 }' ! lt ! 800 ! throttle ! No space (newsq) ## =()@ | awk 'NR == 2 { print $4 }' ! lt ! @@ ! throttle ! No space (newslib)>()= !!! /usr/bin/df -k /news2/privcontrol | awk 'NR == 2 { print $4 }' ! lt ! 40000 ! throttle ! No space (newslib) ## =()@ | awk 'NR == 2 { print $4 }' ! lt ! @@ ! throttle ! No space (overview)>()= !!! /usr/bin/df -k /news3/overview | awk 'NR == 2 { print $4 }' ! lt ! 6000 ! throttle ! No space (overview) ## =()@ ! throttle ! No space (spool inodes)>()= !!! /usr/bin/df -e . | awk 'NR == 2 { print $2 }' ! lt ! 200 ! throttle ! No space (spool inodes) ---------- Solaris fix #3 Don't run the "lint" step if you use Solaris. In fact, nobody needs to execute this step except Rich, when he's writing new code. If you have a Solaris machine without "lint", just make "lint" a symlink to "/bin/echo". ---------- Solaris fix #4 People running Solaris 2.3 have built INN with HAVE_UNIX_DOMAIN set to TRUE and everything seems to be ok. I guess Sun has fixed enough bugs in 2.3 to make it usable. I recommend the latest "recommended patches" if you run any version of Solaris 2.x. To install all of the "Recommended Patches" in one command, refer to: ftp://sunsolve1.sun.com/pub/patches/patches.html ---------- Solaris fix #5 If "inews" outputs "Bad Message-ID" when posting Under Solaris 2.x (where x = 0, 1, 2 or 3) you need to change the file "getfqdn.c". Find the lines that read: if (strchr(hp->h_name, '.') == NULL) { /* Try to force DNS lookup if NIS/whatever gets in the way. */ (void)strncpy(temp, buff, sizeof buff); (void)strcat(temp, "."); hp = gethostbyname(temp); } and delete them. ---------- Solaris fix #6 If posting gets you "441 Can't generate Message-ID, Error 0" and you are running with DNS, then the problem is with Solaris 2.3's gethostbyname. dns. If you ask for a host with "hostname." it returns "hostname." instead "hostname.yourdomain.com" as expected by nn. The workaround is to define "domain" in your inn.conf and apply the following patch to getfqdn.c: *** getfqdn.c.~1~ Sun Sep 4 09:02:37 1994 --- getfqdn.c Sun Sep 4 09:53:11 1994 *************** *** 35,45 **** if ((hp = gethostbyname(buff)) == NULL) return NULL; ! if (strchr(hp->h_name, '.') == NULL) { ! /* Try to force DNS lookup if NIS/whatever gets in the way. */ ! (void)strncpy(temp, buff, sizeof buff); ! (void)strcat(temp, "."); ! hp = gethostbyname(temp); ! } ! if (hp != NULL && strchr(hp->h_name, '.') != NULL) { if (strlen(hp->h_name) < sizeof buff - 1) return strcpy(buff, hp->h_name); --- 35,39 ---- if ((hp = gethostbyname(buff)) == NULL) return NULL; ! if (strchr(hp->h_name, '.') != NULL) { if (strlen(hp->h_name) < sizeof buff - 1) return strcpy(buff, hp->h_name); ---------- Solaris fix #7 From Ian Dickinson : Sun appear to reduced the frequency of the problem, but not fixed the bug itself. I still need this under SunOS5.4 101945-29. You should already have -DSUNOS5 in your DEFS setting in config.data anyway. (Note that in 1.5.x this workaround is already in the source. You can enable with with specifying -DPOLL_BUG in the DEFS settings in config.data. Thanks to rhaskins@shiva.com who pointed that out). This should apply - maybe with a bit of fuzz: *** innd/chan.c.ORIG Wed Dec 14 11:03:16 1994 --- innd/chan.c Thu Dec 15 17:00:54 1994 *************** *** 497,502 **** --- 497,508 ---- bp->Left = bp->Size - bp->Used; i = read(cp->fd, &bp->Data[bp->Used], bp->Left - 1); if (i < 0) { + #ifdef SUNOS5 + /* return of -2 indicates EAGAIN, for SUNOS5.4 poll() bug workaround */ + if (errno == EAGAIN) { + return -2; + } + #endif syslog(L_ERROR, "%s cant read %m", p); return -1; } *** innd/nc.c.ORIG Thu Mar 18 21:04:28 1993 --- innd/nc.c Thu Dec 15 17:00:41 1994 *************** *** 783,788 **** --- 783,794 ---- /* Read any data that's there; ignore errors (retry next time it's our * turn) and if we got nothing, then it's EOF so mark it closed. */ if ((i = CHANreadtext(cp)) < 0) { + #ifdef SUNOS5 + /* return of -2 indicates EAGAIN, for SUNOS5.4 poll() bug workaround */ + if (i == -2) { + return; + } + #endif if (cp->BadReads++ >= BAD_IO_COUNT) { if (NCcount > 0) NCcount--; ---------- Solaris fix #8 From: Joe St Sauver We recently upgraded some machines in our news farm to fast ethernet, and after doing so we noticed poor performance (ping times of 30msec between two machines each connected to dedicated switch ports on the same switch...). Poking around a little, we noticed that under Solaris 2.5, tcp_conn_req_max is set to 32 by default, which is a little low if you are working with a fair number of peers or have a lot of readers. We bumped that value to 1000 or so (1024 max under Solaris 2.5), using: # ndd -set /dev/tcp tcp_conn_req_max 1000 and now ping times are back into the 0 or 1 msec reported range you'd hope to see from that sort of topology. :-) ------------------------------ Subject: (2.15) Slackware Tips Slackware comes with The Reference Implementation of NNTP as well as INN. However, if you select "INN" it doesn't remove the nntp entry in your /etc/inetd.conf. If the Slackware people aren't sure why INN requires you to remove that line from /etc/inetd.conf, they should get out of the business. (oh, they can complain to tal@plts.org... he wrote this paragraph). ------------------------------ Subject: (2.16) BSDi 2.0 / FreeBSD / NetBSD Paul Vixie wrote that for BSDi 2.0the use of mmap for use with the history file is ok (add -DMMAP to DBZCFLAGS in config.data), but not for active, so set ACT_STYLE to READ. Others write that it is not. Your mileage may vary and depend on how heavily-used your machine is. For NetBSD1.0 and 1.1 one shouldn't use mmap() unless you add the following: *** icd.c.orig Wed Jun 7 15:04:05 1995 --- icd.c Sat Dec 30 16:22:50 1995 *************** *** 369,375 **** ICDwriteactive() { #if defined(ACT_MMAP) ! /* No-op. */ #else --- 369,375 ---- ICDwriteactive() { #if defined(ACT_MMAP) ! msync(ICDactpointer, 0); #else In NetBSD 1.1 the use of -DMMAP is also ok.(after Curt Sampson ) FreeBSD users should use mmap() with caution. There are serious problems with some realeases of the FreeBSD operating system concerning mmap() and the performance without is quite good. With current releases, namely 2.2.1, this seems fixed. Users of 4.4 BSD derived systems should set LSEEKVAL in config.data to ``off_t'' in order to reflect the 64bit long off_t's in those systems. If you have problems with makehistory on BSDi then replace the BSDi sort command with an other one e.g. from the gnu textutils package. It seems that the BSDi one has some problems with 64kB boundaries. BSDi has a default some datasize limits which will let some operations fail. Add the following at the beginning of rc.news (and also of news.daily): limit datasize unlimited limit openfiles 256 limit memoryuse unlimited limit maxproc unlimited If this still fails look at #5.24 (the same applies to FreeBSD). In 2.1, BSDi introduced a bug with wrong spelling of ``february'' somewhere which lets inn fail somehow .. But they also have a patch: ftp://ftp.bsdi.com/bsdi/patches/patches-2.1/U210-002 Here's the Summary from the fix: This patch fixes a bug in the BSD/OS 2.1 release of the inn programs. A fix that we made between the 2.0 and 2.1 releases introduced a bug that caused innd to incorrectly parse dates. The symptom is that inn programs fail with "437 Bad "Date" header" in the /var/log/news/news file, or that Pnews will fail with "441 Can't parse "Date" header" messages. For FreeBSD 2.1.6 and INN1.5 Vincent Archer has written a autoconf package, that you can get from James will try to incorporate this into the main INN tree. To get it to work: Go to your inn 1.5 source directory, untar, you'll get configure and config/config.data.in. Type ./configure; make; make install :) (well, you might want to check the pathnames and parameters first, or type ./configure --help) ------------------------------ Subject: (2.17) 3Com Router users If you observe strange behavior, like nnrpd locking and not sending some articles to the clients, and if you find no clues about other potential problems, then check your IP layer: some users have observed bugs in the IP implementation of 3Com routers caused TCP sessions lock outs. You have very probably also NFS problems then. Upgrading to the latest PROMs fixes this totally bizarre problem. ------------------------------ Subject: (2.18) NOV problems on a Pyramid This applies only to Pyramid systems that run OSx. Newer systems run DC/OSx and/or Sinix 5.43 which are "normal" SysV that have normal cronjobs. Q: I just turned on the overview stuff and I don't think news.daily is properly expiring the .overview files. I'm using a Pyramid. A: Do you need quotes in your crontab entry? Look at your news.daily report -- expire using "expireover delayrm" should take a few minutes. If it takes longer than, say, 10-20 minutes, then the keywords aren't being seen by news.daily so perhaps the commandline quoting is wrong. i.e. you had: su news -c /usr/lib/news/bin/news.daily delayrm expireover You should have: su news -c "/usr/lib/news/bin/news.daily delayrm expireover" Without quoting, the options are thrown away and only the "news.daily" is executed. ------------------------------ Subject: (2.19) Warnings to people that must set HAVE_UNIX_DOMAIN to DONT Disclaimer: First of all, if you have to set HAVE_UNIX_DOMAIN to DONT, YOU HAVE TO SET IT to DONT. It's not a choice you can make, it's a description of the operating system that you've purchased. If you've wrongly set this variable to DO your system isn't going to work *at* *all*. When you use POST (the NNTP command), you are talking to nnrpd. nnrpd cleans up your headers, adds the missing headers that it is allowed to add, checks whatever it checks, and then submits the finalized version to innd. How does it talk to innd? If you have HAVE_UNIX_DOMAIN set to DO, nnrpd opens a Unix domain socket and sends the text. At this point it is talking to innd somewhat like ctlinnd does. innd can trust that the post isn't forged since it is coming from a program trustworthy enough to get to the socket (which isn't much). If you have HAVE_UNIX_DOMAIN set to DONT, it has no choice but to open a socket to port 119, issue the "IHAVE" command, and send the text that way (just like a remote newsreader). This means that innd (not another nnrpd) has to be at the other end of the pipe. If it opens the connection and sees a "nnrpd" you're hosed and you get "441 480 Transfer permission denied". (Better the "441 480" message than an infinite loop of nnrpd's connecting to nnrpd's!) To get innd to not hand off the connection to a nnrpd process, you must have the host's name in the hosts.nntp file. (don't forget to do "ctlinnd reload hosts.nntp") If you have your host's name in the hosts.nntp file, then any newsreader running on your nntphost must be "INN-aware" (i.e. that they issue the "mode reader" command) or they must read news via the file system instead of NNTP. If you have NNTP-based newsreaders that can't send the "mode reader" command, you can try including "server: localhost" in your inn.conf file, but then you must have a different inn.conf file for the other machines. If you can't do that, you have no other options but to recompile your newsreaders. Remember, if you change your inn.conf file, you must shutdown and restart innd. There is no "ctlinnd reload inn.conf" command. There is a patch which is listed in the unoff3/UNOFF-NOTES that seems to work at least for linux but should theoretically work for other os that have to set HAVE_UNIX_DOMAIN to DONT which resolves the problem that multiple invocations of ctlinnd break. ------------------------------ Subject: (2.20) INN for SNI RM400 There seems to be no working config.data available for that hardware, but you can get a ported version of INN from SNI in the ``NetServe'' package. If anyone has a working configuration and tips how to get there, then mail the FAQ maintainer for inclusion in part9 .. ------------------------------ Subject: (2.21) INN on NeXT-/OpenStep Scott Anguish has made his tips of configuring INN on NeXT-/OpenStep available on http://www.stepwise.com/Resources/Software/inn_1.5.1_configuration.html inn-1.7.2/nnrpd/0040755000175100001440000000000006443103542011753 5ustar mdusersinn-1.7.2/nnrpd/misc.c0100644000175100001440000002250406443103542013052 0ustar mdusers/* $Revision: 1.18 $ ** ** Miscellaneous support routines. */ #include #include #include "configdata.h" #include "clibrary.h" #include "nnrpd.h" #include "dbz.h" #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #define ASCtoNUM(c) ((c) - '0') #define CHARStoINT(c1, c2) (ASCtoNUM((c1)) * 10 + ASCtoNUM((c2))) #define DaysInYear(y) ((y % 4 ? 365 : 366)) /* ** Parse a string into a NULL-terminated array of words; return number ** of words. If argvp isn't NULL, it and what it points to will be ** DISPOSE'd. */ int Argify(line, argvp) char *line; char ***argvp; { register char **argv; register char *p; register int i; if (*argvp != NULL) { DISPOSE(*argvp[0]); DISPOSE(*argvp); } /* Copy the line, which we will split up. */ while (ISWHITE(*line)) line++; i = strlen(line); p = NEW(char, i + 1); (void)strcpy(p, line); /* Allocate worst-case amount of space. */ for (*argvp = argv = NEW(char*, i + 2); *p; ) { /* Mark start of this word, find its end. */ for (*argv++ = p; *p && !ISWHITE(*p); ) p++; if (*p == '\0') break; /* Nip off word, skip whitespace. */ for (*p++ = '\0'; ISWHITE(*p); ) p++; } *argv = NULL; return argv - *argvp; } /* ** Take a vector which Argify made and glue it back together with ** spaces between each element. Returns a pointer to dynamic space. */ char * Glom(av) char **av; { register char **v; register char *p; register int i; char *save; /* Get space. */ for (i = 0, v = av; *v; v++) i += strlen(*v) + 1; for (save = p = NEW(char, i + 1), v = av; *v; v++) { if (p > save) *p++ = ' '; p += strlen(strcpy(p, *v)); } return save; } /* ** Match a list of newsgroup specifiers against a list of newsgroups. ** func is called to see if there is a match. */ BOOL PERMmatch(match, Pats, list) register BOOL match; char **Pats; char **list; { register int i; register char *p; if (Pats[0] == NULL) return TRUE; for ( ; *list; list++) { for (i = 0; (p = Pats[i]) != NULL; i++) { if (p[0] == '!') { if (wildmat(*list, ++p)) match = FALSE; } else if (wildmat(*list, p)) match = TRUE; } if (match) /* If we can read it in one group, we can read it, period. */ return TRUE; } return FALSE; } /* ** Check to see if user is allowed to see this article by matching ** Newsgroups line. */ BOOL PERMartok(qp) register QIOSTATE *qp; { static char **grplist; register char *p; register char *q; BOOL found; if (!PERMspecified) return PERMdefault; for (found = FALSE; ; ) { p = QIOread(qp); if (p == NULL) { if (QIOtoolong(qp)) continue; break; } if (*p == '\n') /* End of header */ break; if (*p != 'N' && *p != 'n') continue; if ((q = strchr(p, ':')) == NULL) continue; *q = '\0'; if (caseEQ(p, "newsgroups")) { found = NGgetlist(&grplist, q + 2); break; } } (void)QIOrewind(qp); if (!found) /* No newgroups or null entry. */ return 1; return PERMmatch(PERMdefault, PERMlist, grplist); } /* ** Parse a date like yymmddhhmmss into a long. Return -1 on error. */ long NNTPtoGMT(av1, av2) char *av1; char *av2; { /* Note that this is origin-one! */ static int DaysInMonth[12] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 }; register char *p; int year; int month; int day; int hour; int mins; int secs; register int i; long seconds; char buff[6 + 6 + 1]; if (strlen(av1) != 6 || strlen(av2) != 6) return -1; (void)sprintf(buff, "%s%s", av1, av2); for (p = buff; *p; p++) if (!CTYPE(isdigit, *p)) return -1; year = CHARStoINT(buff[ 0], buff[ 1]); month = CHARStoINT(buff[ 2], buff[ 3]); day = CHARStoINT(buff[ 4], buff[ 5]); hour = CHARStoINT(buff[ 6], buff[ 7]); mins = CHARStoINT(buff[ 8], buff[ 9]); secs = CHARStoINT(buff[10], buff[11]); if (month < 1 || month > 12 || day < 1 || day > 31 || mins < 0 || mins > 59 || secs < 0 || secs > 59) return -1; if (hour == 24) { hour = 0; day++; } else if (hour < 0 || hour > 23) return -1; if (year < 50) year += 100 ; for (seconds = 0, year += 1900, i = 1970; i < year; i++) seconds += DaysInYear(i); if (DaysInYear(year) == 366 && month > 2) seconds++; while (--month > 0) seconds += DaysInMonth[month]; seconds += day - 1; seconds = 24 * seconds + hour; seconds = 60 * seconds + mins; seconds = 60 * seconds + secs; return seconds; } /* ** Convert local time (seconds since epoch) to GMT. */ long LOCALtoGMT(t) long t; { TIMEINFO Now; (void)GetTimeInfo(&Now); t += Now.tzone * 60; return t; } /* ** Return the path name of an article if it is in the history file. ** Return a pointer to static data. */ char * HISgetent(msg_id, fulldata) char *msg_id; BOOL fulldata; { static BOOL setup; #if NNRP_DBZINCORE_DELAY > 0 static int count = NNRP_DBZINCORE_DELAY; #endif /* NNRP_DBZINCORE_DELAY > 0 */ static FILE *hfp; static char path[BIG_BUFFER]; register char *p; register char *q; register int i; char *save; char buff[BIG_BUFFER]; OFFSET_T l; datum key; datum value; struct stat Sb; #if NNRP_DBZINCORE_DELAY > 0 if (count && --count == 0) { if (setup) { (void)dbmclose(); setup = FALSE; } (void)dbzincore(1); } #endif /* NNRP_DBZINCORE_DELAY > 0 */ if (!setup) { if (dbminit(HISTORY) < 0) { syslog(L_ERROR, "%s cant dbminit %s %m", ClientHost, HISTORY); return NULL; } setup = TRUE; } /* Set the key value, fetch the entry. */ for (p = key.dptr = msg_id; *p; p++) if (*p == HIS_FIELDSEP || *p == '\n') *p = HIS_BADCHAR; key.dsize = p - key.dptr + 1; value = dbzfetch(key); if (value.dptr == NULL) return NULL; for (q = (char *)&l, p = value.dptr, i = sizeof l; --i >= 0; ) *q++ = *p++; /* Open history file if we need to. */ if (hfp == NULL) { if ((hfp = fopen(HISTORY, "r")) == NULL) { syslog(L_ERROR, "%s cant fopen %s %m", ClientHost, HISTORY); return NULL; } CloseOnExec((int)fileno(hfp), TRUE); } /* Seek and read. */ if (fseek(hfp, l, SEEK_SET) == -1) { syslog(L_ERROR, "%s cant fseek to %ld %m", ClientHost, l); return NULL; } if (fgets(buff, sizeof buff, hfp) == NULL) { syslog(L_ERROR, "%s cant fgets from %ld %m", ClientHost, l); return NULL; } if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; /* Skip first two fields. */ if ((p = strchr(buff, '\t')) == NULL) { syslog(L_ERROR, "%s bad_history at %ld for %s", ClientHost, l, msg_id); return NULL; } if ((p = strchr(p + 1, '\t')) == NULL) /* Article has expired. */ return NULL; save = p + 1; /* Want the full data? */ if (fulldata) { (void)strcpy(path, save); for (p = path; *p; p++) if (*p == '.') *p = '/'; return path; } /* Want something we can open; loop over all entries. */ for ( ; ; save = q + 1) { if ((q = strchr(save, ' ')) != NULL) *q = '\0'; for (p = save; *p; p++) if (*p == '.') *p = '/'; (void)sprintf(path, "%s/%s", _PATH_SPOOL, save); if (stat(path, &Sb) >= 0) return path; if (q == NULL) break; } return NULL; } /* ** Parse a newsgroups line, return TRUE if there were any. */ BOOL NGgetlist(argvp, list) char ***argvp; char *list; { register char *p; for (p = list; *p; p++) if (*p == ',') *p = ' '; return Argify(list, argvp) != 0; } /* ** Take an NNTP distribution list and turn it into an array. */ BOOL ParseDistlist(argvp, list) char ***argvp; char *list; { static char **argv; register char *p; if (list[0] != '<' || (p = strchr(&list[1], '>')) == NULL) return FALSE; *p = '\0'; for (p = list + 1; *p; p++) if (*p == ',') *p = ' '; (void)Argify(list + 1, &argv); *argvp = argv; return TRUE; } /* ** Read a line of input, with timeout. */ READTYPE READline(start, size, timeout) char *start; int size; int timeout; { static int count; static char buffer[BUFSIZ]; static char *bp; register char *p; register char *end; struct timeval t; FDSET rmask; int i; char c; for (p = start, end = &start[size - 1]; ; ) { if (count == 0) { /* Fill the buffer. */ Again: FD_ZERO(&rmask); FD_SET(STDIN, &rmask); t.tv_sec = timeout; t.tv_usec = 0; i = select(STDIN + 1, &rmask, (FDSET *)NULL, (FDSET *)NULL, &t); if (i < 0) { if (errno == EINTR) goto Again; syslog(L_ERROR, "%s cant select %m", ClientHost); return RTtimeout; } if (i == 0 || !FD_ISSET(STDIN, &rmask)) return RTtimeout; count = read(STDIN, buffer, sizeof buffer); if (count < 0) { syslog(L_ERROR, "%s cant read %m", ClientHost); return RTtimeout; } if (count == 0) return RTeof; bp = buffer; } /* Process next character. */ count--; c = *bp++; if (c == '\n') break; if (p < end) *p++ = c; } /* If last two characters are \r\n, kill the \r as well as the \n. */ if (p > start && p < end && p[-1] == '\r') p--; *p = '\0'; return p == end ? RTlong : RTok; } inn-1.7.2/nnrpd/commands.c0100644000175100001440000003650406443103542013725 0ustar mdusers/* $Revision: 1.22 $ ** ** Miscellaneous commands. */ #include #include #include "configdata.h" #include "clibrary.h" #include "nnrpd.h" #include typedef struct _LISTINFO { STRING File; BOOL Required; STRING Items; STRING Format; } LISTINFO; STATIC LISTINFO INFOactive = { ACTIVE, TRUE, "active newsgroups", "Newsgroups in form \"group high low flags\"" }; STATIC LISTINFO INFOactivetimes = { ACTIVETIMES, FALSE, "creation times", "Group creations in form \"name time who\"" }; STATIC LISTINFO INFOdistribs = { _PATH_NNRPDIST, FALSE, "newsgroup distributions", "Distributions in form \"area description\"" }; STATIC LISTINFO INFOsubs = { _PATH_NNRPSUBS, FALSE, "automatic group subscriptions", "Subscriptions in form \"group\"" }; STATIC LISTINFO INFOdistribpats = { _PATH_DISTPATS, FALSE, "distribution patterns", "Default distributions in form \"weight:pattern:value\"" }; STATIC LISTINFO INFOgroups = { NEWSGROUPS, FALSE, "newsgroup descriptions", "Descriptions in form \"group description\"" }; STATIC LISTINFO INFOmoderators = { _PATH_MODERATORS, FALSE, "moderator patterns", "Newsgroup moderators in form \"group-pattern:mail-address-pattern\"" }; STATIC LISTINFO INFOschema = { _PATH_SCHEMA, TRUE, "overview format", "Order of fields in overview database" }; /* returns: -1 for problem (such as no such authenticator etc.) 0 for authentication succeeded 1 for authentication failed */ static char *PERMauthstring; int PERMgeneric(av, accesslist) char *av[]; char *accesslist; { char path[BIG_BUFFER], *fields[6], *p; int i, pan[2], status; PID_T pid; struct stat stb; av += 2; if (!*av) { Reply("%d no authenticator\r\n", NNTP_SYNTAX_VAL); return(-1); } /* check for ../. I'd use strstr, but there doesn't appear to be any other references for it, and I don't want to break portability */ for (p = av[0]; *p; p++) if (EQn(p, "../", 3)) { Reply("%d ../ in authenticator %s\r\n", NNTP_SYNTAX_VAL, av[0]); return(-1); } (void)sprintf(path, "%s/%s", _PATH_AUTHDIR, av[0]); #if !defined(S_IXUSR) && defined(_S_IXUSR) #define S_IXUSR _S_IXUSR #endif /* !defined(S_IXUSR) && defined(_S_IXUSR) */ #if !defined(S_IXUSR) && defined(S_IEXEC) #define S_IXUSR S_IEXEC #endif /* !defined(S_IXUSR) && defined(S_IEXEC) */ if (stat(path, &stb) || !(stb.st_mode&S_IXUSR)) { Reply("%d No such authenticator %s\r\n", NNTP_TEMPERR_VAL, av[0]); return -1; } /* Create a pipe. */ if (pipe(pan) < 0) { syslog(L_FATAL, "cant pipe for %s %m", av[0]); return -1; } for (i = 0; (pid = FORK()) < 0; i++) { if (i == MAX_FORKS) { Reply("%d Can't fork %s\r\n", NNTP_TEMPERR_VAL, strerror(errno)); syslog(L_FATAL, "cant fork %s %m", av[0]); return -1; } syslog(L_NOTICE, "cant fork %s -- waiting", av[0]); (void)sleep(5); } /* Run the child, with redirection. */ if (pid == 0) { (void)close(STDERR); /* close existing stderr */ (void)close(pan[PIPE_READ]); /* stderr goes down the pipe. */ if (pan[PIPE_WRITE] != STDERR) { if ((i = dup2(pan[PIPE_WRITE], STDERR)) != STDERR) { syslog(L_FATAL, "cant dup2 %d to %d got %d %m", pan[PIPE_WRITE], STDERR, i); _exit(1); } (void)close(pan[PIPE_WRITE]); } CloseOnExec(STDIN, FALSE); CloseOnExec(STDOUT, FALSE); CloseOnExec(STDERR, FALSE); (void)execv(path, av); Reply("%s\r\n", NNTP_BAD_COMMAND); syslog(L_FATAL, "cant execv %s %m", path); _exit(1); } (void)close(pan[PIPE_WRITE]); i = read(pan[PIPE_READ], path, sizeof(path)); if ((p = strchr(path, '\n')) != NULL) *p = '\0'; if (PERMauthstring) free(PERMauthstring); PERMauthstring = malloc(strlen(path) + 1); if (PERMauthstring) strcpy(PERMauthstring, path); while( pid != waitnb(&status) ); /*syslog(L_NOTICE, "%s (%ld) returned: %d %s %d\n", av[0], (long) pid, i, path, status);*/ /* Split "host:permissions:user:pass:groups" into fields. */ for (fields[0] = path, i = 0, p = path; *p; p++) if (*p == ':') { *p = '\0'; fields[++i] = p + 1; } PERMcanread = strchr(fields[1], 'R') != NULL; PERMcanpost = strchr(fields[1], 'P') != NULL; sprintf(PERMuser, "%s@%s", fields[2], fields[0]); (void)strcpy(PERMpass, fields[3]); (void)strcpy(accesslist, fields[4]); /*(void)strcpy(writeaccess, fields[5]); future work? */ /*for (i = 0; fields[i] && i < 6; i++) printf("fields[%d] = %s\n", i, fields[i]);*/ return !status; } /* ARGSUSED */ FUNCTYPE CMDauthinfo(ac, av) int ac; char *av[]; { static char User[30]; static char Password[30]; char accesslist[BIG_BUFFER]; if (caseEQ(av[1], "generic")) { char *logrec = Glom(av); strcpy(PERMuser, ""); switch (PERMgeneric(av, accesslist)) { case 1: PERMspecified = NGgetlist(&PERMlist, accesslist); syslog(L_NOTICE, "%s auth %s (%s -> %s)", ClientHost, PERMuser, logrec, PERMauthstring? PERMauthstring: "" ); Reply("%d Authentication succeeded\r\n", NNTP_AUTH_OK_VAL); PERMneedauth = FALSE; PERMauthorized = TRUE; free(logrec); return; case 0: syslog(L_NOTICE, "%s bad_auth %s (%s)", ClientHost, PERMuser, logrec); Reply("%d Authentication failed\r\n", NNTP_ACCESS_VAL); free(logrec); ExitWithStats(1); default: /* lower level has issued Reply */ return; } } else { if (caseEQ(av[1], "user")) { (void)strncpy(User, av[2], sizeof User - 1); User[sizeof User - 1] = 0; Reply("%d PASS required\r\n", NNTP_AUTH_NEXT_VAL); return; } if (!caseEQ(av[1], "pass")) { Reply("%d bad authinfo param\r\n", NNTP_BAD_COMMAND_VAL); return; } if (User[0] == '\0') { Reply("%d USER required\r\n", NNTP_AUTH_REJECT_VAL); return; } (void)strncpy(Password, av[2], sizeof Password - 1); Password[sizeof Password - 1] = 0; if (EQ(User, PERMuser) && EQ(Password, PERMpass)) { syslog(L_NOTICE, "%s user %s", ClientHost, User); Reply("%d Ok\r\n", NNTP_AUTH_OK_VAL); PERMneedauth = FALSE; PERMauthorized = TRUE; return; } if (PERMinfile((char *)NULL, (char *)NULL, User, Password, accesslist)) { PERMspecified = NGgetlist(&PERMlist, accesslist); syslog(L_NOTICE, "%s user %s", ClientHost, User); Reply("%d Ok\r\n", NNTP_AUTH_OK_VAL); PERMneedauth = FALSE; PERMauthorized = TRUE; return; } syslog(L_NOTICE, "%s bad_auth", ClientHost); Reply("%d Authentication error\r\n", NNTP_ACCESS_VAL); ExitWithStats(1); } } /* ** The "DATE" command. Part of NNTPv2. */ /* ARGSUSED0 */ FUNCTYPE CMDdate(ac, av) int ac; char *av[]; { TIMEINFO t; struct tm *gmt; if (GetTimeInfo(&t) < 0 || (gmt = gmtime(&t.time)) == NULL) { Reply("%d Can't get time, %s\r\n", NNTP_TEMPERR_VAL, strerror(errno)); return; } Reply("%d %04.4d%02.2d%02.2d%02.2d%02.2d%02.2d\r\n", NNTP_DATE_FOLLOWS_VAL, gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday, gmt->tm_hour, gmt->tm_min, gmt->tm_sec); } /* ** List active newsgroups, newsgroup descriptions, and distributions. */ /* ARGSUSED0 */ FUNCTYPE CMDlist(ac, av) int ac; char *av[]; { register QIOSTATE *qp; register char *p; register char *save; char *grplist[2]; LISTINFO *lp; char *wildarg = NULL; char savec; p = av[1]; if (p == NULL || caseEQ(p, "active")) { static time_t last_time; time_t now; (void)time(&now); if (ac < 3 || now > last_time + NNRP_RESCAN_DELAY * 3) { if (last_time && !GetGroupList()) { syslog(L_NOTICE, "%s cant getgroupslist for list %m", ClientHost); Reply("%d Group update failed. Try later.\r\n", NNTP_TEMPERR_VAL); ExitWithStats(1); } last_time = now; } if (ac == 3) { GROUPENTRY *gp = GRPfind(av[2]); if (gp) { Reply("%d list:\r\n", NNTP_LIST_FOLLOWS_VAL); Printf("%s %ld %ld %c%s\r\n.\r\n", gp->Name, (long)gp->High, (long)gp->Low, gp->Flag, gp->Alias ? gp->Alias : ""); return; } wildarg = av[2]; } lp = &INFOactive; } else if (caseEQ(p, "active.times")) lp = &INFOactivetimes; else if (caseEQ(p, "distributions")) lp = &INFOdistribs; else if (caseEQ(p, "subscriptions")) lp = &INFOsubs; else if (caseEQ(p, "distrib.pats")) lp = &INFOdistribpats; else if (caseEQ(p, "moderators")) lp = &INFOmoderators; else if (caseEQ(p, "newsgroups")) { if (ac == 3) wildarg = av[2]; lp = &INFOgroups; } else if (caseEQ(p, "overview.fmt")) lp = &INFOschema; else { Reply("%s\r\n", NNTP_SYNTAX_USE); return; } if (ac > 2 && !wildarg) { Reply("%s\r\n", NNTP_SYNTAX_USE); return; } if ((qp = QIOopen(lp->File, QIO_BUFFER)) == NULL) { if (!lp->Required && errno == ENOENT) { Reply("%d %s.\r\n", NNTP_LIST_FOLLOWS_VAL, lp->Format); Printf(".\r\n"); } else { syslog(L_ERROR, "%s cant fopen %s %m", ClientHost, lp->File); Reply("%d No list of %s available.\r\n", NNTP_TEMPERR_VAL, lp->Items); } return; } Reply("%d %s.\r\n", NNTP_LIST_FOLLOWS_VAL, lp->Format); if (!PERMspecified && !PERMdefault) { /* Optmize for unlikely case of no permissions and FALSE default. */ (void)QIOclose(qp); Printf(".\r\n"); } /* Set up group list terminator. */ grplist[1] = NULL; /* Read lines, ignore long ones. */ while ((p = QIOread(qp)) != NULL) { if (lp == &INFOdistribs || lp == &INFOdistribpats || lp == &INFOsubs || lp == &INFOmoderators) { Printf("%s\r\n", p); continue; } if (lp == &INFOschema) { if (*p != '\0' && *p != '#') Printf("%s\r\n", p); continue; } savec = '\0'; for (save = p; *save != '\0'; save++) { if (*save == ' ' || *save == '\t') { savec = *save; *save = '\0'; break; } } if (PERMspecified) { grplist[0] = p; if (!PERMmatch(PERMdefault, PERMlist, grplist)) continue; } if (wildarg && !wildmat(p, wildarg)) continue; if (savec != '\0') *save = savec; Printf("%s\r\n", p); } QIOclose(qp); Printf(".\r\n"); } /* ** Handle the "mode" command. */ /* ARGSUSED */ FUNCTYPE CMDmode(ac, av) int ac; char *av[]; { if (caseEQ(av[1], "reader")) Reply("%d %s InterNetNews NNRP server %s ready (%s).\r\n", PERMcanpost ? NNTP_POSTOK_VAL : NNTP_NOPOSTOK_VAL, MyHostName, INNVersion(), PERMcanpost ? "posting ok" : "no posting"); else Reply("%d What?\r\n", NNTP_BAD_COMMAND_VAL); } /* ** Display new newsgroups since a given date and time for specified ** . */ FUNCTYPE CMDnewgroups(ac, av) int ac; char *av[]; { static char USAGE[] = "NEWGROUPS yymmdd hhmmss [\"GMT\"] []"; static char **distlist; register char *p; register char *q; register char **dp; register QIOSTATE *qp; register GROUPENTRY *gp; BOOL All; long date; char *grplist[2]; /* Parse the date. */ date = NNTPtoGMT(av[1], av[2]); if (date < 0) { Reply("%d Usage: %s\r\n", NNTP_SYNTAX_VAL, USAGE); return; } ac -= 3; av += 3; if (ac > 0 && caseEQ(*av, "GMT")) { av++; ac--; } else date = LOCALtoGMT(date); if (ac == 0) All = TRUE; else { if (!ParseDistlist(&distlist, *av)) { Reply("%d Bad distribution list %s:\r\n", NNTP_SYNTAX_VAL, *av); return; } All = FALSE; } if (!GetGroupList()) { syslog(L_NOTICE, "%s cant getgroupslist for list %m", ClientHost); Reply("%d Group update failed. Try later.\r\n", NNTP_TEMPERR_VAL); ExitWithStats(1); } if ((qp = QIOopen(ACTIVETIMES, QIO_BUFFER)) == NULL) { syslog(L_ERROR, "%s cant fopen %s %m", ClientHost, ACTIVETIMES); Reply("%d Cannot open newsgroup date file.\r\n", NNTP_TEMPERR_VAL); return; } Reply("%d New newsgroups follow.\r\n", NNTP_NEWGROUPS_FOLLOWS_VAL); /* Set up group list terminator. */ grplist[1] = NULL; /* Read the file, ignoring long lines. */ while ((p = QIOread(qp)) != NULL) { if ((q = strchr(p, ' ')) == NULL) continue; *q++ = '\0'; if (atol(q) < date || (gp = GRPfind(p)) == NULL) continue; if (PERMspecified) { grplist[0] = p; grplist[1] = NULL; if (!PERMmatch(PERMdefault, PERMlist, grplist)) continue; } else if (!PERMdefault) continue; if (!All) { if ((q = strchr(p, '.')) == NULL) continue; for (*q = '\0', dp = distlist; *dp; dp++) if (EQ(p, *dp)) { *q = '.'; break; } if (*dp == NULL) continue; } Printf("%s %ld %ld %c%s\r\n", p, (long)gp->High, (long)gp->Low, gp->Flag, gp->Alias ? gp->Alias : ""); } QIOclose(qp); Printf(".\r\n"); } /* ** Post an article. */ /* ARGSUSED */ FUNCTYPE CMDpost(ac, av) int ac; char *av[]; { static char *article; static int size; register char *p; register char *end; register int longline; register READTYPE r; int i; long l; STRING response; char idbuff[SMBUF]; if (!PERMcanpost) { syslog(L_NOTICE, "%s noperm post without permission", ClientHost); Reply("%s\r\n", NNTP_CANTPOST); return; } /* Start at beginning of buffer. */ if (article == NULL) { size = 4096; article = NEW(char, size); } p = article; end = &article[size]; Reply("%d Ok\r\n", NNTP_START_POST_VAL); (void)fflush(stdout); for (l = 0, longline = 0; ; l++) { /* Need more room? */ if (end - p < ART_LINE_MALLOC) { i = p - article; size += ART_LINE_MALLOC; RENEW(article, char, size); end = &article[size]; p = i + article; } /* Read line, process bad cases. */ switch (r = READline(p, ART_LINE_LENGTH, DEFAULT_TIMEOUT)) { default: syslog(L_ERROR, "%s internal %d in post", ClientHost, r); /* FALLTHROUGH */ case RTtimeout: syslog(L_ERROR, "%s timeout in post", ClientHost); Printf("%d timeout after %d seconds, closing connection\r\n", NNTP_TEMPERR_VAL, DEFAULT_TIMEOUT); ExitWithStats(1); /* NOTREACHED */ case RTeof: syslog(L_ERROR, "%s eof in post", ClientHost); ExitWithStats(1); /* NOTREACHED */ case RTlong: if (longline == 0) longline = l + 1; continue; case RTok: break; } /* Process normal text. */ if (*p != '.') { p += strlen(p); *p++ = '\n'; *p = '\0'; continue; } /* Got a leading period; see if it's the terminator. */ if (p[1] == '\0') { *p = '\0'; break; } /* "Arnold, please copy down over the period for me." */ while ((p[0] = p[1]) != '\0') p++; *p++ = '\n'; *p = '\0'; } if (longline) { syslog(L_NOTICE, "%s toolong in post", ClientHost); Printf("%d Line %d too long\r\n", NNTP_POSTFAIL_VAL, longline); POSTrejected++; return; } /* Send the article to the server. */ response = ARTpost(article, idbuff); if (response == NULL) { syslog(L_NOTICE, "%s post ok %s", ClientHost, idbuff); Reply("%s\r\n", NNTP_POSTEDOK); POSTreceived++; } else { if ((p = strchr(response, '\r')) != NULL) *p = '\0'; if ((p = strchr(response, '\n')) != NULL) *p = '\0'; syslog(L_NOTICE, "%s post failed %s", ClientHost, response); Reply("%d %s\r\n", NNTP_POSTFAIL_VAL, response); POSTrejected++; } } /* ** The "xpath" command. An uncommon extension. */ /* ARGSUSED */ FUNCTYPE CMDxpath(ac, av) int ac; char *av[]; { char *p; if ((p = HISgetent(av[1], TRUE)) == NULL) Reply("%d Don't have it\r\n", NNTP_DONTHAVEIT_VAL); else Reply("%d %s\r\n", NNTP_NOTHING_FOLLOWS_VAL, p); } inn-1.7.2/nnrpd/newnews.c0100644000175100001440000001421306443103542013603 0ustar mdusers/* $Revision: 1.16 $ ** ** The newnews command. */ #include #include #include "configdata.h" #include "clibrary.h" #include "nnrpd.h" #if defined(DONT_ALLOW_NEWNEWS) FUNCTYPE CMDnewnews(ac, av) register int ac; char *av[]; { Reply("%d NEWNEWS command disabled by administrator\r\n", NNTP_ACCESS_VAL); } #else #define FILE_LIST_DELTA 10 #define GET_DATE(p, line) \ ((p = strchr(line, HIS_FIELDSEP)) == NULL ? 0 : atol(++p)) /* ** Open an article and see if its distribution is in the list. */ STATIC BOOL DistMatches(distribs, files) char **distribs; char **files; { register char **dp; register QIOSTATE *qp; register char *p; register char *q; char buff[BIG_BUFFER]; char *save; /* Loop through the file list, trying to open one of them.. */ for (save = files[0]; *files; files++) { /* this next line makes me nervous--from unoff4... */ (void)sprintf(buff, "%s/%s/%s", _PATH_SPOOL, files[0], files[0] + strlen(files[0]) + 1); for (p = &buff[STRLEN(_PATH_SPOOL)]; *p; p++) if (*p == '.') *p = '/'; if ((qp = QIOopen(buff, QIO_BUFFER)) != NULL) break; } if (*files == NULL) { return FALSE; } /* Scan the article for the Distribution header. */ while ((p = QIOread(qp)) != NULL) { if (*p == '\n') /* End of headers. */ break; if (*p != 'd' && *p != 'D') continue; if ((q = strchr(p, '\n')) != NULL) *q = '\0'; if ((q = strchr(p, ':')) == NULL) continue; *q = '\0'; if (caseEQ(p, "distribution")) { for (q += 2, dp = distribs; *dp; dp++) if (caseEQ(q, *dp)) { QIOclose(qp); return TRUE; } break; } } QIOclose(qp); return FALSE; } /* ** Split file list into array of newsgroups. Return static pointer, ** or NULL if there are no filenames. */ STATIC char ** GetFiles(p) register char *p; { static int size; static char **list; register int i; register char *slash = p; if (size == 0) { size = FILE_LIST_DELTA; list = NEW(char*, size + 1); } for (i = 0 ; ; ) { while (ISWHITE(*p)) p++; if (*p == '\0' || *p == '\n') break; if (i >= size - 1) { size += FILE_LIST_DELTA; RENEW(list, char *, size + 1); } for (list[i] = p; *p && *p != '\n' && !ISWHITE(*p); p++) { if (*p == '/') *(slash = p) = '\0'; } if (*p) *p++ = '\0'; if (slash > list[i]) /* Only save filenames with '/' */ i++; } list[i] = NULL; return i ? list : NULL; } /* ** Seek to first line in the history file where the date is after the ** desired one. Returns FALSE on failure. */ STATIC BOOL FindLinesAfter(date, line, linesize, F) long date; char *line; int linesize; FILE *F; { char *p; long upper; long lower; long middle; /* Read first line -- is it in our range? */ (void)fseek(F, 0L, SEEK_SET); if (fgets(line, linesize, F) == NULL) return FALSE; if (GET_DATE(p, line) >= date) return TRUE; /* Set search ranges and go. */ lower = 0; (void)fseek(F, 0L, SEEK_END); upper = ftell(F); for ( ; ; ) { /* Seek to middle line. */ middle = (upper + lower) / 2; (void)fseek(F, middle, SEEK_SET); while (getc(F) != '\n' && ++middle <= upper) continue; if (middle >= upper) break; if (fgets(line, linesize, F) != NULL && GET_DATE(p, line) > date) upper = middle; else if (lower == middle) break; else lower = middle; } /* Move to lower bound; we know this will always be the start of a line. */ (void)fseek(F, lower, SEEK_SET); while (fgets(line, linesize, F) != NULL) if (GET_DATE(p, line) >= date) return TRUE; return FALSE; } /* ** NEWNEWS newsgroups date time ["GMT"] [] ** Return the Message-ID of any articles after the specified date, ** and within the specified distributions. */ FUNCTYPE CMDnewnews(ac, av) register int ac; char *av[]; { static char **groups; register char *start; register char *p; register FILE *F; register BOOL AllDists; register BOOL AllGroups; char **distribs; char **files; char line[BIG_BUFFER]; long date; if (!PERMcanread) { Reply("%s\r\n", NNTP_ACCESS); return; } (void)sprintf(line, "%s %s %s %s %s", av[1], av[2], av[3], (ac >= 5 && *av[4] == 'G') ? "GMT" : "local", (ac >= 5 && *av[ac - 1] == '<') ? av[ac - 1] : "none"); syslog(L_NOTICE, "%s newnews %s", ClientHost, line); /* Optimization in case client asks for !* (no groups) */ if (EQ(av[1], "!*")) { Reply("%s\r\n", NNTP_NEWNEWSOK); Printf(".\r\n"); return; } /* Parse the newsgroups. */ AllGroups = EQ(av[1], "*"); if (!AllGroups && !NGgetlist(&groups, av[1])) { Reply("%d Bad newsgroup specifier %s\r\n", NNTP_SYNTAX_VAL, av[1]); return; } /* Parse the date. */ date = NNTPtoGMT(av[2], av[3]); if (date < 0) { Reply("%d Bad date\r\n", NNTP_SYNTAX_VAL); return; } ac -= 4; av += 4; if (ac > 0 && caseEQ(*av, "GMT")) { ac--; av++; } else date = LOCALtoGMT(date); /* Parse the distributions. */ if (ac == 0) AllDists = TRUE; else { if (!ParseDistlist(&distribs, *av)) { Reply("%d Bad distribution %s\r\n", NNTP_SYNTAX_VAL, *av); return; } AllDists = FALSE; } if ((F = fopen(HISTORY, "r")) == NULL) { syslog(L_ERROR, "%s cant fopen %s %m", ClientHost, HISTORY); Reply("%d Can't open history\r\n", NNTP_TEMPERR_VAL); return; } Reply("%s\r\n", NNTP_NEWNEWSOK); files = NULL; if (FindLinesAfter(date, line, sizeof line, F)) do { /* Skip two tab-separated fields. */ if ((p = strchr(line, HIS_FIELDSEP)) == NULL || (start = strchr(p + 1, HIS_FIELDSEP)) == NULL) continue; /* Get the file list. */ if (*++start == '\n' || (files = GetFiles(start)) == NULL) continue; /* Check permissions. */ if (!AllGroups && !PERMmatch(FALSE, groups, files)) continue; if (!AllDists && !DistMatches(distribs, files)) continue; *p = '\0'; Printf("%s\r\n", line); } while (fgets(line, sizeof line, F) != NULL); (void)fclose(F); Printf(".\r\n"); } #endif /* defined(DONT_ALLOW_NEWNEWS) */ inn-1.7.2/nnrpd/article.c0100644000175100001440000006254406443103542013552 0ustar mdusers/* $Revision: 1.20 $ ** ** Article-related routines. */ #include #include #include "configdata.h" #include "clibrary.h" #include "nnrpd.h" /* ** Data structures for use in ARTICLE/HEAD/BODY/STAT common code. */ typedef enum _SENDTYPE { STarticle, SThead, STbody, STstat } SENDTYPE; typedef struct _SENDDATA { SENDTYPE Type; int ReplyCode; STRING Item; } SENDDATA; /* ** Information about the schema of the news overview files. */ typedef struct _ARTOVERFIELD { char *Header; int Length; BOOL HasHeader; BOOL NeedsHeader; } ARTOVERFIELD; STATIC char ARTnotingroup[] = NNTP_NOTINGROUP; STATIC char ARTnoartingroup[] = NNTP_NOARTINGRP; STATIC char ARTnocurrart[] = NNTP_NOCURRART; STATIC QIOSTATE *ARTqp; STATIC ARTOVERFIELD *ARTfields; STATIC int ARTfieldsize; STATIC int ARTfirstfullfield = 0; STATIC SENDDATA SENDbody = { STbody, NNTP_BODY_FOLLOWS_VAL, "body" }; STATIC SENDDATA SENDarticle = { STarticle, NNTP_ARTICLE_FOLLOWS_VAL, "article" }; STATIC SENDDATA SENDstat = { STstat, NNTP_NOTHING_FOLLOWS_VAL, "status" }; STATIC SENDDATA SENDhead = { SThead, NNTP_HEAD_FOLLOWS_VAL, "head" }; /* ** Overview state information. */ STATIC QIOSTATE *OVERqp; /* Open overview file */ STATIC char *OVERline; /* Current line */ STATIC ARTNUM OVERarticle; /* Current article */ STATIC int OVERopens; /* Number of opens done */ /* ** Read the overview schema. */ void ARTreadschema() { static char SCHEMA[] = _PATH_SCHEMA; register FILE *F; register char *p; register ARTOVERFIELD *fp; register int i; char buff[SMBUF]; /* Open file, count lines. */ if ((F = fopen(SCHEMA, "r")) == NULL) return; for (i = 0; fgets(buff, sizeof buff, F) != NULL; i++) continue; (void)fseek(F, (OFFSET_T)0, SEEK_SET); ARTfields = NEW(ARTOVERFIELD, i + 1); /* Parse each field. */ for (fp = ARTfields; fgets(buff, sizeof buff, F) != NULL; ) { /* Ignore blank and comment lines. */ if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; if ((p = strchr(buff, COMMENT_CHAR)) != NULL) *p = '\0'; if (buff[0] == '\0') continue; if ((p = strchr(buff, ':')) != NULL) { *p++ = '\0'; fp->NeedsHeader = EQ(p, "full"); if (ARTfirstfullfield == 0) ARTfirstfullfield = fp - ARTfields + 1; } else fp->NeedsHeader = FALSE; fp->HasHeader = FALSE; fp->Header = COPY(buff); fp->Length = strlen(buff); fp++; } ARTfieldsize = fp - ARTfields; (void)fclose(F); } /* ** If we have an article open, close it. */ void ARTclose() { if (ARTqp) { QIOclose(ARTqp); ARTqp = NULL; } } /* ** Get the Message-ID from a file. */ STATIC void ARTgetmsgid(qp, id) register QIOSTATE *qp; char *id; { register char *p; register char *q; for (*id = '\0'; (p = QIOread(qp)) != NULL && *p != '\0'; ) { if (*p != 'M' && *p != 'm') continue; if ((q = strchr(p, ' ')) == NULL) continue; *q++ = '\0'; if (caseEQ(p, "Message-ID:")) { (void)strcpy(id, q); break; } } (void)QIOrewind(qp); } /* ** If the article name is valid, open it and stuff in the ID. */ STATIC BOOL ARTopen(name, id) char *name; char *id; { static ARTNUM save_artnum; static char save_artid[BIG_BUFFER]; struct stat Sb; /* Re-use article if it's the same one. */ if (ARTqp != NULL) { if (save_artnum == atol(name) && QIOrewind(ARTqp) != -1) { if (id) (void)strcpy(id, save_artid); return TRUE; } QIOclose(ARTqp); } /* Open it, make sure it's a regular file. */ if ((ARTqp = QIOopen(name, QIO_BUFFER)) == NULL) return FALSE; if (fstat(QIOfileno(ARTqp), &Sb) < 0 || !S_ISREG(Sb.st_mode)) { QIOclose(ARTqp); ARTqp = NULL; return FALSE; } CloseOnExec(QIOfileno(ARTqp), TRUE); save_artnum = atol(name); ARTgetmsgid(ARTqp, save_artid); (void)strcpy(id, save_artid); return TRUE; } /* ** Open the article for a given Message-ID. */ STATIC QIOSTATE * ARTopenbyid(msg_id, ap) char *msg_id; ARTNUM *ap; { QIOSTATE *qp; char *p; char *q; *ap = 0; if ((p = HISgetent(msg_id, FALSE)) == NULL) return NULL; if ((qp = QIOopen(p, QIO_BUFFER)) == NULL) return NULL; CloseOnExec(QIOfileno(qp), TRUE); p += strlen(_PATH_SPOOL) + 1; if ((q = strrchr(p, '/')) != NULL) *q++ = '\0'; if (GRPlast[0] && EQ(p, GRPlast)) *ap = atol(q); return qp; } /* ** Send a (part of) a file to stdout, doing newline and dot conversion. */ STATIC void ARTsend(qp, what) register QIOSTATE *qp; SENDTYPE what; { register char *p; ARTcount++; GRParticles++; /* * it should never take 5 minutes to send an article line */ alarm(DEFAULT_TIMEOUT); /* Get the headers. */ for ( ; ; ) { p = QIOread(qp); if (p == NULL) { if (QIOtoolong(qp)) continue; break; } if (*p == '\0') break; if (what == STbody) continue; alarm(DEFAULT_TIMEOUT); /* restart timer */ Printf("%s%s\r\n", *p == '.' ? "." : "", p); } if (what == SThead) { Printf(".\r\n"); alarm(0); /* cancel timer */ return; } if (what == STarticle) Printf("\r\n"); for ( ; ; ) { p = QIOread(qp); if (p == NULL) { if (QIOtoolong(qp)) continue; break; } alarm(DEFAULT_TIMEOUT); /* restart timer */ Printf("%s%s\r\n", *p == '.' ? "." : "", p); } Printf(".\r\n"); alarm(0); /* cancel timer */ #if defined (DONT_LIKE_PULLERS) /* If the client has pulled in more than 100 articles, then there's a good chance it's a sucking feed. So we slow down a bit the feeding of articles after that point. */ { static int count ; if (what == STarticle) { if (++count > 100) { (void) fflush(stdout) ; sleep (1) ; /* slow down sucking readers */ } } } #endif } /* ** Find an article number in the article array via a binary search; ** return -1 if not found. Cache last hit to make linear lookups ** faster. */ STATIC int ARTfind(i) register ARTNUM i; { register ARTNUM *bottom; register ARTNUM *middle; register ARTNUM *top; if (ARTsize == 0) return -1; top = &ARTnumbers[ARTsize - 1]; if (ARTcache && ++ARTcache <= top && *ARTcache <= i) { if (*ARTcache == i) return ARTcache - ARTnumbers; bottom = ARTcache; } else { ARTcache = NULL; bottom = ARTnumbers; } for ( ; ; ) { if (i < *bottom || i > *top) break; middle = bottom + (top - bottom) / 2; if (i == *middle) { /* Found it; update cache. */ ARTcache = middle; return middle - ARTnumbers; } if (i > *middle) bottom = middle + 1; else top = middle; } return -1; } /* ** Ask the innd server for the article. Only called from CMDfetch, ** and only if history file is buffered. Common case: "oops, cancel ** that article I just posted." */ STATIC QIOSTATE * ARTfromboss(what, id) SENDDATA *what; char *id; { FILE *FromServer; FILE *ToServer; QIOSTATE *qp; char buff[NNTP_STRLEN + 2]; char *name; char *p; BOOL more; /* If we can, open the connection. */ if (NNTPlocalopen(&FromServer, &ToServer, (char *)NULL) < 0) return NULL; /* Send the query to the server. */ qp = NULL; (void)fprintf(ToServer, "XPATH %s\r\n", id); (void)fflush(ToServer); if (ferror(ToServer)) goto QuitClose; /* Get the reply; article exist? */ if (fgets(buff, sizeof buff, FromServer) == NULL || atoi(buff) != NNTP_NOTHING_FOLLOWS_VAL) goto QuitClose; /* Yes. Be quick if just doing a stat. */ if (what == &SENDstat) { qp = QIOopen("/dev/null", 0); goto QuitClose; } /* Clean up response. */ if ((p = strchr(buff, '\r')) != NULL) *p = '\0'; if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; /* Loop over all filenames until we can open one. */ for (name = buff; *name; name = p + 1) { /* Snip off next name, turn dots to slashes. */ for (p = name; ISWHITE(*p); p++) continue; for (name = p; *p && *p != ' '; p++) if (*p == '.') *p = '/'; more = *p == ' '; if (more) *p = '\0'; if ((qp = QIOopen(name, QIO_BUFFER)) != NULL || !more) break; } /* Send quit, read server's reply, close up and return. */ QuitClose: (void)fprintf(ToServer, "quit\r\n"); (void)fclose(ToServer); (void)fgets(buff, sizeof buff, FromServer); (void)fclose(FromServer); return qp; } /* ** Fetch part or all of an article and send it to the client. */ FUNCTYPE CMDfetch(ac, av) int ac; char *av[]; { char buff[SMBUF]; char idbuff[BIG_BUFFER]; SENDDATA *what; register QIOSTATE *qp; register BOOL ok; ARTNUM art; /* Find what to send; get permissions. */ ok = PERMcanread; switch (*av[0]) { default: what = &SENDbody; break; case 'a': case 'A': what = &SENDarticle; break; case 's': case 'S': what = &SENDstat; break; case 'h': case 'H': what = &SENDhead; /* Poster might do a "head" command to verify the article. */ ok = PERMcanread || PERMcanpost; break; } if (!ok) { Reply("%s\r\n", NOACCESS); return; } /* Requesting by Message-ID? */ if (ac == 2 && av[1][0] == '<') { if ((qp = ARTopenbyid(av[1], &art)) == NULL) { Reply("%d No such article\r\n", NNTP_DONTHAVEIT_VAL); return; } if (!PERMartok(qp)) { QIOclose(qp); Reply("%s\r\n", NOACCESS); return; } Reply("%d %ld %s %s\r\n", what->ReplyCode, art, av[1], what->Item); if (what->Type != STstat) ARTsend(qp, what->Type); QIOclose(qp); return; } /* Trying to read. */ if (GRPcount == 0) { Reply("%s\r\n", ARTnotingroup); return; } /* Default is to get current article, or specified article. */ if (ac == 1) { if (ARTindex < 0 || ARTindex >= ARTsize) { Reply("%s\r\n", ARTnocurrart); return; } (void)sprintf(buff, "%ld", ARTnumbers[ARTindex]); } else { if (strspn(av[1], "0123456789") != strlen(av[1])) { Reply("%s\r\n", ARTnoartingroup); return; } (void)strcpy(buff, av[1]); } /* Move forward until we can find one. */ while (!ARTopen(buff, idbuff)) { if (ac > 1 || ++ARTindex >= ARTsize) { Reply("%s\r\n", ARTnoartingroup); return; } (void)sprintf(buff, "%ld", ARTnumbers[ARTindex]); } /* fjc -- 1.5.1corr -- 19970806 If we cause Reply() more than 2048 bytes, it will overrun. idbuff is a message ID which came out of the history file. I really doubt it can be more than 255 bytes without some major history file corruption, but we'll force truncate it at 512 bytes. Note: Decent compilers will optimize out the following ?: */ idbuff[(BIG_BUFFER) > 512 ? 512 : (BIG_BUFFER-1)] = '\0'; Reply("%d %s %s %s\r\n", what->ReplyCode, buff, idbuff, what->Item); if (what->Type != STstat) ARTsend(ARTqp, what->Type); if (ac > 1) ARTindex = ARTfind((ARTNUM)atol(buff)); } /* ** Go to the next or last (really previous) article in the group. */ FUNCTYPE CMDnextlast(ac, av) int ac; char *av[]; { char buff[SPOOLNAMEBUFF]; char idbuff[SMBUF]; int save; BOOL next; int delta; int errcode; STRING message; if (!PERMcanread) { Reply("%s\r\n", NOACCESS); return; } if (GRPcount == 0) { Reply("%s\r\n", ARTnotingroup); return; } if (ARTindex < 0 || ARTindex >= ARTsize) { Reply("%s\r\n", ARTnocurrart); return; } next = (av[0][0] == 'n' || av[0][0] == 'N'); if (next) { delta = 1; errcode = NNTP_NONEXT_VAL; message = "next"; } else { delta = -1; errcode = NNTP_NOPREV_VAL; message = "previous"; } save = ARTindex; ARTindex += delta; if (ARTindex < 0 || ARTindex >= ARTsize) { Reply("%d No %s to retrieve.\r\n", errcode, message); ARTindex = save; return; } (void)sprintf(buff, "%ld", ARTnumbers[ARTindex]); while (!ARTopen(buff, idbuff)) { ARTindex += delta; if (ARTindex < 0 || ARTindex >= ARTsize) { Reply("%d No %s article to retrieve.\r\n", errcode, message); ARTindex = save; return; } (void)sprintf(buff, "%ld", ARTnumbers[ARTindex]); } Reply("%d %s %s Article retrieved; request text separately.\r\n", NNTP_NOTHING_FOLLOWS_VAL, buff, idbuff); if (ac > 1) ARTindex = ARTfind((ARTNUM)atol(buff)); } /* ** Return the header from the specified file, or NULL if not found. ** We can estimate the Lines header, if that's what's wanted. */ STATIC char * GetHeader(qp, header, IsLines) register QIOSTATE *qp; register char *header; BOOL IsLines; { static char buff[40]; register char *p; register char *q; struct stat Sb; for ( ; ; ) { if ((p = QIOread(qp)) == NULL) { if (QIOtoolong(qp)) continue; break; } if (*p == '\0') /* End of headers. */ break; if (ISWHITE(*p) || (q = strchr(p, ':')) == NULL) /* Continuation or bogus (shouldn't happen) line; ignore. */ continue; *q = '\0'; if (caseEQ(header, p)) return *++q ? q + 1 : NULL; } if (IsLines && fstat(QIOfileno(qp), &Sb) >= 0) { /* Lines estimation taken from Tor Lillqvist 's * posting in * news.sysadmin. */ (void)sprintf(buff, "%d", (int)(6.4e-8 * Sb.st_size * Sb.st_size + 0.023 * Sb.st_size - 12)); return buff; } return NULL; } STATIC BOOL CMDgetrange(ac, av, rp) int ac; char *av[]; register ARTRANGE *rp; { register char *p; if (GRPcount == 0) { Reply("%s\r\n", ARTnotingroup); return FALSE; } if (ac == 1) { /* No argument, do only current article. */ if (ARTindex < 0 || ARTindex >= ARTsize) { Reply("%s\r\n", ARTnocurrart); return FALSE; } rp->High = rp->Low = ARTnumbers[ARTindex]; return TRUE; } /* Got just a single number? */ if ((p = strchr(av[1], '-')) == NULL) { rp->Low = rp->High = atol(av[1]); return TRUE; } /* Parse range. */ *p++ = '\0'; rp->Low = atol(av[1]); if (ARTsize) { if (*p == '\0' || (rp->High = atol(p)) < rp->Low) /* "XHDR 234-0 header" gives everything to the end. */ rp->High = ARTnumbers[ARTsize - 1]; else if (rp->High > ARTnumbers[ARTsize - 1]) rp->High = ARTnumbers[ARTsize - 1]; if (rp->Low < ARTnumbers[0]) rp->Low = ARTnumbers[0]; } else /* No articles; make sure loops don't run. */ rp->High = rp->Low ? rp->Low - 1 : 0; return TRUE; } /* ** Return a field from the overview line or NULL on error. Return a copy ** since we might be re-using the line later. */ STATIC char * OVERGetHeader(p, field) register char *p; int field; { static char *buff; static int buffsize; register int i; ARTOVERFIELD *fp; char *next; fp = &ARTfields[field - 1]; if (fp->NeedsHeader) /* we're going to need an exact match */ field = ARTfirstfullfield; /* Skip leading headers. */ for (; --field >= 0 && *p; p++) if ((p = strchr(p, '\t')) == NULL) return NULL; if (*p == '\0') return NULL; if (fp->HasHeader) p += fp->Length + 2; if (fp->NeedsHeader) { /* find an exact match */ while (strncmp(fp->Header, p, fp->Length) != 0) { if ((p = strchr(p, '\t')) == NULL) return NULL; p++; } p += fp->Length + 2; } /* Figure out length; get space. */ if ((next = strchr(p, '\t')) != NULL) i = next - p; else i = strlen(p); if (buffsize == 0) { buffsize = i; buff = NEW(char, buffsize + 1); } else if (buffsize < i) { buffsize = i; RENEW(buff, char, buffsize + 1); } (void)strncpy(buff, p, i); buff[i] = '\0'; return buff; } /* ** Open an OVERVIEW file. */ STATIC BOOL OVERopen() { char name[SPOOLNAMEBUFF]; /* Already open? */ if (OVERqp != NULL) /* Don't rewind -- we are probably going forward via repeated * NNTP commands. */ return TRUE; /* Failed here before? */ if (OVERopens++) return FALSE; OVERline = NULL; OVERarticle = 0; (void)sprintf(name, "%s/%s/%s", _PATH_OVERVIEWDIR, GRPlast, _PATH_OVERVIEW); OVERqp = QIOopen(name, QIO_BUFFER); return OVERqp != NULL; } /* ** Close the OVERVIEW file. */ void OVERclose() { if (OVERqp != NULL) { QIOclose(OVERqp); OVERqp = NULL; OVERopens = 0; } } /* ** Return the overview data for an article or NULL on failure. ** Assumes that what we return is never modified. */ STATIC char * OVERfind(artnum) ARTNUM artnum; { if (OVERqp == NULL) return NULL; if (OVERarticle > artnum) { (void)QIOrewind(OVERqp); OVERarticle = 0; OVERline = NULL; } for ( ; OVERarticle < artnum; OVERarticle = atol(OVERline)) if ((OVERline = QIOread(OVERqp)) == NULL) { if (QIOtoolong(OVERqp)) continue; /* Don't close file; we may rewind. */ return NULL; } return OVERarticle == artnum ? OVERline : NULL; } /* ** Read an article and create an overview line without the trailing ** newline. Returns pointer to static space or NULL on error. */ STATIC char * OVERgen(name) char *name; { static ARTOVERFIELD *Headers; static char *buff; static int buffsize; register ARTOVERFIELD *fp; register ARTOVERFIELD *hp; register QIOSTATE *qp; register char *colon; register char *line; register char *p; register int i; register int size; register int ov_size; register long lines; struct stat Sb; long t; char value[10]; /* Open article. */ if ((qp = QIOopen(name, QIO_BUFFER)) == NULL) return NULL; if ((p = strrchr(name, '/')) != NULL) name = p + 1; /* Set up place to store headers. */ if (Headers == NULL) { Headers = NEW(ARTOVERFIELD, ARTfieldsize); for (fp = ARTfields, hp = Headers, i = ARTfieldsize; --i >= 0; hp++, fp++) { hp->Length = 0; hp->NeedsHeader = fp->NeedsHeader; } } for (hp = Headers, i = ARTfieldsize; --i >= 0; hp++) hp->HasHeader = FALSE; for ( ; ; ) { /* Read next line. */ if ((line = QIOread(qp)) == NULL) { if (QIOtoolong(qp)) continue; /* Error or EOF (in headers!?); shouldn't happen. */ QIOclose(qp); return NULL; } /* End of headers? */ if (*line == '\0') break; /* Is it a continuation line? */ if (ISWHITE(*line) && (hp - Headers) < ARTfieldsize) { /* Skip whitespace but one. */ for (p = line; *p && ISWHITE(*p); p++) continue; --p; /* Now append it. */ hp->Length += strlen(p); RENEW(hp->Header, char, hp->Length + 1); (void)strcat(hp->Header, p); for (p = hp->Header; *p; p++) if (*p == '\t' || *p == '\n') *p = ' '; continue; } /* See if we want this header. */ fp = ARTfields; for (hp = Headers, i = ARTfieldsize; --i >= 0; hp++, fp++) { colon = &line[fp->Length]; if (*colon != ':') continue; *colon = '\0'; if (!caseEQ(line, fp->Header)) { *colon = ':'; continue; } *colon = ':'; if (fp->NeedsHeader) p = line; else /* Skip colon and whitespace, store value. */ for (p = colon; *++p && ISWHITE(*p); ) continue; size = strlen(p); if (hp->Length == 0) { hp->Length = size; hp->Header = NEW(char, hp->Length + 1); } else if (hp->Length < size) { hp->Length = size; RENEW(hp->Header, char, hp->Length + 1); } (void)strcpy(hp->Header, p); for (p = hp->Header; *p; p++) if (*p == '\t' || *p == '\n') *p = ' '; hp->HasHeader = TRUE; break; } } /* Read body of article, just to get lines. */ for (lines = 0; ; lines++) if ((p = QIOread(qp)) == NULL) { if (QIOtoolong(qp)) continue; if (QIOerror(qp)) { QIOclose(qp); return NULL; } break; } /* Calculate total size, fix hardwired headers. */ ov_size = strlen(name) + ARTfieldsize + 2; for (hp = Headers, fp = ARTfields, i = ARTfieldsize; --i >= 0; hp++, fp++) { if (caseEQ(fp->Header, "Bytes") || caseEQ(fp->Header, "Lines")) { if (fp->Header[0] == 'B' || fp->Header[0] == 'b') t = fstat(QIOfileno(qp), &Sb) >= 0 ? (long)Sb.st_size : 0L; else t = lines; (void)sprintf(value, "%ld", t); size = strlen(value); if (hp->Length == 0) { hp->Length = size; hp->Header = NEW(char, hp->Length + 1); } else if (hp->Length < size) { hp->Length = size; RENEW(hp->Header, char, hp->Length + 1); } (void)strcpy(hp->Header, value); hp->HasHeader = TRUE; } if (hp->HasHeader) ov_size += strlen(hp->Header); } /* Get space. */ if (buffsize == 0) { buffsize = ov_size; buff = NEW(char, buffsize + 1); } else if (buffsize < ov_size) { buffsize = ov_size; RENEW(buff, char, buffsize + 1); } /* Glue all the fields together. */ p = buff + strlen(strcpy(buff, name)); for (hp = Headers, i = ARTfieldsize; --i >= 0; hp++) { if (hp->NeedsHeader && !hp->HasHeader) continue; *p++ = '\t'; if (hp->HasHeader) p += strlen(strcpy(p, hp->Header)); } *p = '\0'; QIOclose(qp); return buff; } /* ** XHDR, a common extension. Retrieve specified header from a ** Message-ID or article range. */ FUNCTYPE CMDxhdr(ac, av) int ac; char *av[]; { register QIOSTATE *qp; register ARTNUM i; register char *p; int Overview; BOOL IsLines; ARTRANGE range; char buff[SPOOLNAMEBUFF]; ARTNUM art; if (!PERMcanread) { Reply("%s\r\n", NOACCESS); return; } IsLines = caseEQ(av[1], "lines"); /* Message-ID specified? */ if (ac == 3 && av[2][0] == '<') { if ((qp = ARTopenbyid(av[2], &art)) == NULL) { Reply("%d No such article\r\n", NNTP_DONTHAVEIT_VAL); return; } Reply("%d %ld %s header of article %s.\r\n", NNTP_HEAD_FOLLOWS_VAL, art, av[1], av[2]); p = GetHeader(qp, av[1], IsLines); Printf("%s %s\r\n", av[2], p ? p : "(none)"); QIOclose(qp); Printf(".\r\n"); return; } /* Range specified. */ if (!CMDgetrange(ac - 1, av + 1, &range)) return; /* Is this a header in our overview? */ for (Overview = 0, i = 0; i < ARTfieldsize; i++) if (caseEQ(ARTfields[i].Header, av[1])) { if (OVERopen()) Overview = i + 1; break; } Reply("%d %s fields follow\r\n", NNTP_HEAD_FOLLOWS_VAL, av[1]); for (i = range.Low; i <= range.High; i++) { alarm(0); /* stop timer */ if (ARTfind(i) < 0) continue; /* * It should never take this long to send a single line * of overview information. */ alarm(DEFAULT_TIMEOUT); /* start timer */ /* Get it from the overview? */ if (Overview && (p = OVERfind(i)) != NULL) { p = OVERGetHeader(p, Overview); Printf("%ld %s\r\n", i, p && *p ? p : "(none)"); continue; } (void)sprintf(buff, "%ld", i); if ((qp = QIOopen(buff, QIO_BUFFER)) == NULL) continue; p = GetHeader(qp, av[1], IsLines); Printf("%ld %s\r\n", i, p ? p : "(none)"); QIOclose(qp); } Printf(".\r\n"); alarm (0) ; } /* ** XOVER another extension. Dump parts of the overview database. */ FUNCTYPE CMDxover(ac, av) int ac; char *av[]; { register char *p; register ARTNUM i; register BOOL Opened; ARTRANGE range; char buff[SPOOLNAMEBUFF]; if (!PERMcanread) { Printf("%s\r\n", NOACCESS); return; } /* Trying to read. */ if (GRPcount == 0) { Reply("%s\r\n", ARTnotingroup); return; } /* Parse range. */ if (!CMDgetrange(ac, av, &range)) return; Reply("%d data follows\r\n", NNTP_OVERVIEW_FOLLOWS_VAL); for (Opened = OVERopen(), i = range.Low; i <= range.High; i++) { if (ARTfind(i) < 0) continue; if (Opened && (p = OVERfind(i)) != NULL) { Printf("%s\r\n", p); continue; } (void)sprintf(buff, "%ld", i); if ((p = OVERgen(buff)) != NULL) Printf("%s\r\n", p); } Printf(".\r\n"); } /* ** XPAT, an uncommon extension. Print only headers that match the pattern. */ /* ARGSUSED */ FUNCTYPE CMDxpat(ac, av) int ac; char *av[]; { register char *p; register QIOSTATE *qp; register ARTNUM i; ARTRANGE range; char *header; char *pattern; char *text; int Overview; char buff[SPOOLNAMEBUFF]; ARTNUM art; if (!PERMcanread) { Printf("%s\r\n", NOACCESS); return; } header = av[1]; /* Message-ID specified? */ if (av[2][0] == '<') { p = av[2]; qp = ARTopenbyid(p, &art); if (qp == NULL) { Printf("%d No such article.\r\n", NNTP_DONTHAVEIT_VAL); return; } Printf("%d %s matches follow.\r\n", NNTP_HEAD_FOLLOWS_VAL, header); pattern = Glom(&av[3]); if ((text = GetHeader(qp, header, FALSE)) != NULL && wildmat(text, pattern)) Printf("%s %s\r\n", p, text); QIOclose(qp); Printf(".\r\n"); DISPOSE(pattern); return; } /* Range specified. */ if (!CMDgetrange(ac - 1, av + 1, &range)) return; /* In overview? */ for (Overview = 0, i = 0; i < ARTfieldsize; i++) if (caseEQ(ARTfields[i].Header, av[1])) { if (OVERopen()) Overview = i + 1; break; } Printf("%d %s matches follow.\r\n", NNTP_HEAD_FOLLOWS_VAL, header); for (pattern = Glom(&av[3]), i = range.Low; i <= range.High; i++) { if (ARTfind(i) < 0) continue; /* Get it from the Overview? */ if (Overview && (p = OVERfind(i)) != NULL && (p = OVERGetHeader(p, Overview)) != NULL) { if (wildmat(p, pattern)) Printf("%ld %s\r\n", i, p); continue; } (void)sprintf(buff, "%ld", i); if ((qp = QIOopen(buff, QIO_BUFFER)) == NULL) continue; if ((p = GetHeader(qp, av[1], FALSE)) == NULL) p = "(none)"; if (wildmat(p, pattern)) Printf("%ld %s\r\n", i, p); QIOclose(qp); } Printf(".\r\n"); DISPOSE(pattern); } inn-1.7.2/nnrpd/post.c0100644000175100001440000006076506443103542013117 0ustar mdusers/* $Revision: 1.32 $ ** ** Check article, send it to the local server. */ #include #include #include "configdata.h" #include "clibrary.h" #include "nnrpd.h" #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include "post.h" #define FLUSH_ERROR(F) (fflush((F)) == EOF || ferror((F))) #define HEADER_DELTA 20 STATIC char *tmpPtr ; STATIC char Error[SMBUF]; STATIC char NGSEPS[] = NG_SEPARATOR; STATIC char **OtherHeaders; STATIC int OtherCount; STATIC int OtherSize; STATIC BOOL WasMailed; STATIC STRING BadDistribs[] = { BAD_DISTRIBS }; HEADER Table[] = { /* Name Canset Type */ { "Path", TRUE, HTstd }, #define _path 0 { "From", TRUE, HTreq }, #define _from 1 { "Newsgroups", TRUE, HTreq }, #define _newsgroups 2 { "Subject", TRUE, HTreq }, #define _subject 3 { "Control", TRUE, HTstd }, #define _control 4 { "Supersedes", TRUE, HTstd }, #define _supersedes 5 { "Followup-To", TRUE, HTstd }, #define _followupto 6 { "Date", TRUE, HTstd }, #define _date 7 { "Organization", TRUE, HTstd }, #define _organization 8 { "Lines", TRUE, HTstd }, #define _lines 9 { "Sender", TRUE, HTstd }, #define _sender 10 { "Approved", TRUE, HTstd }, #define _approved 11 { "Distribution", TRUE, HTstd }, #define _distribution 12 { "Expires", TRUE, HTstd }, #define _expires 13 { "Message-ID", TRUE, HTstd }, #define _messageid 14 { "References", TRUE, HTstd }, #define _references 15 { "Reply-To", TRUE, HTstd }, #define _replyto 16 { "NNTP-Posting-Host", FALSE, HTstd }, #define _nntpposthost 17 { "Mime-Version", TRUE, HTstd }, #define _mimeversion 18 { "Content-Type", TRUE, HTstd }, #define _contenttype 19 { "Content-Transfer-Encoding", TRUE, HTstd }, #define _contenttransferencoding 20 { "Xref", FALSE, HTstd }, { "Summary", TRUE, HTstd }, { "Keywords", TRUE, HTstd }, { "Date-Received", FALSE, HTobs }, { "Received", FALSE, HTobs }, { "Posted", FALSE, HTobs }, { "Posting-Version", FALSE, HTobs }, { "Relay-Version", FALSE, HTobs }, }; HEADER *EndOfTable = ENDOF(Table); /* Join() and MaxLength() are taken from innd.c */ /* ** Turn any \r or \n in text into spaces. Used to splice back multi-line ** headers into a single line. */ STATIC char * Join(text) register char *text; { register char *p; for (p = text; *p; p++) if (*p == '\n' || *p == '\r') *p = ' '; return text; } /* ** Return a short name that won't overrun our bufer or syslog's buffer. ** q should either be p, or point into p where the "interesting" part is. */ char * MaxLength(p, q) char *p; char *q; { static char buff[80]; register int i; /* Already short enough? */ i = strlen(p); if (i < sizeof buff - 1) return Join(p); /* Simple case of just want the begining? */ if (q - p < sizeof buff - 4) { (void)strncpy(buff, p, sizeof buff - 4); (void)strcpy(&buff[sizeof buff - 4], "..."); } /* Is getting last 10 characters good enough? */ else if ((p + i) - q < 10) { (void)strncpy(buff, p, sizeof buff - 14); (void)strcpy(&buff[sizeof buff - 14], "..."); (void)strcpy(&buff[sizeof buff - 11], &p[i - 10]); } else { /* Not in last 10 bytes, so use double elipses. */ (void)strncpy(buff, p, sizeof buff - 17); (void)strcpy(&buff[sizeof buff - 17], "..."); (void)strncpy(&buff[sizeof buff - 14], &q[-5], 10); (void)strcpy(&buff[sizeof buff - 4], "..."); } return Join(buff); } /* ** Trim trailing spaces, return pointer to first non-space char. */ STATIC char * TrimSpaces(p) register char *p; { register char *start; for (start = p; ISWHITE(*start); start++) continue; for (p = start + strlen(start); p > start && CTYPE(isspace, p[-1]); ) *--p = '\0'; return start; } /* ** Mark the end of the header starting at p, and return a pointer ** to the start of the next one or NULL. Handles continuations. */ STATIC char * NextHeader(p) register char *p; { for ( ; (p = strchr(p, '\n')) != NULL; p++) { if (ISWHITE(p[1])) continue; *p = '\0'; return p + 1; } return NULL; } /* ** Strip any headers off the article and dump them into the table. ** On error, return NULL and fill in Error. */ STATIC char * StripOffHeaders(article) char *article; { register char *p; register char *q; register HEADER *hp; register char c; /* Scan through buffer, a header at a time. */ for (p = article; ; ) { /* See if it's a known header. */ c = CTYPE(islower, *p) ? toupper(*p) : *p; for (hp = Table; hp < ENDOF(Table); hp++) if (c == hp->Name[0] && p[hp->Size] == ':' && caseEQn(p, hp->Name, hp->Size)) { if (hp->Type == HTobs) { (void)sprintf(Error, "Obsolete \"%s\" header", hp->Name); return NULL; } if (hp->Value) { (void)sprintf(Error, "Duplicate \"%s\" header", hp->Name); return NULL; } for (q = &p[hp->Size + 1]; ISWHITE(*q); q++) continue; hp->Value = q; break; } /* No; add it to the set of other headers. */ if (hp == ENDOF(Table)) { if (OtherCount >= OtherSize - 1) { OtherSize += HEADER_DELTA; RENEW(OtherHeaders, char*, OtherSize); } OtherHeaders[OtherCount++] = p; } /* Get start of next header; if it's a blank line, we hit the end. */ if ((p = NextHeader(p)) == NULL) { (void)strcpy(Error, "Article has no body -- just headers"); return NULL; } if (*p == '\n') break; } return p + 1; } /* ** Check the control message, and see if it's legit. Return pointer to ** error message if not. */ STATIC STRING CheckControl(ctrl) char *ctrl; { register char *p; register char *q; char save; /* Snip off the first word. */ for (p = ctrl; ISWHITE(*p); p++) continue; for (ctrl = p; *p && !ISWHITE(*p); p++) continue; if (p == ctrl) return "Empty control message"; save = *p; *p = '\0'; if (EQ(ctrl, "cancel")) { for (q = p + 1; ISWHITE(*q); q++) continue; if (*q == '\0') return "Message-ID missing in cancel"; } else if (EQ(ctrl, "sendsys") || EQ(ctrl, "senduuname") || EQ(ctrl, "version") || EQ(ctrl, "checkgroups") || EQ(ctrl, "ihave") || EQ(ctrl, "sendme") || EQ(ctrl, "newgroup") || EQ(ctrl, "rmgroup")) /* SUPPRESS 530 *//* Empty body for statement */ ; else { (void)sprintf(Error, "\"%s\" is not a valid control message", MaxLength(ctrl,ctrl)); return Error; } *p = save; return NULL; } /* ** Check the Distribution header, and exit on error. */ STATIC STRING CheckDistribution(p) register char *p; { static char SEPS[] = " \t,"; register STRING *dp; if ((p = strtok(p, SEPS)) == NULL) return "Can't parse Distribution line."; do { for (dp = BadDistribs; *dp; dp++) if (wildmat(p, *dp)) { (void)sprintf(Error, "Illegal distribution \"%s\"", MaxLength(p,p)); return Error; } } while ((p = strtok((char *)NULL, SEPS)) != NULL); return NULL; } /* ** Process all the headers. FYI, they're done in RFC-order. ** Return NULL if okay, or an error message. */ STATIC STRING ProcessHeaders(linecount) int linecount; { static char MONTHS[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; static char datebuff[40]; static char orgbuff[SMBUF]; static char linebuff[40]; static char sendbuff[SMBUF]; static char mimeversion[SMBUF]; static char mimetype[SMBUF]; static char mimeencoding[SMBUF]; register HEADER *hp; register char *p; time_t t; struct tm *gmt; TIMEINFO Now; STRING error; /* Do some preliminary fix-ups. */ for (hp = Table; hp < ENDOF(Table); hp++) { if (!hp->CanSet && hp->Value) { (void)sprintf(Error, "Can't set system \"%s\" header", hp->Name); return Error; } if (hp->Value) { hp->Value = TrimSpaces(hp->Value); if (*hp->Value == '\0') hp->Value = NULL; } } #if defined(DO_NNRP_AUTH_SENDER) /* If authorized and we didn't get a sender, add the header based on * our info. If not authorized, zap the Sender so we don't put out * unauthenticated data. */ if (PERMauthorized && HDR(_sender) == NULL) { (void)sprintf(sendbuff, "%s@%s", PERMuser ? PERMuser : "UNKNOWN", ClientHost); HDR(_sender) = sendbuff; } else if (!PERMauthorized) HDR(_sender) = NULL; #endif /* defined(DO_NNRP_AUTH_SENDER) */ /* Set Date. */ if (GetTimeInfo(&Now) < 0) { (void)sprintf(Error, "Can't get the time, %s", strerror(errno)); return Error; } if (HDR(_date) == NULL) { if ((gmt = gmtime(&Now.time)) == NULL) return "Can't get the time"; (void)sprintf(datebuff, "%d %3.3s %d %02d:%02d:%02d GMT", gmt->tm_mday, &MONTHS[3 * gmt->tm_mon], 1900 + gmt->tm_year, gmt->tm_hour, gmt->tm_min, gmt->tm_sec); HDR(_date) = datebuff; } else { if ((t = parsedate(HDR(_date), &Now)) == -1) return "Can't parse \"Date\" header"; if (t > Now.time + DATE_FUZZ) return "Article posted in the future"; } /* Newsgroups are checked later. */ if (HDR(_control)) { if ((error = CheckControl(HDR(_control))) != NULL) return error; } else { p = HDR(_subject); if (p == NULL) return "Required \"Subject\" header is missing"; if (EQn(p, "cmsg ", 5)) { HDR(_control) = p + 5; if ((error = CheckControl(HDR(_control))) != NULL) return error; } #if 0 if (EQn(p, "Re: ", 4) && HDR(_references) == NULL) return "Article starts with \"Re: \" but has no references"; #endif /* 0 */ } /* Set Message-ID */ if (HDR(_messageid) == NULL) { if ((p = GenerateMessageID()) == NULL) { (void)sprintf(Error, "Can't generate Message-ID, %s", strerror(errno)); return Error; } HDR(_messageid) = p; } /* Set Path */ if (HDR(_path) == NULL) { /* Note that innd will put host name here for us. */ HDR(_path) = PATHMASTER; } else { #if 0 /* Here's where to do Path changes for new Posts. */ char *newpath; if ((newpath = strrchr(HDR(_path), '!')) != NULL) { newpath++; if (*newpath == '\0') { HDR(_path) = NEWSMASTER; } else { HDR(_path) = newpath; } } #endif } /* Reply-To; left alone. */ /* Sender; set above. */ /* Check Expires. */ if (HDR(_expires) && parsedate(HDR(_expires), &Now) == -1) return "Can't parse \"Expires\" header"; /* References; left alone. */ /* Control; checked above. */ /* Distribution. */ if ((p = HDR(_distribution)) != NULL) { p = COPY(p); error = CheckDistribution(p); DISPOSE(p); if (error != NULL) return error; } /* Set Organization */ if (HDR(_organization) == NULL && (p = GetConfigValue(_CONF_ORGANIZATION)) != NULL) { (void)strcpy(orgbuff, p); HDR(_organization) = orgbuff; } /* Keywords; left alone. */ /* Summary; left alone. */ /* Approved; left alone. */ /* MIME headers. */ if (HDR(_mimeversion) == NULL && (p = GetConfigValue(_CONF_MIMEVERSION)) != NULL) { (void)strcpy(mimeversion, p); HDR(_mimeversion) = mimeversion; /* Set Content-Type */ if (HDR(_contenttype) == NULL) { if ((p = GetConfigValue(_CONF_CONTENTTYPE)) == NULL) return "Can't get \"Content-Type\" header"; (void)strcpy(mimetype, p); HDR(_contenttype) = mimetype; } /* Set Content-Transfer-Encoding */ if (HDR(_contenttransferencoding) == NULL) { if ((p = GetConfigValue(_CONF_ENCODING)) == NULL) return "Can't get \"Content-Transfer-Encoding\" header"; (void)strcpy(mimeencoding, p); HDR(_contenttransferencoding) = mimeencoding; } } /* Set Lines */ (void)sprintf(linebuff, "%d", linecount); HDR(_lines) = linebuff; /* Supersedes; left alone. */ /* NNTP-Posting host; set. */ HDR(_nntpposthost) = ClientHost; /* Now make sure everything is there. */ for (hp = Table; hp < ENDOF(Table); hp++) if (hp->Type == HTreq && hp->Value == NULL) { (void)sprintf(Error, "Required \"%s\" header is missing", hp->Name); return Error; } return NULL; } #if defined(DO_CHECK_INCLUDED_TEXT) /* ** See if the user has more included text than new text. Simple-minded, but ** reasonably effective for catching neophyte's mistakes. A line starting ** with > is included text. Decrement the count on lines starting with < ** so that we don't reject diff(1) output. */ STATIC STRING CheckIncludedText(p, lines) register char *p; register int lines; { register int i; for (i = 0; ; p++) { switch (*p) { case '>': i++; break; case '|': i++; break; case ':': i++; break; case '<': i--; break; } if ((p = strchr(p + 1, '\n')) == NULL) break; } if ((i * 2 > lines) && (lines > 40)) return "Article not posted -- more included text than new text"; return NULL; } #endif /* defined(DO_CHECK_INCLUDED_TEXT) */ /* ** Try to mail an article to the moderator of the group. */ STATIC STRING MailArticle(group, article) char *group; char *article; { static char CANTSEND[] = "Can't send text to mailer"; register FILE *F; register HEADER *hp; register int i; char *address; char buff[SMBUF]; /* Try to get the address first. */ if ((address = GetModeratorAddress(NULL, NULL, group)) == NULL) { (void)sprintf(Error, "No mailing address for \"%s\" -- %s", group, "ask your news administrator to fix this"); return Error; } /* Now build up the command (ignore format/argument mismatch errors, * in case %s isn't in _PATH_SENDMAIL) and send the headers. */ (void)sprintf(buff, _PATH_SENDMAIL, address); if ((F = popen(buff, "w")) == NULL) return "Can't start mailer"; (void)fprintf(F, "To: %s\n", address); if (FLUSH_ERROR(F)) { (void)pclose(F); return CANTSEND; } /* Write the headers, a blank line, then the article. */ for (hp = Table; hp < ENDOF(Table); hp++) if (hp->Value) { (void)fprintf(F, "%s: %s\n", hp->Name, hp->Value); if (FLUSH_ERROR(F)) { (void)pclose(F); return CANTSEND; } } for (i = 0; i < OtherCount; i++) { (void)fprintf(F, "%s\n", OtherHeaders[i]); if (FLUSH_ERROR(F)) { (void)pclose(F); return CANTSEND; } } (void)fprintf(F, "\n"); i = strlen(article); if (fwrite((POINTER)article, (SIZE_T)1, (SIZE_T)i, F) != i) return "Can't send article"; if (FLUSH_ERROR(F)) { (void)pclose(F); return CANTSEND; } i = pclose(F); if (i) { (void)sprintf(Error, "Mailer exited with status %d -- %s", i, "Article might not have been mailed"); return Error; } WasMailed = TRUE; return NULL; } /* ** Check the newsgroups and make sure they're all valid, that none are ** moderated, etc. */ STATIC STRING ValidNewsgroups(hdr, article) char *hdr; char *article; { static char distbuff[SMBUF]; register char *groups; register char *p; register GROUPENTRY *gp; register BOOL approved; struct _DDHANDLE *h; char *grplist[2]; BOOL IsNewgroup; BOOL FoundOne; p = HDR(_control); IsNewgroup = p && EQn(p, "newgroup", 8); groups = COPY(hdr); if ((p = strtok(groups, NGSEPS)) == NULL) return "Can't parse newsgroups line"; /* Don't mail article if just checking Followup-To line. */ approved = HDR(_approved) != NULL || article == NULL; Error[0] = '\0'; FoundOne = FALSE; h = DDstart((FILE *)NULL, (FILE *)NULL); do { #if defined(DO_MERGE_TO_GROUPS) if (p[0] == 't' && p[1] == 'o' && p[2] == '.') p = "to"; #endif /* defined(DO_MERGE_TO_GROUPS) */ if ((gp = GRPfind(p)) == NULL) continue; FoundOne = TRUE; DDcheck(h, p); if (PERMspecified) { grplist[0] = p; grplist[1] = NULL; if (!PERMmatch(PERMdefault, PERMlist, grplist)) { sprintf(Error,"%s: %s\r\n", NNTP_NOSUCHGROUP,p); DISPOSE(groups); tmpPtr = DDend(h); DISPOSE(tmpPtr); return Error; } } switch (gp->Flag) { case NF_FLAG_OK: break; case NF_FLAG_MODERATED: if (!approved) { DISPOSE(groups); tmpPtr = DDend(h); DISPOSE(tmpPtr); return MailArticle(gp->Name, article); } break; case NF_FLAG_IGNORE: case NF_FLAG_NOLOCAL: (void)sprintf(Error, "Postings to \"%s\" are not allowed here.", gp->Name); break; case NF_FLAG_EXCLUDED: /* Do NOT return an error. */ break; case NF_FLAG_ALIAS: (void)sprintf(Error, "The newsgroup \"%s\" has been renamed to \"%s\".\n", p, gp->Alias); break; } } while ((p = strtok((char *)NULL, NGSEPS)) != NULL); DISPOSE(groups); if (!FoundOne && !IsNewgroup) (void)sprintf(Error, "No valid newsgroups in \"%s\"", MaxLength(hdr,hdr)); if (Error[0]) { tmpPtr = DDend(h); DISPOSE(tmpPtr) ; return Error; } p = DDend(h); if (HDR(_distribution) == NULL && *p) { (void)strcpy(distbuff, p); HDR(_distribution) = distbuff; } DISPOSE(p); return NULL; } /* ** Send a quit message to the server, eat its reply. */ STATIC void SendQuit(FromServer, ToServer) FILE *FromServer; FILE *ToServer; { char buff[NNTP_STRLEN]; (void)fprintf(ToServer, "quit\r\n"); (void)fflush(ToServer); (void)fclose(ToServer); (void)fgets(buff, sizeof buff, FromServer); (void)fclose(FromServer); } /* ** Offer the article to the server, return its reply. */ STATIC int OfferArticle(buff, buffsize, FromServer, ToServer) char *buff; int buffsize; FILE *FromServer; FILE *ToServer; { static char CANTSEND[] = "Can't send %s to server, %s"; (void)fprintf(ToServer, "ihave %s\r\n", HDR(_messageid)); if (FLUSH_ERROR(ToServer) || fgets(buff, buffsize, FromServer) == NULL) { (void)sprintf(buff, CANTSEND, "IHAVE", strerror(errno)); return -1; } return atoi(buff); } /* ** Spool article to temp file. */ STATIC STRING Spoolit(article, Error) char *article; char *Error; { static char CANTSPOOL[NNTP_STRLEN+2]; register HEADER *hp; register FILE *F = NULL; register int i; char temp[BUFSIZ]; char path[BUFSIZ]; struct stat Sb; /* Initialize the returned error message */ sprintf(CANTSPOOL, "%s and can't write text to local spool file", Error); /* Try to write it to the spool dir. */ TempName(_PATH_SPOOLNEWS, temp); /* rnews -U ignores files starting with . */ strrchr(temp, '/')[1] = '.'; if ((F = fopen(temp, "w")) == NULL) { syslog(L_FATAL, "cant open %s %m", temp); return CANTSPOOL; } fchmod(fileno(F), BATCHFILE_MODE); /* Write the headers and a blank line. */ for (hp = Table; hp < ENDOF(Table); hp++) if (hp->Value) { (void)fprintf(F, "%s: %s\n", hp->Name, hp->Value); if (FLUSH_ERROR(F)) { (void)fclose(F); return CANTSPOOL; } } for (i = 0; i < OtherCount; i++) { (void)fprintf(F, "%s\n", OtherHeaders[i]); if (FLUSH_ERROR(F)) { (void)fclose(F); return CANTSPOOL; } } (void)fprintf(F, "\n"); /* Write the article body */ i = strlen(article); if (fwrite((POINTER)article, (SIZE_T)1, (SIZE_T)i, F) != i) { fclose(F); return CANTSPOOL; } /* Flush and catch any errors */ if (fclose(F)) return CANTSPOOL; TempName(_PATH_SPOOLNEWS, path); if (rename(temp, path) < 0) { syslog(L_FATAL, "cant rename %s %s %m", temp, path); return CANTSPOOL; } /* Article has been spooled */ return NULL; } STRING ARTpost(article, idbuff) char *article; char *idbuff; { static char CANTSEND[] = "Can't send %s to server, %s"; register int i; register char *p; register char *next; register HEADER *hp; FILE *ToServer; FILE *FromServer; char buff[NNTP_STRLEN + 2], frombuf[SMBUF]; STRING error; /* Set up the other headers list. */ if (OtherHeaders == NULL) { OtherSize = HEADER_DELTA; OtherHeaders = NEW(char*, OtherSize); } /* Basic processing. */ OtherCount = 0; WasMailed = FALSE; for (hp = Table; hp < ENDOF(Table); hp++) { hp->Size = strlen(hp->Name); hp->Value = NULL; } if ((article = StripOffHeaders(article)) == NULL) return Error; for (i = 0, p = article; p; i++, p = next + 1) if ((next = strchr(p, '\n')) == NULL) break; #if defined(DO_CHECK_INCLUDED_TEXT) if ((error = CheckIncludedText(article, i)) != NULL) return error; #endif /* defined(DO_CHECK_INCLUDED_TEXT) */ if ((error = ProcessHeaders(i)) != NULL) return error; if (i == 0 && HDR(_control) == NULL) return "Article is empty"; if (idbuff != NULL) strcpy (idbuff,"(mailed to moderator)") ; if ((error = ValidNewsgroups(HDR(_newsgroups), article)) != NULL || WasMailed) return error; if (idbuff != NULL) idbuff [0] = '\0' ; strncpy(frombuf, HDR(_from), sizeof(frombuf) - 1); frombuf[sizeof(frombuf) - 1] = '\0'; HeaderCleanFrom(frombuf); p = strchr(frombuf, '@'); if (p) { strcpy(frombuf, p+1); p = strrchr(frombuf, '.'); if (!p) return "From: address not in Internet syntax"; } else return "From: address not in Internet syntax"; if ((p = HDR(_followupto)) != NULL && !EQ(p, "poster") && (error = ValidNewsgroups(p, (char *)NULL)) != NULL) return error; #if LOCAL_MAX_ARTSIZE > 0 if (strlen(article) > LOCAL_MAX_ARTSIZE) { (void)sprintf(Error, "Article is bigger then local limit of %ld bytes\n", LOCAL_MAX_ARTSIZE); return Error; } #endif /* LOCAL_MAX_ARTSIZE > 0 */ #if defined(DO_PERL) /* Calls the Perl subroutine for headers management */ if ((p = (char *)HandleHeaders()) != NULL) return p; #endif /* defined(DO_PERL) */ /* Open a local connection to the server. */ if (RemoteMaster) i = NNTPconnect(RemoteMaster, &FromServer, &ToServer, buff); else { #if defined(DO_HAVE_UNIX_DOMAIN) i = NNTPlocalopen(&FromServer, &ToServer, buff); #else i = NNTPremoteopen(&FromServer, &ToServer, buff); #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ } /* If we cannot open the connection, initialize the error message and * attempt to recover from this by spooling it locally */ if (i < 0) { if (buff[0]) (void)strcpy(Error, buff); else (void)sprintf(Error, CANTSEND, "connect request", strerror(errno)); return Spoolit(article,Error); } if (Tracing) syslog(L_TRACE, "%s post_connect %s", ClientHost, RemoteMaster ? RemoteMaster : "localhost"); /* The code below has too many (void) casts for my tastes. At least * they are all inside cases that are most likely never going to * happen -- for example, if the server crashes. */ /* Offer article to server. */ i = OfferArticle(buff, sizeof buff, FromServer, ToServer); if (i == NNTP_AUTH_NEEDED_VAL) { /* Send authorization. */ if (NNTPsendpassword(RemoteMaster, FromServer, ToServer) < 0) { (void)sprintf(Error, "Can't authorize with %s", RemoteMaster ? RemoteMaster : "innd"); return Spoolit(article,Error); } i = OfferArticle(buff, sizeof buff, FromServer, ToServer); } if (i != NNTP_SENDIT_VAL) { (void)strcpy(Error, buff); SendQuit(FromServer, ToServer); return (i != NNTP_HAVEIT_VAL ? Spoolit(article, Error) : Error) ; } if (Tracing) syslog(L_TRACE, "%s post starting", ClientHost); /* Write the headers and a blank line. */ for (hp = Table; hp < ENDOF(Table); hp++) if (hp->Value) (void)fprintf(ToServer, "%s: %s\r\n", hp->Name, hp->Value); for (i = 0; i < OtherCount; i++) (void)fprintf(ToServer, "%s\r\n", OtherHeaders[i]); (void)fprintf(ToServer, "\r\n"); if (FLUSH_ERROR(ToServer)) { (void)sprintf(Error, CANTSEND, "headers", strerror(errno)); (void)fclose(FromServer); (void)fclose(ToServer); return Spoolit(article, Error); } /* Send the article, get the server's reply. */ if (NNTPsendarticle(article, ToServer, TRUE) < 0 || fgets(buff, sizeof buff, FromServer) == NULL) { (void)sprintf(Error, CANTSEND, "article", strerror(errno)); (void)fclose(FromServer); (void)fclose(ToServer); return Spoolit(article, Error); } /* Did the server want the article? */ if ((i = atoi(buff)) != NNTP_TOOKIT_VAL) { (void)strcpy(Error, buff); SendQuit(FromServer, ToServer); return (i != NNTP_REJECTIT_VAL ? Spoolit(article, Error) : Error) ; } /* Send a quit and close down */ SendQuit(FromServer, ToServer); if (idbuff) { (void)strncpy(idbuff, HDR(_messageid), SMBUF - 1); idbuff[SMBUF - 1] = '\0'; } return NULL; } inn-1.7.2/nnrpd/perl.c0100644000175100001440000000346506443103542013066 0ustar mdusers/* -*- c -*- * * Author: Christophe Wolfhugel * (although he wouldn't recognise it anymore so don't blame him) * File: perl.c * RCSId: $Id: perl.c,v 1.5 1996/12/17 00:21:23 brister Exp $ * Description: Perl hooks for nnrpd. * */ #if ! defined (lint) static const char *rcsid = "$Id: perl.c,v 1.5 1996/12/17 00:21:23 brister Exp $" ; static void use_rcsid (const char *rid) { /* Never called */ use_rcsid (rcsid) ; use_rcsid (rid) ; } #endif #include #include #include "configdata.h" #include "clibrary.h" #include "paths.h" #include "post.h" #include "logging.h" #if defined(DO_PERL) #include #include extern BOOL PerlFilterActive; extern HEADER Table[], *EndOfTable; extern char LogName[]; char * HandleHeaders() { dSP; HEADER *hp; HV *hdr; int rc; char *p; static char buf[256]; if (!PerlFilterActive) return NULL; /* not really necessary */ ENTER ; SAVETMPS ; /* Create the Perl Hash */ hdr = perl_get_hv("hdr", TRUE); for (hp = Table; hp < EndOfTable; hp++) { if (hp->Value) hv_store(hdr, (char *) hp->Name, strlen(hp->Name), newSVpv(hp->Value, 0), 0); } rc = perl_call_argv("filter_post", G_EVAL|G_SCALAR, NULL); SPAGAIN; hv_undef (hdr); buf [0] = '\0' ; if (SvTRUE(GvSV(errgv))) /* check $@ */ { syslog (L_ERROR,"Perl function filter_post died: %s", SvPV(GvSV(errgv), na)) ; POPs ; PerlFilter (FALSE) ; } else if (rc == 1) { p = POPp; if (p != NULL && *p != '\0') { strncpy(buf, p, sizeof(buf) - 1); buf[sizeof(buf) - 1] = '\0'; } } FREETMPS ; LEAVE ; if (buf[0] != '\0') return buf ; return NULL; } #endif /* defined(DO_PERL) */ inn-1.7.2/nnrpd/loadave.c0100644000175100001440000000302706443103542013531 0ustar mdusers/* $Revision: 1.5 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include "nnrpd.h" #if NNRP_LOADLIMIT > 0 #ifdef linux /* ** Get the current load average as an integer. */ int GetLoadAverage() { FILE *ProcLoadAve; float load; if ((ProcLoadAve=fopen("/proc/loadavg", "r"))==NULL) return -1; if (fscanf(ProcLoadAve,"%f", &load)!=1) return -1; fclose(ProcLoadAve); return (int)(load+0.5); } #else #include STATIC struct nlist NameList[] = { { "_avenrun" }, #define X_AVENRUN 0 { NULL } }; /* ** Get the current load average as an integer. */ int GetLoadAverage() { int fd; int oerrno; #if defined(FSCALE) long avenrun[3]; #else double avenrun[3]; #endif /* defined(FSCALE) */ fd = open("/dev/kmem", 0, 0); if (fd < 0) return -1; #if defined(HPUX) (void)nlist("/hp-ux", NameList); #else #if defined(SUNOS5) (void)nlist("/dev/ksyms", NameList); #else (void)nlist("/vmunix", NameList); #endif /* defined(SUNOS5) */ #endif /* !defined(HPUX) */ if (NameList[0].n_type == 0 || lseek(fd, (OFFSET_T) NameList[X_AVENRUN].n_value, SEEK_SET) == -1 || read(fd, (char *)avenrun, sizeof avenrun) != sizeof avenrun) { oerrno = errno; (void)close(fd); errno = oerrno; return -1; } (void)close(fd); #if defined(FSCALE) return (int)(avenrun[0] + FSCALE / 2) >> FSHIFT; #else return (int)(avenrun[0] + 0.5); #endif /* defined(FSCALE) */ } #endif /* linux */ #endif /* NNRP_LOADLIMIT > 0 */ inn-1.7.2/nnrpd/nnrpd.h0100644000175100001440000000551506443103542013250 0ustar mdusers/* $Revision: 1.20 $ ** ** Net News Reading Protocol server. */ #include #include #include #include #if defined(VAR_VARARGS) #include #endif /* defined(VAR_VARARGS) */ #if defined(VAR_STDARGS) #include #endif /* defined(VAR_STDARGS) */ #include #include #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include "paths.h" #include "nntp.h" #include "logging.h" #include "libinn.h" #include "qio.h" #include "macros.h" /* ** Maximum input line length, sigh. */ #define ART_LINE_LENGTH 1000 #define ART_LINE_MALLOC 1024 /* ** Some convenient shorthands. */ typedef struct in_addr INADDR; #define Printf (void)printf #if defined(VAR_NONE) #define Reply (void)printf #endif /* defined(VAR_NONE) */ /* ** A group entry. */ typedef struct _GROUPENTRY { char *Name; ARTNUM High; ARTNUM Low; char Flag; char *Alias; } GROUPENTRY; /* ** A range of article numbers. */ typedef struct _ARTRANGE { int Low; int High; } ARTRANGE; /* ** What READline returns. */ typedef enum _READTYPE { RTeof, RTok, RTlong, RTtimeout } READTYPE; #if defined(MAINLINE) #define EXTERN /* NULL */ #else #define EXTERN extern #endif /* defined(MAINLINE) */ EXTERN BOOL PERMauthorized; EXTERN BOOL PERMcanpost; EXTERN BOOL PERMcanread; EXTERN BOOL PERMneedauth; EXTERN BOOL PERMspecified; EXTERN BOOL Tracing; EXTERN char **PERMlist; EXTERN STRING MyHostName; extern char ACTIVE[]; EXTERN char ClientHost[SMBUF]; EXTERN char LogName[256] ; extern char ACTIVETIMES[]; extern char HISTORY[]; extern char NEWSGROUPS[]; extern char NOACCESS[]; EXTERN char PERMpass[20]; EXTERN char PERMuser[20]; EXTERN char *RemoteMaster; EXTERN ARTNUM *ARTcache; EXTERN ARTNUM *ARTnumbers; EXTERN int ARTindex; EXTERN int ARTsize; extern int PERMdefault; EXTERN long ARTcount; EXTERN long GRParticles; EXTERN long GRPcount; EXTERN char GRPlast[SPOOLNAMEBUFF]; EXTERN long POSTreceived; EXTERN long POSTrejected; #if NNRP_LOADLIMIT > 0 extern int GetLoadAverage(); #endif /* NNRP_LOADLIMIT > 0 */ extern STRING ARTpost(); extern void ARTclose(); extern void ARTreadschema(); extern char *Glom(); extern int Argify(); extern NORETURN ExitWithStats(); extern BOOL GetGroupList(); extern void GRPreport(); extern GROUPENTRY *GRPfind(); extern char *HISgetent(); extern long LOCALtoGMT(); extern BOOL NGgetlist(); extern long NNTPtoGMT(); extern BOOL PERMartok(); extern BOOL PERMinfile(); extern BOOL PERMmatch(); extern BOOL ParseDistlist(); extern READTYPE READline(); extern void OVERclose(); #if defined(VAR_STDARGS) extern void Reply(char *, ...); #endif /* defined(VAR_STDARGS) */ #if defined(VAR_VARARGS) extern void Reply(); #endif /* defined(VAR_VARARGS) */ inn-1.7.2/nnrpd/group.c0100644000175100001440000002136206443103542013254 0ustar mdusers/* $Revision: 1.18 $ ** ** Newsgroups and the active file. */ #include #include #include "configdata.h" #include "clibrary.h" #include "nnrpd.h" #include "mydir.h" /* ** Newsgroup hashing stuff. See comments in innd/ng.c. */ #define GRP_HASH(Name, p, j) \ for (p = Name, j = 0; *p; ) j = (j << 5) + j + *p++ #define GRP_SIZE 512 #define GRP_BUCKET(j) &GRPtable[j & (GRP_SIZE - 1)] typedef struct _GRPHASH { int Size; int Used; GROUPENTRY **Groups; } GRPHASH; STATIC GRPHASH GRPtable[GRP_SIZE]; STATIC GROUPENTRY *GRPentries; STATIC int GRPbuckets; STATIC int GRPsize; /* ** See if a given newsgroup exists. */ GROUPENTRY * GRPfind(group) register char *group; { register char *p; register unsigned int j; register int i; register GROUPENTRY **gpp; GRPHASH *htp; char c; /* SUPPRESS 6 *//* Over/underflow from plus expression */ GRP_HASH(group, p, j); htp = GRP_BUCKET(j); for (c = *group, gpp = htp->Groups, i = htp->Used; --i >= 0; gpp++) if (c == gpp[0]->Name[0] && EQ(group, gpp[0]->Name)) return gpp[0]; return NULL; } STATIC void GRPhash() { register char *p; register int i; register GROUPENTRY *gp; register unsigned int j; register GRPHASH *htp; /* Set up the default hash buckets. */ GRPbuckets = GRPsize / GRP_SIZE; if (GRPbuckets == 0) GRPbuckets = 1; if (GRPtable[0].Groups) for (i = GRP_SIZE, htp = GRPtable; --i >= 0; htp++) htp->Used = 0; else for (i = GRP_SIZE, htp = GRPtable; --i >= 0; htp++) { htp->Size = GRPbuckets; htp->Groups = NEW(GROUPENTRY*, htp->Size); htp->Used = 0; } /* Now put all groups into the hash table. */ for (i = GRPsize, gp = GRPentries; --i >= 0; gp++) { /* SUPPRESS 6 *//* Over/underflow from plus expression */ GRP_HASH(gp->Name, p, j); htp = GRP_BUCKET(j); if (htp->Used >= htp->Size) { htp->Size += GRPbuckets; RENEW(htp->Groups, GROUPENTRY*, htp->Size); } htp->Groups[htp->Used++] = gp; } /* Note that we don't sort the buckets. */ } /* ** Read the active file into memory, sort it, and set the number of ** newsgroups read in. Return TRUE if okay, FALSE on error. */ BOOL GetGroupList() { static char *active; register char *p; register char *q; register GROUPENTRY *gp; register int i; /* If re-scanning, free previous groups. */ if (active != NULL) { DISPOSE(active); DISPOSE(GRPentries); } /* Get the new file. */ active = ReadInFile(ACTIVE, (struct stat *)NULL); if (active == NULL) { syslog(L_ERROR, "%s cant read %s %m", ClientHost, ACTIVE); return FALSE; } /* Count lines. */ for (p = active, i = 0; (p = strchr(p, '\n')) != NULL; p++, i++) continue; /* Fill in the group array. */ GRPentries = NEW(GROUPENTRY, i); for (i = 0, gp = GRPentries, p = active; *p; i++, gp++, p = q + 1) { gp->Name = p; if ((p = strchr(p, ' ')) == NULL) { syslog(L_ERROR, "%s internal no_space1 \"%.20s...\"", ClientHost, gp->Name); return FALSE; } *p++ = '\0'; /* Get the high mark. */ if ((q = strchr(p, ' ')) == NULL) { syslog(L_ERROR, "%s internal no_space2 \"%.20s...\"", ClientHost, gp->Name); return FALSE; } *q++ = '\0'; gp->High = atol(p); /* Get the low mark. */ if ((p = strchr(q, ' ')) == NULL) { syslog(L_ERROR, "%s internal no_space3 \"%.20s...\"", ClientHost, gp->Name); return FALSE; } *p++ = '\0'; gp->Low = atol(q); /* Kill the newline. */ if ((q = strchr(p, '\n')) == NULL) { syslog(L_ERROR, "%s internal newline \"%.20s...\"", ClientHost, gp->Name); return FALSE; } *q = '\0'; gp->Flag = *p; gp->Alias = gp->Flag == NF_FLAG_ALIAS ? p + 1 : NULL; } GRPsize = i; GRPhash(); return TRUE; } /* ** Sorting predicate to put newsgroup names into numeric order. */ STATIC int ARTcompare(p1, p2) CPOINTER p1; CPOINTER p2; { ARTNUM *i1; ARTNUM *i2; i1 = CAST(ARTNUM*, p1); i2 = CAST(ARTNUM*, p2); return *i1 - *i2; } /* ** Fill in ARTnumbers with the numbers of the articles in the current ** group. */ STATIC void GRPscandir(dir) char *dir; { static char SPOOL[] = _PATH_SPOOL; static int ARTarraysize; register DIRENTRY *ep; register DIR *dp; register char *p; register ARTNUM i; /* Go to the directory. */ if (chdir(SPOOL) < 0) { syslog(L_FATAL, "%s cant cd %s %m", ClientHost, SPOOL); ExitWithStats(1); } if (ARTarraysize == 0) { ARTarraysize = 1024; ARTnumbers = NEW(ARTNUM, ARTarraysize); } /* The newsgroup directory might not exist; treat it as empty. */ ARTsize = 0; GRPcount++; if (chdir(dir) < 0) return; dp = opendir("."); if (dp == NULL) { syslog(L_ERROR, "%s cant opendir %s %m", ClientHost, dir); return; } while ((ep = readdir(dp)) != NULL) { /* Get the numeric value of the filename, if it's all digits. */ for (p = ep->d_name, i = 0; *p; p++) { if (!CTYPE(isdigit, *p)) break; i = i * 10 + *p - '0'; } if (*p || i == 0) continue; if (ARTsize + 1 >= ARTarraysize) { ARTarraysize += 1024; RENEW(ARTnumbers, ARTNUM, ARTarraysize); } ARTnumbers[ARTsize++] = i; } (void)closedir(dp); ARTcache = NULL; qsort((POINTER)ARTnumbers, (SIZE_T)ARTsize, sizeof ARTnumbers[0], ARTcompare); } /* ** Change to or list the specified newsgroup. If invalid, stay in the old ** group. */ FUNCTYPE CMDgroup(ac, av) int ac; char *av[]; { static time_t last_time; static char NOSUCHGROUP[] = NNTP_NOSUCHGROUP; register char *p; register int i; time_t now; char *grplist[2]; char *group; char buff[SPOOLNAMEBUFF]; if (!PERMcanread) { Reply("%s\r\n", NOACCESS); return; } /* Parse arguments. */ if (ac == 1) { if (GRPcount == 0) { Printf("%d No group specified\r\n", NNTP_XGTITLE_BAD); return; } (void)strcpy(buff, GRPlast); for (p = buff; *p; p++) if (*p == '/') *p = '.'; group = buff; } else group = av[1]; if (GRPfind(group) == NULL) { Reply("%s %s\r\n", NOSUCHGROUP,group); return; } /* If permission is denied, pretend group doesn't exist. */ if (PERMspecified) { grplist[0] = group; grplist[1] = NULL; if (!PERMmatch(PERMdefault, PERMlist, grplist)) { Reply("%s\r\n", NOSUCHGROUP); return; } } else if (!PERMdefault) { Reply("%s\r\n", NOSUCHGROUP); return; } /* Close out any existing article, report group stats. */ ARTclose(); ARTindex = 0; GRPreport(); /* Make the group name a directory name. */ (void)strcpy(buff, group); for (p = buff; *p; p++) if (*p == '.') *p = '/'; /* If we haven't been in the group recently, rescan. */ (void)time(&now); if (!EQ(buff, GRPlast) || now > last_time + NNRP_RESCAN_DELAY) { GRPscandir(buff); (void)strcpy(GRPlast, buff); last_time = now; } /* Close down any overview file. */ OVERclose(); /* Doing a "group" command? */ if (caseEQ(av[0], "group")) { if (ARTsize == 0) Reply("%d 0 0 0 %s\r\n", NNTP_GROUPOK_VAL, group); else Reply("%d %d %ld %ld %s\r\n", NNTP_GROUPOK_VAL, ARTsize, ARTnumbers[0], ARTnumbers[ARTsize - 1], group); } else { /* Must be doing a "listgroup" command. */ Reply("%d Article list follows\r\n", NNTP_GROUPOK_VAL); for (i = 0; i < ARTsize; i++) Printf("%ld\r\n", ARTnumbers[i]); Printf(".\r\n"); } } /* ** Report on the number of articles read in the group, and clear the count. */ void GRPreport() { register char *p; char buff[SPOOLNAMEBUFF]; if (GRPlast[0] && GRParticles != 0) { (void)strcpy(buff, GRPlast); for (p = buff; *p; p++) if (*p == '/') *p = '.'; syslog(L_NOTICE, "%s group %s %ld", ClientHost, buff, GRParticles); GRParticles = 0; } } /* ** Used by ANU-News clients. */ FUNCTYPE CMDxgtitle(ac, av) int ac; char *av[]; { register QIOSTATE *qp; register char *line; register char *p; register char *q; char save; /* Parse the arguments. */ if (ac == 1) { if (GRPcount == 0) { Printf("%d No group specified\r\n", NNTP_XGTITLE_BAD); return; } p = GRPlast; } else p = av[1]; /* Open the file, get ready to scan. */ if ((qp = QIOopen(NEWSGROUPS, QIO_BUFFER)) == NULL) { syslog(L_ERROR, "%s cant open %s %m", ClientHost, NEWSGROUPS); Printf("%d Can't open %s\r\n", NNTP_XGTITLE_BAD, NEWSGROUPS); return; } Printf("%d list follows\r\n", NNTP_XGTITLE_OK); /* Print all lines with matching newsgroup name. */ while ((line = QIOread(qp)) != NULL) { for (q = line; *q && !ISWHITE(*q); q++) continue; save = *q; *q = '\0'; if (wildmat(line, p)) { *q = save; Printf("%s\r\n", line); } } /* Done. */ QIOclose(qp); Printf(".\r\n"); } inn-1.7.2/nnrpd/Makefile0100644000175100001440000001222606443103542013413 0ustar mdusers## $Revision: 1.22 $ SHELL = /bin/sh MAKE = make DESTDIR = D = $(DESTDIR) ## =()

@>()= P = ## =()@>()= CC = gcc ## =()@>()= PERLLIB = ## =()@>()= PERLINC = ## =()@ $(PERLINC)>()= DEFS = -I../include $(PERLINC) ## =()@>()= CFLAGS = $(DEFS) -g ## =()@>()= LDFLAGS = ## =()@>()= LINTFLAGS = -b -h -z $(DEFS) ## =()@>()= LINTFILTER = | sed -n -f ../sedf.sun ## =()@>()= CTAGS = ctags -t -w ## =()@>()= PROF = -pg ## =()@>()= NNRPD = /usr/news/bin/nnrpd ## =()@ -G @@>()= OWNER = -O news -G news ## =()@>()= LIBS = -lutil LIBNEWS = ../libinn.a LINTLIB = ../llib-linn.ln SOURCES = \ article.c group.c commands.c misc.c newnews.c nnrpd.c \ perl.c post.c loadave.c OBJECTS = \ article.o group.o commands.o misc.o newnews.o nnrpd.o \ perl.o post.o loadave.o ALL = nnrpd all: $(ALL) install: $D$(NNRPD) ## Low-level install actions. $D$(NNRPD): nnrpd $(SHELL) ../installit.sh $(OWNER) -m 0555 -b .OLD $? $@ clobber clean: rm -f *.o $(ALL) rm -f nnrpd nnrpdp profiled rm -f all install lint tags ctags: $(SOURCES) $(CTAGS) $(SOURCES) ../lib/*.c nnrpd.h ../include/*.h nnrpd: $(P) $(OBJECTS) $(LIBNEWS) @rm -f $@ $(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBNEWS) $(LIBS) $(PERLLIB) lint: $(ALL) @rm -f lint -lint $(LINTFLAGS) $(SOURCES) $(LINTLIB) $(LINTFILTER) >lint ../include/dbz.h: (cd ../lib ; $(MAKE) ../include/dbz.h) $(LIBNEWS) $(LINTLIB): (cd ../lib ; $(MAKE) install ) ## Profiling. The rules are a bit brute-force, but good enough. profiled: nnrpdp date >$@ nnrpdp: $(SOURCES) rm -f $(OBJECTS) $(MAKE) nnrpd CFLAGS="$(CFLAGS) $(PROF)" LIBNEWS=../libinn_p.a mv nnrpd nnrpdp rm -f $(OBJECTS) ccenter: $(SOURCES) #load $(CFLAGS) $(SOURCES) $(LIBNEWS) ## Dependencies. Default list, below, is probably good enough. depend: Makefile $(SOURCES) makedepend $(DEFS) $(SOURCES) # DO NOT DELETE THIS LINE -- make depend depends on it. article.o: ../include/clibrary.h article.o: ../include/configdata.h article.o: ../include/configdata.h article.o: ../include/libinn.h article.o: ../include/libinn.h article.o: ../include/logging.h article.o: ../include/macros.h article.o: ../include/nntp.h article.o: ../include/paths.h article.o: ../include/paths.h article.o: ../include/qio.h article.o: nnrpd.h commands.o: ../include/clibrary.h commands.o: ../include/configdata.h commands.o: ../include/configdata.h commands.o: ../include/libinn.h commands.o: ../include/libinn.h commands.o: ../include/logging.h commands.o: ../include/macros.h commands.o: ../include/nntp.h commands.o: ../include/paths.h commands.o: ../include/paths.h commands.o: ../include/qio.h commands.o: nnrpd.h group.o: ../include/clibrary.h group.o: ../include/configdata.h group.o: ../include/configdata.h group.o: ../include/libinn.h group.o: ../include/libinn.h group.o: ../include/logging.h group.o: ../include/macros.h group.o: ../include/mydir.h group.o: ../include/mydir.h group.o: ../include/nntp.h group.o: ../include/paths.h group.o: ../include/paths.h group.o: ../include/qio.h group.o: nnrpd.h loadave.o: ../include/clibrary.h loadave.o: ../include/configdata.h loadave.o: ../include/configdata.h loadave.o: ../include/libinn.h loadave.o: ../include/libinn.h loadave.o: ../include/logging.h loadave.o: ../include/macros.h loadave.o: ../include/nntp.h loadave.o: ../include/paths.h loadave.o: ../include/paths.h loadave.o: ../include/qio.h loadave.o: nnrpd.h misc.o: ../include/clibrary.h misc.o: ../include/configdata.h misc.o: ../include/configdata.h misc.o: ../include/dbz.h misc.o: ../include/dbz.h misc.o: ../include/libinn.h misc.o: ../include/libinn.h misc.o: ../include/logging.h misc.o: ../include/macros.h misc.o: ../include/nntp.h misc.o: ../include/paths.h misc.o: ../include/paths.h misc.o: ../include/qio.h misc.o: nnrpd.h newnews.o: ../include/clibrary.h newnews.o: ../include/configdata.h newnews.o: ../include/configdata.h newnews.o: ../include/libinn.h newnews.o: ../include/libinn.h newnews.o: ../include/logging.h newnews.o: ../include/macros.h newnews.o: ../include/nntp.h newnews.o: ../include/paths.h newnews.o: ../include/paths.h newnews.o: ../include/qio.h newnews.o: nnrpd.h nnrpd.o: ../include/clibrary.h nnrpd.o: ../include/configdata.h nnrpd.o: ../include/configdata.h nnrpd.o: ../include/libinn.h nnrpd.o: ../include/libinn.h nnrpd.o: ../include/logging.h nnrpd.o: ../include/macros.h nnrpd.o: ../include/nntp.h nnrpd.o: ../include/paths.h nnrpd.o: ../include/paths.h nnrpd.o: ../include/qio.h nnrpd.o: nnrpd.h perl.o: ../include/clibrary.h perl.o: ../include/configdata.h perl.o: ../include/configdata.h perl.o: ../include/logging.h perl.o: ../include/paths.h perl.o: post.h perl.o: post.h post.o: ../include/clibrary.h post.o: ../include/configdata.h post.o: ../include/configdata.h post.o: ../include/libinn.h post.o: ../include/libinn.h post.o: ../include/logging.h post.o: ../include/macros.h post.o: ../include/nntp.h post.o: ../include/paths.h post.o: ../include/paths.h post.o: ../include/qio.h post.o: nnrpd.h post.o: post.h inn-1.7.2/nnrpd/nnrpd.c0100644000175100001440000004451406443103542013245 0ustar mdusers/* $Revision: 1.32 $ ** ** NNTP server for readers (NNRP) for InterNetNews. ** This server doesn't do any real load-limiting, except for what has ** proven empirically necesary (i.e., look at GRPscandir). */ #include #include #include "configdata.h" #include "clibrary.h" #define MAINLINE #include "nnrpd.h" #include #include #if defined(HPUX) #include #endif /* defined(HPUX) */ /* ** Here is some defensive code to protect the news server from hosts, ** mostly PC's, that sometimes make a connection and then never give ** any commands. The connection is abandoned, but we're never told ** about it. The first time the connection is read, it will have a ** timeout value of INITIAL_TIMEOUT seconds. All subsequent reads ** will have the standard timeout of CLIENT_TIMEOUT seconds. */ #if !defined(INITIAL_TIMEOUT) #define INITIAL_TIMEOUT 10 #endif #define CMDany -1 typedef struct _CMDENT { STRING Name; FUNCPTR Function; BOOL Needauth; int Minac; int Maxac; STRING Help; } CMDENT; char NOACCESS[] = NNTP_ACCESS; char ACTIVE[] = _PATH_ACTIVE; char ACTIVETIMES[] = _PATH_ACTIVETIMES; char HISTORY[] = _PATH_HISTORY; char NEWSGROUPS[] = _PATH_NEWSGROUPS; /* Default permission -- change with adb. */ BOOL PERMdefault = FALSE; STATIC double STATstart; STATIC double STATfinish; STATIC char *PushedBack; #if !defined(HPUX) STATIC char *TITLEstart; STATIC char *TITLEend; #endif /* !defined(HPUX) */ STATIC SIGVAR ChangeTrace; extern FUNCTYPE CMDauthinfo(); extern FUNCTYPE CMDdate(); extern FUNCTYPE CMDfetch(); extern FUNCTYPE CMDgroup(); STATIC FUNCTYPE CMDhelp(); extern FUNCTYPE CMDlist(); extern FUNCTYPE CMDmode(); extern FUNCTYPE CMDnewgroups(); extern FUNCTYPE CMDnewnews(); extern FUNCTYPE CMDnextlast(); extern FUNCTYPE CMDpost(); extern FUNCTYPE CMDxgtitle(); extern FUNCTYPE CMDxhdr(); extern FUNCTYPE CMDxover(); extern FUNCTYPE CMDxpat(); extern FUNCTYPE CMDxpath(); extern FUNCTYPE CMD_unimp(); STATIC char CMDfetchhelp[] = "[MessageID|Number]"; STATIC CMDENT CMDtable[] = { { "authinfo", CMDauthinfo, FALSE, 3, CMDany, "user Name|pass Password|generic " }, { "article", CMDfetch, TRUE, 1, 2, CMDfetchhelp }, { "body", CMDfetch, TRUE, 1, 2, CMDfetchhelp }, { "date", CMDdate, FALSE, 1, 1, NULL }, { "group", CMDgroup, TRUE, 2, 2, "newsgroup" }, { "head", CMDfetch, TRUE, 1, 2, CMDfetchhelp }, { "help", CMDhelp, FALSE, 1, CMDany, NULL }, { "ihave", CMD_unimp, TRUE, 1, 2, NULL }, { "last", CMDnextlast, TRUE, 1, 1, NULL }, { "list", CMDlist, TRUE, 1, 3, "[active|active.times|newsgroups|distributions|distrib.pats|overview.fmt|subscriptions]" }, { "listgroup", CMDgroup, TRUE, 1, 2, "newsgroup" }, { "mode", CMDmode, FALSE, 2, 2, "reader" }, { "newgroups", CMDnewgroups, TRUE, 3, 5, "yymmdd hhmmss [\"GMT\"] []" }, { "newnews", CMDnewnews, TRUE, 4, 6, "newsgroups yymmdd hhmmss [\"GMT\"] []" }, { "next", CMDnextlast, TRUE, 1, 1, NULL }, { "post", CMDpost, TRUE, 1, 1, NULL }, { "slave", CMD_unimp, FALSE, 1, 1, NULL }, { "stat", CMDfetch, TRUE, 1, 2, CMDfetchhelp }, { "xgtitle", CMDxgtitle, TRUE, 1, 2, "[group_pattern]" }, { "xhdr", CMDxhdr, TRUE, 2, 3, "header [range|MessageID]" }, { "xover", CMDxover, TRUE, 1, 2, "[range]" }, { "xpat", CMDxpat, TRUE, 4, CMDany, "header range|MessageID pat [morepat...]" }, { "xpath", CMDxpath, TRUE, 2, 2, "MessageID" }, { NULL } }; /* ** Log a summary status message and exit. */ NORETURN ExitWithStats(x) int x; { TIMEINFO Now; double usertime; double systime; (void)fflush(stdout); (void)GetTimeInfo(&Now); STATfinish = TIMEINFOasDOUBLE(Now); if (GetResourceUsage(&usertime, &systime) < 0) { usertime = 0; systime = 0; } GRPreport(); syslog(L_NOTICE, "%s exit articles %ld groups %ld", ClientHost, ARTcount, GRPcount); if (POSTreceived || POSTrejected) syslog(L_NOTICE, "%s posts received %ld rejected %ld", ClientHost, POSTreceived, POSTrejected); syslog(L_NOTICE, "%s times user %.3f system %.3f elapsed %.3f", ClientHost, usertime, systime, STATfinish - STATstart); exit(x); } /* ** The "help" command. */ /* ARGSUSED0 */ STATIC FUNCTYPE CMDhelp(ac, av) int ac; char *av[]; { CMDENT *cp; Reply("%s\r\n", NNTP_HELP_FOLLOWS); for (cp = CMDtable; cp->Name; cp++) if (cp->Help == NULL) Printf(" %s\r\n", cp->Name); else Printf(" %s %s\r\n", cp->Name, cp->Help); Printf("Report problems to <%s@%s>\r\n", NEWSMASTER, GetConfigValue(_CONF_FROMHOST)); Reply(".\r\n"); } /* ** Unimplemented catch-all. */ /* ARGSUSED0 */ FUNCTYPE CMD_unimp(ac, av) int ac; char *av[]; { if (caseEQ(av[0], "ihave")) Reply("%d Transfer permission denied\r\n", NNTP_AUTH_NEEDED_VAL); else if (caseEQ(av[0], "slave")) /* Somebody sends us this? I don't believe it! */ Reply("%d Unsupported\r\n", NNTP_SLAVEOK_VAL); else Reply("%d %s not implemented; try help\r\n", NNTP_BAD_COMMAND_VAL, av[0]); } /* ** Overwrite the original argv so that ps will show what's going on. */ STATIC void TITLEset(what) char *what; { #if defined(DO_HAVE_SETPROCTITLE) setproctitle("%s %s", ClientHost, what); #else #if !defined(HPUX) register char *p; register int i; char buff[BUFSIZ]; /* Make ps think we're swapped out so we get "(nnrpd)" in the output. */ p = TITLEstart; *p++ = '-'; (void)sprintf(buff, "%s %s", ClientHost, what); i = strlen(buff); if (i > TITLEend - p - 2) { i = TITLEend - p - 2; buff[i] = '\0'; } (void)strcpy(p, buff); for (p += i; p < TITLEend; ) *p++ = ' '; #else char buff[BUFSIZ]; union pstun un; (void)sprintf(buff, "(nnrpd) %s %s", ClientHost, what); (void)pstat(PSTAT_SETCMD, un, strlen(buff), 0, 0); #endif /* defined(HPUX) */ #endif /* defined(DO_HAVE_SETPROCTITLE) */ } #if defined(DO_NNRP_GETHOSTBYADDR) /* ** Convert an IP address to a hostname. Don't trust the reverse lookup, ** since anyone can fake .in-addr.arpa entries. */ STATIC BOOL Address2Name(ap, hostname, i) register INADDR *ap; register char *hostname; register int i; { register char *p; register struct hostent *hp; #if defined(h_addr) register char **pp; #endif /* Get the official hostname, store it away. */ if ((hp = gethostbyaddr((char *)ap, sizeof *ap, AF_INET)) == NULL) return FALSE; (void)strncpy(hostname, hp->h_name, i); hostname[i - 1] = '\0'; /* Get addresses for this host. */ if ((hp = gethostbyname(hostname)) == NULL) return FALSE; /* Make sure one of those addresses is the address we got. */ #if defined(h_addr) /* We have many addresses */ for (pp = hp->h_addr_list; *pp; pp++) if (memcmp((POINTER)&ap->s_addr, (POINTER)*pp, (SIZE_T)hp->h_length) == 0) break; if (*pp == NULL) return FALSE; #else /* We have one address. */ if (memcmp((POINTER)&ap->s_addr, (POINTER)hp->h_addr, (SIZE_T)hp->h_length) != 0) return FALSE; #endif /* Only needed for misconfigured YP/NIS systems. */ if (strchr(hostname, '.') == NULL && (p = GetConfigValue(_CONF_DOMAIN)) != NULL) { (void)strcat(hostname, "."); (void)strcat(hostname, p); } /* Make all lowercase, for wildmat. */ for (p = hostname; *p; p++) if (CTYPE(isupper, *p)) *p = tolower(*p); return TRUE; } #endif /* defined(DO_NNRP_GETHOSTBYADDR) */ BOOL PERMinfile(hp, ip, user, pass, accesslist) char *hp; char *ip; char *user; char *pass; char *accesslist; { static char ACCESS[] = _PATH_NNRPACCESS; register FILE *F; register char *p; register BOOL found; register int i; struct passwd *pwd; char buff[BIG_BUFFER]; char *fields[5]; if ((F = fopen(ACCESS, "r")) == NULL) { syslog(L_ERROR, "%s cant fopen %s %m", ClientHost, ACCESS); return FALSE; } PERMcanread = FALSE; PERMcanpost = FALSE; found = FALSE; accesslist[0] = '\0'; while (fgets(buff, sizeof buff, F) != NULL) { if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; if ((p = strchr(buff, COMMENT_CHAR)) != NULL) *p = '\0'; if (buff[0] == '\0') continue; /* Split "host:permissions:user:pass:groups" into fields. */ for (fields[0] = buff, i = 0, p = buff; *p; p++) if (*p == ':') { *p = '\0'; fields[++i] = p + 1; } if (i != 4) /* Malformed line. */ continue; if (hp) /* Got an address; try to match either the IP address or as * a text hostname. */ if (!(ip && wildmat(ip, fields[0])) && !wildmat(hp, fields[0])) continue; /* See if we should lookup a specific user in the passwd file */ if (user && pass && EQ(fields[2], "+")) { if ((pwd = getpwnam(user)) == NULL) continue; if (!EQ(pwd->pw_passwd, crypt(pass, pwd->pw_passwd))) continue; } /* Matching for a specific user or just the host? */ else if (user && (!EQ(user, fields[2]) || !EQ(pass, fields[3]))) continue; PERMcanread = strchr(fields[1], 'R') != NULL; PERMcanpost = strchr(fields[1], 'P') != NULL; (void)strcpy(PERMuser, user ? user : fields[2]); (void)strcpy(PERMpass, pass ? pass : fields[3]); (void)strcpy(accesslist, fields[4]); found = TRUE; } (void)fclose(F); return found; } /* ** Determine access rights of the client. */ STATIC void StartConnection(accesslist) char *accesslist; { struct sockaddr_in sin; int length; char buff[SMBUF]; char *ClientAddr; /* Get the peer's name. */ length = sizeof sin; ClientAddr = NULL; if (getpeername(STDIN, (struct sockaddr *)&sin, &length) < 0) { if (!isatty(STDIN)) { syslog(L_ERROR, "%s cant getpeername %m", "?"); (void)strcpy(ClientHost, "?"); /* so stats generation looks correct. */ Printf("%d I can't get your name. Goodbye.\r\n", NNTP_ACCESS_VAL); ExitWithStats(1); } (void)strcpy(ClientHost, "stdin"); } #if defined(AF_DECnet) else if (sin.sin_family == AF_DECnet) { char *p, *MyDECnetDomain; (void) strcpy(ClientHost, getenv("REMNODE")); for (p = ClientHost; *p; p++) if (CTYPE(isupper, *p)) *p = tolower(*p); #define _CONF_DECNETDOMAIN "decnetdomain" if ((MyDECnetDomain = GetConfigValue(_CONF_DECNETDOMAIN)) != NULL) { (void)strcat(ClientHost, "."); (void)strcat(ClientHost, MyDECnetDomain); } } #endif else { if (sin.sin_family != AF_INET) { syslog(L_ERROR, "%s bad_address_family %ld", "?", (long)sin.sin_family); Printf("%d Bad address family. Goodbye.\r\n", NNTP_ACCESS_VAL); ExitWithStats(1); } /* Get client's name. */ #if defined(DO_NNRP_GETHOSTBYADDR) if (!Address2Name(&sin.sin_addr, ClientHost, sizeof ClientHost)) { (void)strcpy(ClientHost, inet_ntoa(sin.sin_addr)); syslog(L_NOTICE, "? cant gethostbyaddr %s %m -- using IP address for access", ClientHost); } else { ClientAddr = buff; (void)strcpy(buff, inet_ntoa(sin.sin_addr)); } #else (void)strcpy(ClientHost, inet_ntoa(sin.sin_addr)); #endif /* defined(DO_NNRP_GETHOSTBYADDR) */ } strncpy (LogName,ClientHost,sizeof(LogName) - 1) ; LogName[sizeof(LogName) - 1] = '\0'; syslog(L_NOTICE, "%s connect", ClientHost); if (!PERMinfile(ClientHost, ClientAddr, (char *)NULL, (char *)NULL, accesslist)) { syslog(L_NOTICE, "%s no_access", ClientHost); Printf("%d You are not in my access file. Goodbye.\r\n", NNTP_ACCESS_VAL); ExitWithStats(1); } } #if !defined(VAR_NONE) #if defined(VAR_VARARGS) #if defined(lint) #define START_VARARG(fmt, vp, type) va_start(vp); fmt = NULL #else #define START_VARARG(fmt, vp, type) va_start(vp); fmt = va_arg(vp, type) #endif /* defined(lint) */ #endif /* defined(VAR_VARARGS) */ #if defined(VAR_STDARGS) #define START_VARARG(fmt, vp, type) va_start(vp, fmt) #endif /* defined(VAR_STDARGS) */ /* ** Send a reply, possibly with debugging output. */ /*VARARGS*/ void #if defined(VAR_VARARGS) Reply(va_alist) va_dcl #endif /* defined(VAR_VARARGS) */ #if defined(VAR_STDARGS) Reply(char *fmt, ...) #endif /* defined(VAR_STDARGS) */ { register int oerrno; register char *p; va_list vp; char buff[2048]; #if defined(VAR_VARARGS) register char *fmt; #endif /* defined(VAR_VARARGS) */ START_VARARG(fmt, vp, char*); (void)vprintf(fmt, vp); va_end(vp); if (Tracing) { oerrno = errno; START_VARARG(fmt, vp, char*); /* Copy output, but strip trailing CR-LF. */ (void)vsprintf(buff, fmt, vp); p = buff + strlen(buff) - 1; while (p >= buff && (*p == '\n' || *p == '\r')) *p-- = '\0'; syslog(LOG_DEBUG, "%s > %s", ClientHost, buff); va_end(vp); errno = oerrno; } } #endif /* !defined(VAR_NONE) */ /* ** Got a signal; toggle tracing. */ STATIC SIGHANDLER ToggleTrace(s) int s; { ChangeTrace = TRUE; (void)signal(s, ToggleTrace); } /* ** Print a usage message and exit. */ STATIC void Usage() { (void)fprintf(stderr, "Usage error.\n"); exit(1); } /* ARGSUSED0 */ int main(argc, argv, env) int argc; char *argv[]; char *env[]; { #if NNRP_LOADLIMIT > 0 int load; #endif /* NNRP_LOADLIMIT > 0 */ CMDENT *cp; char buff[NNTP_STRLEN]; char **av; int ac; READTYPE r; TIMEINFO Now; register int i; char *Reject; char accesslist[BIG_BUFFER]; int timeout; #if !defined(HPUX) /* Save start and extent of argv for TITLEset. */ TITLEstart = argv[0]; TITLEend = argv[argc - 1] + strlen(argv[argc - 1]) - 1; #endif /* !defined(HPUX) */ /* Parse arguments. Must COPY() optarg if used because the * TITLEset() routine would clobber it! */ Reject = NULL; while ((i = getopt(argc, argv, "S:r:s:t")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'i': /* Initial command */ PushedBack = COPY(optarg); break; case 'S': /* We're a slave to NNTP master */ RemoteMaster = COPY(optarg); break; case 's': /* Unused title string */ break; case 't': /* Tracing */ Tracing = TRUE; break; case 'r': /* Reject connection message */ Reject = COPY(optarg); break; } argc -= optind; if (argc) Usage(); /* Setup. */ openlog("nnrpd", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG); if (GetTimeInfo(&Now) < 0) { syslog(L_FATAL, "cant gettimeinfo %m"); exit(1); } STATstart = TIMEINFOasDOUBLE(Now); if ((MyHostName = GetConfigValue(_CONF_PATHHOST)) == NULL) { syslog(L_FATAL, "cant getconfigvalue %m"); ExitWithStats(1); } MyHostName = COPY(MyHostName); #if NNRP_LOADLIMIT > 0 if ((load = GetLoadAverage()) > NNRP_LOADLIMIT) { syslog(L_NOTICE, "load %d > %d", load, NNRP_LOADLIMIT); Reply("%d load at %d, try later\r\n", NNTP_GOODBYE_VAL, load); ExitWithStats(1); } #endif /* NNRP_LOADLIMIT > 0 */ strcpy (LogName,"?") ; /* Ignore SIGPIPE, since we'll see closed connections with read. */ (void)signal(SIGPIPE, SIG_IGN); /* Arrange to toggle tracing. */ (void)signal(SIGHUP, ToggleTrace); /* Get permissions and see if we can talk to this client */ StartConnection(accesslist); if (!PERMcanread && !PERMcanpost) { syslog(L_NOTICE, "%s no_permission", ClientHost); Printf("%d You have no permission to talk. Goodbye.\r\n", NNTP_ACCESS_VAL); ExitWithStats(1); } /* Proceed with initialization. */ PERMneedauth = PERMuser[0] != '\0' && PERMpass[0] != '\0'; PERMspecified = NGgetlist(&PERMlist, accesslist); TITLEset("connect"); /* Were we told to reject connections? */ if (Reject) { syslog(L_NOTICE, "%s rejected %s", ClientHost, Reject); Reply("%s %s\r\n", NNTP_GOODBYE, Reject); ExitWithStats(0); } ARTreadschema(); if (!GetGroupList()) { /* This shouldn't really happen. */ syslog(L_NOTICE, "%s cant getgrouplist %m", ClientHost); Reply("%d NNTP server unavailable. Try later.\r\n", NNTP_TEMPERR_VAL); ExitWithStats(1); } #if defined(DO_PERL) /* Load the Perl code */ PERLsetup(NULL, _PATH_PERL_FILTER_NNRPD, "filter_post"); PerlFilter (TRUE) ; #endif /* defined(DO_PERL) */ Reply("%d %s InterNetNews NNRP server %s ready (%s).\r\n", PERMcanpost ? NNTP_POSTOK_VAL : NNTP_NOPOSTOK_VAL, MyHostName, INNVersion(), PERMcanpost ? "posting ok" : "no posting"); /* Main dispatch loop. */ for (timeout = INITIAL_TIMEOUT, av = NULL; ; timeout = CLIENT_TIMEOUT) { (void)fflush(stdout); if (ChangeTrace) { Tracing = Tracing ? FALSE : TRUE; syslog(L_TRACE, "trace %sabled", Tracing ? "en" : "dis"); ChangeTrace = FALSE; } if (PushedBack) { if (PushedBack[0] == '\0') continue; if (Tracing) syslog(L_TRACE, "%s < %s", ClientHost, PushedBack); ac = Argify(PushedBack, &av); } else switch (r = READline(buff, (int)sizeof buff, timeout)) { default: syslog(L_ERROR, "%s internal %d in main", ClientHost, r); /* FALLTHROUGH */ case RTtimeout: if (timeout < CLIENT_TIMEOUT) syslog(L_NOTICE, "%s timeout short", ClientHost); else syslog(L_NOTICE, "%s timeout", ClientHost); Printf("%d Timeout after %d seconds, closing connection.\r\n", NNTP_TEMPERR_VAL, timeout); ExitWithStats(1); break; case RTlong: Reply("%d Line too long\r\n", NNTP_BAD_COMMAND_VAL); continue; case RTok: /* Do some input processing, check for blank line. */ if (Tracing) syslog(L_TRACE, "%s < %s", ClientHost, buff); if (buff[0] == '\0') continue; ac = Argify(buff, &av); break; case RTeof: /* Handled below. */ break; } /* Client gone? */ if (r == RTeof) break; if (ac == 0 || caseEQ(av[0], "quit")) break; /* Find command. */ for (cp = CMDtable; cp->Name; cp++) if (caseEQ(cp->Name, av[0])) break; if (cp->Name == NULL) { if ((int)strlen(buff) > 40) syslog(L_NOTICE, "%s unrecognized %.40s...", ClientHost, buff); else syslog(L_NOTICE, "%s unrecognized %s", ClientHost, buff); Reply("%d What?\r\n", NNTP_BAD_COMMAND_VAL); continue; } /* Check usage. */ if ((cp->Minac != CMDany && ac < cp->Minac) || (cp->Maxac != CMDany && ac > cp->Maxac)) { Reply("%d %s\r\n", NNTP_SYNTAX_VAL, cp->Help ? cp->Help : "Usage error"); continue; } /* Check permissions and dispatch. */ if (cp->Needauth && PERMneedauth) { Reply("%d Authentication required for command\r\n", NNTP_AUTH_NEEDED_VAL); continue; } TITLEset(av[0]); (*cp->Function)(ac, av); } Reply("%s\r\n", NNTP_GOODBYE_ACK); ExitWithStats(0); /* NOTREACHED */ } inn-1.7.2/nnrpd/post.h0100644000175100001440000000050606443103542013107 0ustar mdusers/* $Revision: 1.1 $ ** ** Net News Reading Protocol server. */ typedef enum _HEADERTYPE { HTobs, HTreq, HTstd } HEADERTYPE; typedef struct _HEADER { STRING Name; BOOL CanSet; HEADERTYPE Type; int Size; char *Value; } HEADER; #define HDR(_x) (Table[(_x)].Value) inn-1.7.2/installit.sh0100755000175100001440000000751006443103542013174 0ustar mdusers#! /bin/sh ## $Revision: 1.9 $ ## A script to install files and directories. PROGNAME=`basename $0` ## Paths to programs. CHOWN and WHOAMI are checked below. CHOWN=chown CHGRP=chgrp CHMOD=chmod CP=cp LN=ln MKDIR=mkdir MV=mv RM=rm STRIP=strip WHOAMI=whoami ## Some systems don't support -x, so we have to use -f. if [ ${CHOWN} = chown ] ; then if [ -f /etc/chown ] ; then CHOWN=/etc/chown else if [ -f /usr/etc/chown ] ; then CHOWN=/usr/etc/chown fi fi fi if [ ${WHOAMI} = whoami ] ; then if [ -f /usr/ucb/whoami ] ; then WHOAMI=/usr/ucb/whoami fi fi ## Defaults. CHOWNIT=false CHGROUPIT=false CHMODIT=false STRIPIT=false BACKIT=false TOUCHIT=true ROOT=unknown ## Process JCL. MORETODO=true while ${MORETODO} ; do case X"$1" in X-b) BACKIT=true BACKUP="$2" shift ;; X-b*) BACKIT=true BACKUP=`expr "$1" : '-b\(.*\)'` ;; X-g) GROUP="$2" CHGROUPIT=true shift ;; X-g*) GROUP=`expr "$1" : '-g\(.*\)'` CHGROUPIT=true ;; X-G) case ${ROOT} in unknown) case `${WHOAMI}` in root) ROOT=true ;; *) ROOT=false ;; esac ;; esac GROUP="$2" shift ${ROOT} && CHGROUPIT=true ;; X-G*) case ${ROOT} in unknown) case `${WHOAMI}` in root) ROOT=true ;; *) ROOT=false ;; esac ;; esac if ${ROOT} ; then GROUP=`expr "$1" : '-g\(.*\)'` CHGROUPIT=true fi ;; X-m) MODE="$2" CHMODIT=true shift ;; X-m*) MODE=`expr "$1" : '-m\(.*\)'` CHMODIT=true ;; X-n) TOUCHIT=false ;; X-o) OWNER="$2" CHOWNIT=true shift ;; X-o*) OWNER=`expr "$1" : '-o\(.*\)'` CHOWNIT=true ;; X-O) case ${ROOT} in unknown) case `${WHOAMI}` in root) ROOT=true ;; *) ROOT=false ;; esac ;; esac OWNER="$2" shift ${ROOT} && CHOWNIT=true ;; X-O*) case ${ROOT} in unknown) case `${WHOAMI}` in root) ROOT=true ;; *) ROOT=false ;; esac ;; esac if ${ROOT} ; then OWNER=`expr "$1" : '-o\(.*\)'` CHOWNIT=true fi ;; X-s) STRIPIT=true ;; X--) shift MORETODO=false ;; X-*) echo "${PROGNAME}: Unknown flag $1" 1>&2 exit 1 ;; *) MORETODO=false ;; esac ${MORETODO} && shift done ## Process arguments. if [ $# -ne 2 ] ; then echo "Usage: ${PROGNAME} [flags] source destination" exit 1 fi ## Making a directory? if [ X"$1" = X. ] ; then DEST="$2" if [ ! -d "${DEST}" ] ; then ${MKDIR} "${DEST}" || exit 1 fi if ${CHOWNIT} ; then ${CHOWN} "${OWNER}" "${DEST}" || exit 1 fi if ${CHGROUPIT} ; then ${CHGRP} "${GROUP}" "${DEST}" || exit 1 fi if ${CHMODIT} ; then umask 0 ${CHMOD} "${MODE}" "${DEST}" || exit 1 fi exit 0 fi ## Get the destination and a temp file in the destination diretory. if [ -d "$2" ] ; then DEST="$2/$1" TEMP="$2/$$.tmp" else DEST="$2" TEMP="`expr "$2" : '\(.*\)/.*'`/$$.tmp" fi ## If not given the same name, we must try to copy. if [ X"$1" != X"$2" ] ; then if cmp -s "$1" "${DEST}" ; then ## Files are same; touch or not. ${TOUCHIT} && { touch "${DEST}" || echo '(You can ignore this message)' } else ## If destination exists and we wish to backup, link to backup. if [ -f "${DEST}" ] ; then if ${BACKIT} ; then ${RM} -f "${DEST}${BACKUP}" ${LN} "${DEST}" "${DEST}${BACKUP}" fi fi ## Copy source to the right dir, then move to right spot. ## Done in two parts so we can hope for atomicity. ${RM} -f "${TEMP}" || exit 1 ${CP} "$1" "${TEMP}" || exit 1 ${MV} -f "${TEMP}" "${DEST}" || exit 1 fi fi ## Strip and set the modes. if ${STRIPIT} ; then ${STRIP} "${DEST}" || exit 1 fi if ${CHOWNIT} ; then ${CHOWN} "${OWNER}" "${DEST}" || exit 1 fi if ${CHGROUPIT} ; then ${CHGRP} "${GROUP}" "${DEST}" || exit 1 fi if ${CHMODIT} ; then umask 0 ${CHMOD} "${MODE}" "${DEST}" || exit 1 fi exit 0 inn-1.7.2/COPYRIGHT0100644000175100001440000000213406443103542012122 0ustar mdusers Copyright 1991 Rich Salz. All rights reserved. $Revision: 1.4 $ Redistribution and use in any form are permitted provided that the following restrictions are are met: 1. Source distributions must retain this entire copyright notice and comment. 2. Binary distributions must include the acknowledgement ``This product includes software developed by Rich Salz'' in the documentation or other materials provided with the distribution. This must not be represented as an endorsement or promotion without specific prior written permission. 3. The origin of this software must not be misrepresented, either by explicit claim or by omission. Credits must appear in the source and documentation. 4. Altered versions must be plainly marked as such in the source and documentation and must not be misrepresented as being the original software. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. inn-1.7.2/BUILD0100755000175100001440000001662606443103542011427 0ustar mdusers#! /bin/sh ## $Revision: 1.14 $ ## An interactive script to configure, build, and install InterNetNews. ## Installation documentation can be found in the "Install.ms*" files; ## please see the README! UMASK=${INN_UMASK-027} MAKE=${MAKE-make} if [ ! -f config/config.data ] ; then X=`basename ${EDITOR-vi}` echo "You don't have a config.data file. Do the following:" 1>&2 echo ' cd config' 1>&2 echo ' cp config.dist config.data' 1>&2 echo " $X config.data" 1>&2 echo ' cd ..' 1>&2 echo 'And start again.' 1>&2 exit 1 fi echo 'NOTE: If you just type [RETURN] to any question, this script will' echo ' assume you are being cautious, and default to whatever answer' echo ' is "safer." This usually means recompiling.' echo '' echo ' You cannot install over a running system; this script will' echo ' remind you about this later.' echo '' if [ -f config/subst ] ; then if cmp -s config/subst config/subst.sh ; then TYPE="sh" else TYPE="c" fi echo "A ${TYPE} version of subst exists;" file config/subst echo '-- do you want to use it [y or n]? ' | tr -d '\012' read reply reply=`echo "${reply}" | tr -d ' \011'` case "X${reply}" in X[yY]*) ;; *) rm config/subst if [ -f config/subst ] ; then echo 'Please remove config/subst and start again.' 1>&2 exit 1 fi ;; esac fi if [ ! -f config/subst ] ; then echo '' echo 'Use the /bin/sh version of subst, or the C version?' echo "Type sh, c, or x if you don't care: " | tr -d '\012' read style reply=`echo "${reply}" | tr -d ' \011'` case "X${style}" in X[Cc]*) WHAT=c ;; X[Ss][Hh]*) WHAT=sh ;; *) WHAT=subst ;; esac echo 'Building subst...' cd config ; ${MAKE} ${WHAT} ; cd .. if [ ! -f config/subst ] ; then echo "Can't build subst -- please investigate and fix." 1>&2 exit 1 fi fi echo '' echo 'Have you already built the executables [y or n]? ' | tr -d '\012' read reply reply=`echo "${reply}" | tr -d ' \011'` case "X${reply}" in X[yY]*) MUSTBUILD=false ;; *) MUSTBUILD=true ;; esac if ${MUSTBUILD} ; then echo '' echo 'Configuring INN' cd config ; ${MAKE} quiet ; cd .. echo '' echo 'Building and linting the INN library.' echo 'Please examine the lint output.' cd lib ; ${MAKE} lint ; cd .. ${PAGER-more} lib/lint || cat lib/lint echo '' echo 'Continue with the build [y or n]? ' | tr -d '\012' read reply reply=`echo "${reply}" | tr -d ' \011'` case "X${reply}" in X[yY]*) ;; *) echo 'Fix any problems and start again.' 1>&2 exit 1 ;; esac echo '' echo 'Run lint after each compile [y or n]? ' | tr -d '\012' read reply reply=`echo "${reply}" | tr -d ' \011'` case "X${reply}" in X[yY]*) WHAT=lint echo '' echo 'Compiling and linting the INN programs.' ;; *) WHAT=all echo '' echo 'Compiling the INN programs.' ;; esac ${MAKE} ${WHAT} || { echo 'Could not build INN. Fix any problems and start again.' 1>&2 exit 1 } if [ ${WHAT} = lint ] ; then echo '' echo 'Do you want to see the lint output [y or n]? ' | tr -d '\012' read reply reply=`echo "${reply}" | tr -d ' \011'` case "X${reply}" in X[yY]*) ${PAGER-more} */lint || cat */lint ;; esac fi fi umask ${UMASK} echo '' echo 'Setting umask to' `umask` echo '' echo 'Do the spool, etc., directories exist [y or n]? ' | tr -d '\012' read reply reply=`echo "${reply}" | tr -d ' \011'` case "X${reply}" in X[nN]*) echo 'Please su to root and run the "makedirs.sh" script' su ;; esac echo '' echo 'You are now ready to install the INN programs and config files.' echo 'You CANNOT DO THIS if INN is running now -- you must shut down' echo 'your news system first.' echo 'Do you want to continue with the installation [y or n]? ' | tr -d '\012' read reply reply=`echo "${reply}" | tr -d ' \011'` case "X${reply}" in X[yY]*) ;; *) echo 'Fix any problems and start again.' 1>&2 exit 1 esac echo '' echo 'Installing the INN programs.' echo 'Part of this may fail if you do not have have write permission in' echo 'all the destination directories. This is often the case for innd' echo 'and inndstart, for example. If the following "make" fails, do this:' echo ' echo ${MAKE} update | su' echo 'and rerun this script.' ${MAKE} update || { echo 'Could not install INN. Fix any problems and start again.' 1>&2 exit 1 } echo '' echo 'Building the data files.' cd site ${MAKE} all || { echo 'Fix any problems and start again.' 1>&2 exit 1 } cd .. MORETODO=true SUB='a subshell' while ${MORETODO} ; do echo '' echo "Start ${SUB} to edit the config files [y or n]? " | tr -d '\012' read reply reply=`echo "${reply}" | tr -d ' \011'` case "X${reply}" in X[yY]*) cd site ${SHELL-/bin/sh} cd .. SUB='another shell' ;; X[nN]*) MORETODO=false ;; esac done echo '' echo 'Installing the data files.' cd site ${MAKE} install || { echo 'Could not install INN. Fix any problems and start again.' 1>&2 exit 1 } cd .. echo '' echo 'Checking other data files.' TEMP=${TMPDIR-/tmp}/inn$$ cat >${TEMP} <<\EOF # =()@>()= ACTIVEFILE=/usr/lib/news/active # =()@>()= HISTORY=/usr/lib/news/history # =()@>()= NEWSBIN=/usr/lib/newsbin # =()@>()= NEWSLIB=/usr/lib/news # =()@ -g @@">()= OWNERS="-o news -g news" EOF ./config/subst -f config/config.data ${TEMP} >/dev/null . ${TEMP} rm ${TEMP} PATH=${PATH}:${NEWSBIN} ; export PATH ## Active file. if [ ! -f ${ACTIVEFILE} ] ; then echo '' echo 'You have no active file; making one.' echo 'Make sure to create the new groups you want!' echo 'control 0000000000 0000000001 n' >${ACTIVEFILE} echo 'junk 0000000000 0000000001 n' >>${ACTIVEFILE} else ${NEWSBIN}/makeactive -m -o >${ACTIVEFILE}.new || { echo 'Could not update your active file.' 1>&2 echo "Please run ${NEWSBIN}/makeactive -mo by hand." 1>&2 exit 1 } { mv -f ${ACTIVEFILE} ${ACTIVEFILE}.old && mv ${ACTIVEFILE}.new ${ACTIVEFILE} ; } || { echo 'Could not update active file (to widen number columns).' echo "Please run ${NEWSBIN}/makeactive -mo by hand." 1>&2 exit 1 } sh ./installit.sh ${OWNERS} -m 0640 ${ACTIVEFILE} ${ACTIVEFILE} fi ## History file. if [ ! -f ${HISTORY} ] ; then touch ${HISTORY} FLAGS="-r -i" else echo '' echo 'Did you use DBZ in your old news system [y or n]? ' | tr -d '\012' read reply reply=`echo "${reply}" | tr -d ' \011'` case "X${reply}" in X[yY]*) ;; *) FLAGS="-i" echo 'Will rebuild full history file' cp /dev/null ${HISTORY} ;; esac fi echo '' echo 'Setting correct ownership of history file -- double-check when done.' sh ./installit.sh ${OWNERS} -m 0664 ${HISTORY} ${HISTORY} ls -l ${HISTORY} echo '' echo 'Rebuilding history. This may take some time, so it is the last thing' echo 'in the installation.' HERE=`/bin/pwd` HISTORYDIR=`echo ${HISTORY} | sed -e 's@\(.*\)/.*@\1@'` cd ${HISTORYDIR} ${NEWSBIN}/makehistory ${FLAGS} || { echo 'Could not build history.' 1>&2 echo "Please run ${NEWSBIN}/makehistory by hand." 1>&2 exit 1 } mv history.n.dir history.dir mv history.n.pag history.pag cd ${HERE} sh ./installit.sh ${OWNERS} -m 0664 ${HISTORY}.dir ${HISTORY}.dir sh ./installit.sh ${OWNERS} -m 0664 ${HISTORY}.pag ${HISTORY}.pag exit 0 inn-1.7.2/innd/0040755000175100001440000000000006443103542011562 5ustar mdusersinn-1.7.2/innd/his.c0100644000175100001440000001415306443103542012512 0ustar mdusers/* $Revision: 1.23 $ ** ** History file routines. */ #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" #include "dbz.h" STATIC char HIShistpath[] = _PATH_HISTORY; STATIC FILE *HISwritefp; STATIC int HISreadfd; STATIC int HISdirty; STATIC int HISincore = INND_DBZINCORE; /* ** Set up the history files. */ void HISsetup() { if (HISwritefp == NULL) { /* Open the history file for appending formatted I/O. */ if ((HISwritefp = fopen(HIShistpath, "a")) == NULL) { syslog(L_FATAL, "%s cant fopen %s %m", LogName, HIShistpath); exit(1); } CloseOnExec((int)fileno(HISwritefp), TRUE); /* Open the history file for reading. */ if ((HISreadfd = open(HIShistpath, O_RDONLY)) < 0) { syslog(L_FATAL, "%s cant open %s %m", LogName, HIShistpath); exit(1); } CloseOnExec(HISreadfd, TRUE); /* Open the DBZ file. */ (void)dbzincore(HISincore); (void)dbzwritethrough(1); if (dbminit(HIShistpath) < 0) { syslog(L_FATAL, "%s cant dbminit %s %m", HIShistpath, LogName); exit(1); } } } /* ** Synchronize the in-core history file (flush it). */ void HISsync() { if (HISdirty) { if (dbzsync()) { syslog(L_FATAL, "%s cant dbzsync %m", LogName); exit(1); } HISdirty = 0; } } /* ** Close the history files. */ void HISclose() { if (HISwritefp != NULL) { /* Since dbmclose calls dbzsync we could replace this line with * "HISdirty = 0;". Oh well, it keeps the abstraction clean. */ HISsync(); if (dbmclose() < 0) syslog(L_ERROR, "%s cant dbmclose %m", LogName); if (fclose(HISwritefp) == EOF) syslog(L_ERROR, "%s cant fclose history %m", LogName); HISwritefp = NULL; if (close(HISreadfd) < 0) syslog(L_ERROR, "%s cant close history %m", LogName); HISreadfd = -1; } } /* ** File in the DBZ datum for a Message-ID, making sure not to copy any ** illegal characters. */ STATIC void HISsetkey(p, keyp) register char *p; datum *keyp; { static BUFFER MessageID; register char *dest; register int i; /* Get space to hold the ID. */ i = strlen(p); if (MessageID.Data == NULL) { MessageID.Data = NEW(char, i + 1); MessageID.Size = i; } else if (MessageID.Size < i) { RENEW(MessageID.Data, char, i + 1); MessageID.Size = i; } for (keyp->dptr = dest = MessageID.Data; *p; p++) if (*p == HIS_FIELDSEP || *p == '\n') *dest++ = HIS_BADCHAR; else *dest++ = *p; *dest = '\0'; keyp->dsize = dest - MessageID.Data + 1; } /* ** Get the list of files under which a Message-ID is stored. */ char * HISfilesfor(MessageID) char *MessageID; { static BUFFER Files; char *dest; datum key; datum val; long offset; register char *p; register int i; /* Get the seek value into the history file. */ HISsetkey(MessageID, &key); val = dbzfetch(key); if (val.dptr == NULL || val.dsize != sizeof offset) return NULL; /* Get space. */ if (Files.Data == NULL) { Files.Size = BUFSIZ; Files.Data = NEW(char, Files.Size); } /* Copy the value to an aligned spot. */ for (p = val.dptr, dest = (char *)&offset, i = sizeof offset; --i >= 0; ) *dest++ = *p++; if (lseek(HISreadfd, offset, SEEK_SET) == -1) return NULL; /* Read the text until \n or EOF. */ for (Files.Used = 0; ; ) { i = read(HISreadfd, &Files.Data[Files.Used], Files.Size - Files.Used - 1); if (i <= 0) return NULL; Files.Used += i; Files.Data[Files.Used] = '\0'; if ((p = strchr(Files.Data, '\n')) != NULL) { *p = '\0'; break; } /* If we have half our buffer left, get more space. */ if (Files.Size - Files.Used < Files.Size / 2) { Files.Size += BUFSIZ; RENEW(Files.Data, char, Files.Size); } } /* Move past the first two fields -- Message-ID and date info. */ if ((p = strchr(Files.Data, HIS_FIELDSEP)) == NULL) return NULL; if ((p = strchr(p + 1, HIS_FIELDSEP)) == NULL) return NULL; /* Translate newsgroup separators to slashes, return the fieldstart. */ for (dest = ++p; *p; p++) if (*p == '.') *p = '/'; return dest; } /* ** Have we already seen an article? */ BOOL HIShavearticle(MessageID) char *MessageID; { datum key; datum val; HISsetkey(MessageID, &key); val = dbzfetch(key); return val.dptr != NULL; } /* ** Turn a history filename entry from slashes to dots. It's a pity ** we have to do this. */ STATIC void HISslashify(p) register char *p; { register char *last; for (last = NULL; *p; p++) { if (*p == '/') { *p = '.'; last = p; } else if (*p == ' ' && last != NULL) *last = '/'; } if (last) *last = '/'; } /* ** Write a history entry. */ BOOL HISwrite(Data, paths) ARTDATA *Data; char *paths; { static char NOPATHS[] = ""; long offset; datum key; datum val; int i; HISsetkey(Data->MessageID, &key); if (paths != NULL && paths[0] != '\0') HISslashify(paths); else paths = NOPATHS; offset = ftell(HISwritefp); if (Data->Expires > 0) i = fprintf(HISwritefp, "%s%c%lu%c%lu%c%lu%c%s\n", key.dptr, HIS_FIELDSEP, (unsigned long)Data->Arrived, HIS_SUBFIELDSEP, (unsigned long)Data->Expires, HIS_SUBFIELDSEP, (unsigned long)Data->Posted, HIS_FIELDSEP, paths); else i = fprintf(HISwritefp, "%s%c%lu%c%s%c%lu%c%s\n", key.dptr, HIS_FIELDSEP, (unsigned long)Data->Arrived, HIS_SUBFIELDSEP, HIS_NOEXP, HIS_SUBFIELDSEP, (unsigned long)Data->Posted, HIS_FIELDSEP, paths); if (i == EOF || fflush(HISwritefp) == EOF) { /* The history line is now an orphan... */ i = errno; syslog(L_ERROR, "%s cant write history %m", LogName); IOError("history", i); return FALSE; } /* Set up the database values and write them. */ val.dptr = (char *)&offset; val.dsize = sizeof offset; if (dbzstore(key, val) < 0) { i = errno; syslog(L_ERROR, "%s cant dbzstore %m", LogName); IOError("history database", i); return FALSE; } if (++HISdirty >= ICD_SYNC_COUNT) HISsync(); return TRUE; } inn-1.7.2/innd/lc.c0100644000175100001440000000516206443103542012325 0ustar mdusers/* $Revision: 1.14 $ ** ** Routines for the local connect channel. Create a Unix-domain stream ** socket that processes on the local server connect to. Once the ** connection is set up, we speak NNTP. The connect channel is used only ** by rnews to feed in articles from the UUCP sites. */ #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" #if defined(DO_HAVE_UNIX_DOMAIN) #include STATIC char LCpath[] = _PATH_NNTPCONNECT; STATIC CHANNEL *LCchan; /* ** Read function. Accept the connection and create an NNTP channel. */ STATIC FUNCTYPE LCreader(cp) CHANNEL *cp; { int fd; CHANNEL *new; if (cp != LCchan) { syslog(L_ERROR, "%s internal LCreader wrong channel 0x%x not 0x%x", LogName, cp, LCchan); return; } if ((fd = accept(cp->fd, (struct sockaddr *)NULL, (int *)NULL)) < 0) { syslog(L_ERROR, "%s cant accept CCreader %m", LogName); return; } new = NCcreate(fd, FALSE, TRUE); new->Address.s_addr = MyAddress.s_addr; syslog(L_NOTICE, "%s connected %d", "localhost", new->fd); } /* ** Write-done function. Shouldn't happen. */ STATIC FUNCTYPE LCwritedone() { syslog(L_ERROR, "%s internal LCwritedone", LogName); } #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ /* ** Create the channel. */ void LCsetup() { #if defined(DO_HAVE_UNIX_DOMAIN) int i; struct sockaddr_un server; /* Remove old detritus. */ if (unlink(LCpath) < 0 && errno != ENOENT) { syslog(L_FATAL, "%s cant unlink %s %m", LogName, LCpath); exit(1); } /* Create a socket and name it. */ if ((i = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { syslog(L_FATAL, "%s cant socket %s %m", LogName, LCpath); exit(1); } (void)memset((POINTER)&server, 0, sizeof server); server.sun_family = AF_UNIX; (void)strcpy(server.sun_path, LCpath); if (bind(i, (struct sockaddr *)&server, AF_UNIX_SOCKSIZE(server)) < 0) { syslog(L_FATAL, "%s cant bind %s %m", LogName, LCpath); exit(1); } /* Set it up to wait for connections. */ if (listen(i, MAXLISTEN) < 0) { syslog(L_FATAL, "%s cant listen %s %m", LogName, LCpath); exit(1); } LCchan = CHANcreate(i, CTlocalconn, CSwaiting, LCreader, LCwritedone); syslog(L_NOTICE, "%s lcsetup %s", LogName, CHANname(LCchan)); RCHANadd(LCchan); #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ } /* ** Cleanly shut down the channel. */ void LCclose() { #if defined(DO_HAVE_UNIX_DOMAIN) CHANclose(LCchan, CHANname(LCchan)); LCchan = NULL; if (unlink(LCpath) < 0) syslog(L_ERROR, "%s cant unlink %s %m", LogName, LCpath); #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ } inn-1.7.2/innd/inndstart.c0100644000175100001440000001037406443103542013736 0ustar mdusers/* $Revision: 1.14 $ ** ** Open the privileged port, then exec innd. */ #include #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #include #include "paths.h" #include "logging.h" #include "libinn.h" #include "macros.h" #if NOFILE_LIMIT > 0 #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #endif /* NOFILE_LIMIT > 0 */ #include #include /* #define DEBUGGER "/usr/ucb/dbx" */ #if NOFILE_LIMIT > 0 /* ** Set the limit on the number of open files we can have. I don't ** like having to do this. */ STATIC void SetDescriptorLimit(i) int i; { struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { syslog(L_ERROR, "inndstart cant getrlimit(NOFILE) %m"); return; } rl.rlim_cur = i; if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { syslog(L_ERROR, "inndstart cant setrlimit(NOFILE) %d %m", i); return; } } #endif /* NOFILE_LIMIT > 0 */ int main(ac, av) int ac; char *av[]; { static char INNDDIR[] = _PATH_INNDDIR; GID_T NewsGID; UID_T NewsUID; struct sockaddr_in server; register int i; register int j; #if defined(SO_REUSEADDR) int on; #endif /* defined(SO_REUSEADDR) */ STRING *argv; char *p; char pflag[SMBUF]; char buff[BUFSIZ]; STRING env[8]; struct stat Sb; (void)openlog("inndstart", L_OPENLOG_FLAGS, LOG_INN_PROG); /* Make sure INND directory exists. */ if (stat(INNDDIR, &Sb) < 0 || !S_ISDIR(Sb.st_mode)) { syslog(L_FATAL, "inndstart cant stat %s %m", INNDDIR); exit(1); } NewsUID = Sb.st_uid; NewsGID = Sb.st_gid; if (setgroups(1, &NewsGID) < 0) syslog(L_ERROR, "inndstart cant setgroups %m"); #if NOFILE_LIMIT > 0 SetDescriptorLimit(NOFILE_LIMIT); #endif /* NOFILE_LIMIT > 0 */ /* Create a socket and name it. */ if ((i = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(L_FATAL, "inndstart cant socket %m"); exit(1); } #if defined(SO_REUSEADDR) on = 1; if (setsockopt(i, SOL_SOCKET, SO_REUSEADDR, (caddr_t)&on, sizeof on) < 0) syslog(L_ERROR, "inndstart cant setsockopt %m"); #endif /* defined(SO_REUSEADDR) */ (void)memset((POINTER)&server, 0, sizeof server); server.sin_port = htons(NNTP_PORT); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(i, (struct sockaddr *)&server, sizeof server) < 0) { syslog(L_FATAL, "inndstart cant bind %m"); exit(1); } (void)sprintf(pflag, "-p%d", i); /* Build the new argument vector. */ argv = NEW(STRING, 2 + ac + 1); j = 0; #if defined(DEBUGGER) argv[j++] = DEBUGGER; argv[j++] = _PATH_INND; argv[j] = NULL; (void)printf("Use -dp%d\n", i); #else argv[j++] = _PATH_INND; argv[j++] = pflag; for (i = 1; av[i]; ) { if (strncmp(av[i], "-p", 2) != 0) argv[j++] = av[i++]; else i++; } argv[j] = NULL; #endif /* defined(DEBUGGER) */ /* Set our user and group id. */ (void)setgid(NewsGID); if (getgid() != NewsGID) syslog(L_ERROR, "inndstart cant setgid to %d %m", NewsGID); (void)setuid(NewsUID); if (getuid() != NewsUID) syslog(L_ERROR, "inndstart cant setuid to %d %m", NewsUID); /* Set up the environment. */ (void)sprintf(buff, "PATH=%s:%s:/bin:/usr/bin:/usr/ucb", _PATH_NEWSBIN, _PATH_NEWSLIB); env[0] = COPY(buff); (void)sprintf(buff, "TMPDIR=%s", _PATH_TMP); env[1] = COPY(buff); (void)sprintf(buff, "SHELL=%s", _PATH_SH); env[2] = COPY(buff); (void)sprintf(buff, "LOGNAME=%s", NEWSMASTER); env[3] = COPY(buff); (void)sprintf(buff, "USER=%s", NEWSMASTER); env[4] = COPY(buff); (void)sprintf(buff, "HOME=%s", _PATH_NEWSHOME); env[5] = COPY(buff); i = 6; /* linux uglyness */ if ((p = getenv("BIND_INADDR")) != NULL) { (void)sprintf(buff, "BIND_INADDR=%s", p); env[i++] = COPY(buff); } if ((p = getenv("TZ")) != NULL) { (void)sprintf(buff, "TZ=%s", p); env[i++] = COPY(buff); } env[i++] = NULL; /* Go exec innd. */ (void)execve(argv[0], (CSTRING *)argv, (CSTRING *)env); syslog(L_FATAL, "inndstart cant exec %s %m", argv[0]); _exit(1); /* NOTREACHED */ } inn-1.7.2/innd/innd.c0100644000175100001440000005242106443103542012657 0ustar mdusers/* $Revision: 1.52 $ ** ** Variable definitions, miscellany, and main(). */ #include #include #include "configdata.h" #include "clibrary.h" #define DEFINE_DATA #include "innd.h" #include #include #if NOFILE_LIMIT > 0 #include #endif /* NOFILE_LIMIT > 0 */ #if defined(DO_FAST_RESOLV) #include #include #endif /* defined(DO_FAST_RESOLV) */ #if defined(DO_HAVE_SETBUFFER) #define SETBUFFER(F, buff, size) setbuffer((F), (buff), (size)) STATIC int LogBufferSize = 4096; #else #define SETBUFFER(F, buff, size) setbuf((F), (buff)) STATIC int LogBufferSize = BUFSIZ; #endif /* defined(HAVE_SETBUFFER) */ BOOL AmRoot = TRUE; BOOL BufferedLogs = TRUE; BOOL NNRPTracing = FALSE; BOOL StreamingOff = FALSE ; /* default is we can stream */ BOOL Tracing = FALSE; BOOL DoLinks = TRUE; BOOL DoCancels = TRUE; char LogName[] = "SERVER"; char SPOOL[] = _PATH_SPOOL; int ErrorCount = IO_ERROR_COUNT; int MaxIncoming = DEFAULT_CONNECTIONS; int SPOOLlen = STRLEN(SPOOL); long LargestArticle = MAX_ART_SIZE; OPERATINGMODE Mode = OMrunning; time_t Cutoff = DEFAULT_CUTOFF * 24 * 60 * 60; int RemoteLimit = REMOTELIMIT; time_t RemoteTimer = REMOTETIMER; int RemoteTotal = REMOTETOTAL; #if defined(__CENTERLINE__) BOOL Debug = TRUE; #else BOOL Debug = FALSE; #endif /* defined(__CENTERLINE__) */ #if defined(lint) || defined(__CENTERLINE__) int KeepLintQuiet = 0; #endif /* defined(lint) || defined(__CENTERLINE__) */ STATIC char *ErrlogBuffer; STATIC char *LogBuffer; STATIC char ERRLOG[] = _PATH_ERRLOG; STATIC char INNDDIR[] = _PATH_INNDDIR; STATIC char LOG[] = _PATH_LOGFILE; STATIC char PID[] = _PATH_SERVERPID; STATIC UID_T NewsUID; STATIC GID_T NewsGID; /* ** Sprintf a long into a buffer with enough leading zero's so that it ** takes up width characters. Don't add trailing NUL. Return TRUE ** if it fit. Used for updating high-water marks in the active file ** in-place. */ BOOL FormatLong(p, value, width) register char *p; register long value; register int width; { for (p += width - 1; width-- > 0; ) { *p-- = (int)(value % 10) + '0'; value /= 10; } return value == 0; } /* ** Glue a string, a char, and a string together. Useful for making ** filenames. */ void FileGlue(p, n1, c, n2) register char *p; register char *n1; char c; register char *n2; { p += strlen(strcpy(p, n1)); *p++ = c; (void)strcpy(p, n2); } /* ** Turn any \r or \n in text into spaces. Used to splice back multi-line ** headers into a single line. */ STATIC char * Join(text) register char *text; { register char *p; for (p = text; *p; p++) if (*p == '\n' || *p == '\r') *p = ' '; return text; } /* ** Return a short name that won't overrun our bufer or syslog's buffer. ** q should either be p, or point into p where the "interesting" part is. */ char * MaxLength(p, q) char *p; char *q; { static char buff[80]; register int i; /* Already short enough? */ i = strlen(p); if (i < sizeof buff - 1) return Join(p); /* Simple case of just want the begining? */ if (q - p < sizeof buff - 4) { (void)strncpy(buff, p, sizeof buff - 4); (void)strcpy(&buff[sizeof buff - 4], "..."); } /* Is getting last 10 characters good enough? */ else if ((p + i) - q < 10) { (void)strncpy(buff, p, sizeof buff - 14); (void)strcpy(&buff[sizeof buff - 14], "..."); (void)strcpy(&buff[sizeof buff - 11], &p[i - 10]); } else { /* Not in last 10 bytes, so use double elipses. */ (void)strncpy(buff, p, sizeof buff - 17); (void)strcpy(&buff[sizeof buff - 17], "..."); (void)strncpy(&buff[sizeof buff - 14], &q[-5], 10); (void)strcpy(&buff[sizeof buff - 4], "..."); } return Join(buff); } /* ** Split text into comma-separated fields. Return an allocated ** NULL-terminated array of the fields within the modified argument that ** the caller is expected to save or free. We don't use strchr() since ** the text is expected to be either relatively short or "comma-dense." */ char ** CommaSplit(text) char *text; { register int i; register char *p; register char **av; char **save; /* How much space do we need? */ for (i = 2, p = text; *p; p++) if (*p == ',') i++; for (av = save = NEW(char*, i), *av++ = p = text; *p; ) if (*p == ',') { *p++ = '\0'; *av++ = p; } else p++; *av = NULL; return save; } /* ** Do we need a shell for the command? If not, av is filled in with ** the individual words of the command and the command is modified to ** have NUL's inserted. */ BOOL NeedShell(p, av, end) register char *p; register char **av; register char **end; { static char Metachars[] = ";<>|*?[]{}()#$&=`'\"\\~\n"; register char *q; /* We don't use execvp(); works for users, fails out of /etc/rc. */ if (*p != '/') return TRUE; for (q = p; *q; q++) if (strchr(Metachars, *q) != NULL) return TRUE; for (end--; av < end; ) { /* Mark this word, check for shell meta-characters. */ for (*av++ = p; *p && !ISWHITE(*p); p++) continue; /* If end of list, we're done. */ if (*p == '\0') { *av = NULL; return FALSE; } /* Skip whitespace, find next word. */ for (*p++ = '\0'; ISWHITE(*p); p++) continue; if (*p == '\0') { *av = NULL; return FALSE; } } /* Didn't fit. */ return TRUE; } /* ** Spawn a process, with I/O redirected as needed. Return the PID or -1 ** (and a syslog'd message) on error. */ PID_T Spawn(fd0, fd1, fd2, av) int fd0; int fd1; int fd2; char *av[]; { static char NOCLOSE[] = "%s cant close %d in %s %m"; static char NODUP2[] = "%s cant dup2 %d to %d in %s %m"; PID_T i; /* Fork; on error, give up. If not using the patched dbz, make * this call fork! */ i = FORK(); if (i == -1) { syslog(L_ERROR, "%s cant fork %s %m", LogName, av[0]); return -1; } /* If parent, do nothing. */ if (i > 0) return i; /* Child -- do any I/O redirection. */ if (fd0 != 0) { if (dup2(fd0, 0) < 0) { syslog(L_FATAL, NODUP2, LogName, fd0, 0, av[0]); _exit(1); } if (fd0 != fd1 && fd0 != fd2 && close(fd0) < 0) syslog(L_ERROR, NOCLOSE, LogName, fd0, av[0]); } if (fd1 != 1) { if (dup2(fd1, 1) < 0) { syslog(L_FATAL, NODUP2, LogName, fd1, 1, av[0]); _exit(1); } if (fd1 != fd2 && close(fd1) < 0) syslog(L_ERROR, NOCLOSE, LogName, fd1, av[0]); } if (fd2 != 2) { if (dup2(fd2, 2) < 0) { syslog(L_FATAL, NODUP2, LogName, fd2, 2, av[0]); _exit(1); } if (close(fd2) < 0) syslog(L_ERROR, NOCLOSE, LogName, fd2, av[0]); } CloseOnExec(0, FALSE); CloseOnExec(1, FALSE); CloseOnExec(2, FALSE); /* Try to set our permissions. */ #if defined(DO_INND_NICE_KIDS) (void)nice(INND_NICE_VALUE); #endif /* defined(DO_INND_NICE_KIDS) */ if (setgid(NewsGID) == -1) syslog(L_ERROR, "%s cant setgid in %s %m", LogName, av[0]); if (setuid(NewsUID) == -1) syslog(L_ERROR, "%s cant setuid in %s %m", LogName, av[0]); /* Close the DBZ database without doing any writing. */ /* Not needed with the patched DBZ; can't be used with vfork. * (void)dbzcancel(); * (void)dbmclose(); */ /* Start the desired process (finally!). */ (void)execv(av[0], av); syslog(L_FATAL, "%s cant exec in %s %m", LogName, av[0]); _exit(1); /* NOTREACHED */ } /* ** Stat our control directory and see who should own things. */ STATIC BOOL GetNewsOwnerships() { struct stat Sb; /* Make sure item exists and is of the right type. */ if (stat(INNDDIR, &Sb) < 0) return FALSE; if (!S_ISDIR(Sb.st_mode)) return FALSE; NewsUID = Sb.st_uid; NewsGID = Sb.st_gid; return TRUE; } /* ** Change the onwership of a file. */ void xchown(p) char *p; { if (chown(p, NewsUID, NewsGID) < 0) syslog(L_ERROR, "%s cant chown %s %m", LogName, p); } /* ** Try to make one directory. Return FALSE on error. */ STATIC BOOL MakeDir(Name) char *Name; { struct stat Sb; if (mkdir(Name, GROUPDIR_MODE) >= 0) { if (AmRoot) xchown(Name); return TRUE; } /* See if it failed because it already exists. */ return stat(Name, &Sb) >= 0 && S_ISDIR(Sb.st_mode); } /* ** Given a directory, comp/foo/bar, create that directory and all ** intermediate directories needed. Return 0 if ok, else -1. */ BOOL MakeSpoolDirectory(Name) register char *Name; { register char *p; BOOL made; /* Optimize common case -- parent almost always exists. */ if (MakeDir(Name)) return TRUE; /* Try to make each of comp and comp/foo in turn. */ for (p = Name; *p; p++) if (*p == '/') { *p = '\0'; made = MakeDir(Name); *p = '/'; if (!made) return FALSE; } return MakeDir(Name); } /* ** Flush one log file, with pessimistic size of working filename buffer. */ void ReopenLog(F) FILE *F; { char buff[sizeof LOG + sizeof ERRLOG + 4 + 1]; char *Name; char *Buffer; int mask; if (Debug) return; if (F == Log) { Name = LOG; Buffer = LogBuffer; } else { Name = ERRLOG; Buffer = ErrlogBuffer; } FileGlue(buff, Name, '.', "old"); if (rename(Name, buff) < 0) syslog(L_ERROR, "%s cant rename %s to %s %m", LogName, Name, buff); mask = umask(033); if (freopen(Name, "a", F) != F) { syslog(L_FATAL, "%s cant freopen %s %m", LogName, Name); exit(1); } (void)umask(mask); if (AmRoot) xchown(Name); if (BufferedLogs) SETBUFFER(F, Buffer, LogBufferSize); } /* ** Function called when memory allocation fails. */ STATIC int AllocationFailure(what, i) char *what; unsigned int i; { /* Print i as %d so huge values are real obvious. */ syslog(L_FATAL, "%s cant %s %d bytes %m", LogName, what, i); exit(1); /* NOTREACHED */ } /* ** We ran out of space or other I/O error, throttle ourselves. */ void ThrottleIOError(when) char *when; { char buff[SMBUF]; STRING p; int oerrno; if (Mode == OMrunning) { oerrno = errno; if (Reservation) { DISPOSE(Reservation); Reservation = NULL; } (void)sprintf(buff, "%s writing %s file -- throttling", strerror(oerrno), when); if ((p = CCblock(OMthrottled, buff)) != NULL) syslog(L_ERROR, "%s cant throttle %s", LogName, p); syslog(L_FATAL, "%s throttle %s", LogName, buff); errno = oerrno; } } /* ** Close down all parts of the system (e.g., before calling exit or exec). */ void JustCleanup() { SITEflushall(FALSE); /* PROCclose(FALSE); */ CCclose(); LCclose(); NCclose(); RCclose(); ICDclose(); HISclose(); ARTclose(); #if defined(DO_TCL) TCLclose(); #endif /* defined(DO_TCL) */ #if defined(DO_PERL) PerlFilter (FALSE) ; PerlClose(); #endif /* defined(DO_PERL) */ (void)sleep(1); /* PROCclose(TRUE); */ if (unlink(PID) < 0 && errno != ENOENT) syslog(L_ERROR, "%s cant unlink %s %m", LogName, PID); } /* ** The name is self-explanatory. */ NORETURN CleanupAndExit(x, why) int x; char *why; { JustCleanup(); if (why) syslog(L_FATAL, "%s shutdown %s", LogName, why); else syslog(L_FATAL, "%s shutdown received signal %d", LogName, KillerSignal); exit(x); } #if NOFILE_LIMIT > 0 /* ** Set the limit on the number of open files we can have. I don't ** like having to do this. */ STATIC void SetDescriptorLimit(i) int i; { struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { syslog(L_ERROR, "%s cant getrlimit(NOFILE) %m", LogName); return; } rl.rlim_cur = i; if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { syslog(L_ERROR, "%s cant setrlimit(NOFILE) %d %m", LogName, i); return; } } #endif /* NOFILE_LIMIT > 0 */ /* ** Signal handler to catch SIGTERM and queue a clean shutdown. */ STATIC SIGHANDLER CatchTerminate(s) int s; { GotTerminate = TRUE; KillerSignal = s; (void)signal(s, CatchTerminate); } /* ** Print a usage message and exit. */ STATIC NORETURN Usage() { (void)fprintf(stderr, "Usage error.\n"); exit(1); } int main(ac, av) int ac; char *av[]; { static char WHEN[] = "PID file"; int i; int port; int logflags; char buff[SMBUF]; char *master; STRING path; char *p; FILE *F; BOOL ShouldFork; BOOL ShouldRenumber; BOOL ShouldSyntaxCheck; PID_T pid; #if defined(_DEBUG_MALLOC_INC) union malloptarg m; #endif /* defined(_DEBUG_MALLOC_INC) */ /* Set up the pathname, first thing. */ path = av[0]; if (path == NULL || *path == '\0') path = "innd"; else if ((p = strrchr(path, '/')) != NULL) path = p + 1; ONALLOCFAIL(AllocationFailure); Version = INNVersion(); /* Handle malloc debugging. */ #if defined(_DEBUG_MALLOC_INC) m.i = M_HANDLE_ABORT; dbmallopt(MALLOC_WARN, &m); dbmallopt(MALLOC_FATAL, &m); m.i = 3; dbmallopt(MALLOC_FILLAREA, &m); m.i = 0; dbmallopt(MALLOC_CKCHAIN, &m); dbmallopt(MALLOC_CKDATA, &m); #endif /* defined(_DEBUG_MALLOC_INC) */ /* Set defaults. */ TimeOut.tv_sec = DEFAULT_TIMEOUT; ShouldFork = TRUE; ShouldRenumber = FALSE; ShouldSyntaxCheck = FALSE; logflags = L_OPENLOG_FLAGS | LOG_NOWAIT; port = -1; master = NULL; #if defined(DONT_ALLOW_READERS) NNRPFollows = TRUE; #endif /* defined(DONT_ALLOW_READERS) */ #if defined(DO_FAST_RESOLV) /* We only use FQDN's in the hosts.nntp file. */ _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); #endif /* defined(DO_FAST_RESOLV) */ /* Parse JCL. */ CCcopyargv(av); while ((i = getopt(ac, av, "ac:Cdfi:l:Lm:o:n:p:rsS:t:uH:T:X:")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'a': AnyIncoming = TRUE; break; case 'c': Cutoff = atoi(optarg) * 24 * 60 * 60; break; case 'd': Debug = TRUE; #if defined(LOG_PERROR) logflags = LOG_PERROR | (logflags & ~LOG_CONS); #endif /* defined(LOG_PERROR) */ break; case 'f': ShouldFork = FALSE; break; case 'H': RemoteLimit = atoi(optarg); break; case 'i': MaxIncoming = atoi(optarg); break; case 'l': LargestArticle = atol(optarg); break; case 'm': if (ModeReason) DISPOSE(ModeReason); switch (*optarg) { default: Usage(); /* NOTREACHED */ case 'g': Mode = OMrunning; break; case 'p': Mode = OMpaused; break; case 't': Mode = OMthrottled; break; } if (Mode != OMrunning) { (void)sprintf(buff, "%sed from command line", Mode == OMpaused ? "Paus" : "Throttl"); ModeReason = COPY(buff); } break; case 'n': switch (*optarg) { default: Usage(); /* NOTREACHED */ case 'n': NNRPFollows = TRUE; break; case 'y': NNRPFollows = FALSE; break; } break; case 'o': MaxOutgoing = atoi(optarg); break; case 'p': /* Silently ignore multiple -p flags, in case ctlinnd xexec * called inndstart. */ if (port == -1) { port = atoi(optarg); AmRoot = FALSE; } break; case 'r': ShouldRenumber = TRUE; break; case 's': ShouldSyntaxCheck = TRUE; break; case 'S': if (strlen(optarg) >= SMBUF - 4) Usage(); master = optarg; break; case 't': TimeOut.tv_sec = atol(optarg); break; case 'T': RemoteTotal = atoi(optarg); break; case 'u': BufferedLogs = FALSE; break; case 'L': DoLinks = FALSE; /* don't do links for cross posts */ break; case 'C': DoCancels = FALSE; break; case 'X': RemoteTimer = atoi(optarg); break; case 'Z': StreamingOff = TRUE; break; } ac -= optind; if (ac != 0) Usage(); if (ModeReason && NNRPFollows) NNRPReason = COPY(ModeReason); openlog(path, logflags, LOG_INN_SERVER); if (ShouldSyntaxCheck) { if ((p = (char *) CCcheckfile((char **)NULL)) == NULL) exit(0); (void)fprintf(stderr, "%s\n", p + 2); exit(1); } /* Go to where the data is. */ if (chdir(SPOOL) < 0) { syslog(L_FATAL, "%s cant chdir %s %m", LogName, SPOOL); exit(1); } /* Get the Path entry. */ if ((path = GetConfigValue(_CONF_PATHHOST)) == NULL) { syslog(L_FATAL, "%s cant GetConfigValue %s %m", LogName, _CONF_PATHHOST); exit(1); } Path.Used = strlen(path) + 1; Path.Data = NEW(char, Path.Used + 1); (void)sprintf(Path.Data, "%s!", path); /* Get the Xref prefix. */ Xref.Size = STRLEN("Xref: ") + strlen(path) + 1; Xref.Data = NEW(char, Xref.Size); FileGlue(Xref.Data, "Xref:", ' ', path); if ((p = strchr(Xref.Data, '!')) != NULL) *p = '\0'; Xref.Used = strlen(Xref.Data); Xrefbase = Xref.Used; #if !defined(__CENTERLINE__) /* Set standard input to /dev/null. */ if ((i = open("/dev/null", O_RDWR)) < 0) { syslog(L_FATAL, "%s cant open /dev/null %m", LogName); exit(1); } if (dup2(i, 0) != 0) syslog(L_NOTICE, "%s cant dup2 %d to 0 %m", LogName, i); (void)close(i); #endif /* !defined(__CENTERLINE__) */ /* Set up our permissions. */ (void)umask(NEWSUMASK); if (!GetNewsOwnerships()) { syslog(L_FATAL, "%s internal cant stat control directory %m", LogName); exit(1); } if (port != -1 && setgid(NewsGID) < 0) syslog(L_ERROR, "%s cant setgid running as %d not %d %m", LogName, (int)getgid(), (int)NewsGID); if (Debug) { Log = stdout; Errlog = stderr; (void)signal(SIGINT, CatchTerminate); } else { if (ShouldFork) { /* Become a server. */ i = fork(); if (i < 0) { syslog(L_FATAL, "%s cant fork %m", LogName); exit(1); } if (i > 0) _exit(0); #if defined(TIOCNOTTY) /* Disassociate from terminal. */ if ((i = open("/dev/tty", O_RDWR)) >= 0) { if (ioctl(i, TIOCNOTTY, (char *)NULL) < 0) syslog(L_ERROR, "%s cant ioctl(TIOCNOTTY) %m", LogName); if (close(i) < 0) syslog(L_ERROR, "%s cant close /dev/tty %m", LogName); } #endif /* defined(TIOCNOTTY) */ #if defined(DO_HAVE_SETSID) (void)setsid(); #endif /* defined(DO_HAVE_SETSID) */ } /* Open the Log. */ (void)fclose(stdout); if ((Log = fopen(LOG, "a")) == NULL) { syslog(L_FATAL, "%s cant fopen %s %m", LogName, LOG); exit(1); } if (AmRoot) xchown(LOG); if (BufferedLogs && (LogBuffer = NEW(char, LogBufferSize)) != NULL) SETBUFFER(Log, LogBuffer, LogBufferSize); /* Open the Errlog. */ (void)fclose(stderr); if ((Errlog = fopen(ERRLOG, "a")) == NULL) { syslog(L_FATAL, "%s cant fopen %s %m", LogName, ERRLOG); exit(1); } if (AmRoot) xchown(ERRLOG); if (BufferedLogs && (ErrlogBuffer = NEW(char, LogBufferSize)) != NULL) SETBUFFER(Errlog, ErrlogBuffer, LogBufferSize); } /* Set number of open channels. */ #if NOFILE_LIMIT > 0 if (AmRoot) SetDescriptorLimit(NOFILE_LIMIT); #endif /* NOFILE_LIMIT > 0 */ /* Get number of open channels. */ if ((i = getfdcount()) < 0) { syslog(L_FATAL, "%s cant getfdcount %m", LogName); exit(1); } syslog(L_NOTICE, "%s descriptors %d", LogName, i); if (MaxOutgoing == 0) { /* getfdcount() - (stdio + dbz + cc + lc + rc + art + fudge) */ MaxOutgoing = i - ( 3 + 3 + 2 + 1 + 1 + 1 + 2 ); syslog(L_NOTICE, "%s outgoing %d", LogName, MaxOutgoing); } /* See if another instance is alive. */ if ((F = fopen(PID, "r")) != NULL) { if (fgets(buff, sizeof buff, F) != NULL && ((pid = (PID_T) atol(buff)) > 0) && (kill(pid, 0) > 0 || errno != ESRCH)) { (void)syslog(L_FATAL, "%s already_running pid %ld", LogName, (long) pid); exit(1); } (void)fclose(F); } if (GetTimeInfo(&Now) < 0) syslog(L_ERROR, "%s cant gettimeinfo %m", LogName); /* Set up the various parts of the system. Channel feeds start * processes so call PROCsetup before ICDsetup. NNTP needs to know * if it's a slave, so call RCsetup before NCsetup. */ (void)signal(SIGTERM, CatchTerminate); #if defined(SIGDANGER) (void)signal(SIGDANGER, CatchTerminate); #endif /* defined(SIGDANGER) */ CHANsetup(i); PROCsetup(i * 2); HISsetup(); CCsetup(); LCsetup(); RCsetup(port, master); NCsetup(i); ARTsetup(); ICDsetup(TRUE); #if defined(_DEBUG_MALLOC_INC) m.i = 1; dbmallopt(MALLOC_CKCHAIN, &m); dbmallopt(MALLOC_CKDATA, &m); #endif /* defined(_DEBUG_MALLOC_INC) */ /* Record our PID. */ pid = getpid(); if ((F = fopen(PID, "w")) == NULL) { i = errno; syslog(L_ERROR, "%s cant fopen %s %m", LogName, PID); IOError(WHEN, i); } else { if (fprintf(F, "%ld\n", (long)pid) == EOF || ferror(F)) { i = errno; syslog(L_ERROR, "%s cant fprintf %s %m", LogName, PID); IOError(WHEN, i); } if (fclose(F) == EOF) { i = errno; syslog(L_ERROR, "%s cant fclose %s %m", LogName, PID); IOError(WHEN, i); } if (chmod(PID, 0664) < 0) { i = errno; syslog(L_ERROR, "%s cant chmod %s %m", LogName, PID); IOError(WHEN, i); } } #if defined(DO_TCL) TCLsetup(); #endif /* defined(DO_TCL) */ #if defined(DO_PERL) /* Load the Perl code */ PERLsetup(_PATH_PERL_STARTUP_INND, _PATH_PERL_FILTER_INND, "filter_art"); PerlFilter (TRUE) ; #endif /* defined(DO_PERL) */ /* And away we go... */ if (ShouldRenumber) { syslog(L_NOTICE, "%s renumbering", LogName); if (!ICDrenumberactive()) { syslog(L_FATAL, "%s cant renumber", LogName); exit(1); } } syslog(L_NOTICE, "%s starting", LogName); CHANreadloop(); CleanupAndExit(1, "CHANreadloop returned"); /* NOTREACHED */ } inn-1.7.2/innd/innd.h0100644000175100001440000003157606443103542012674 0ustar mdusers/* $Revision: 1.51 $ ** ** Many of the data types used here have abbreviations, such as CT ** for CHANNELTYPE. Here are a list of the conventions and meanings: ** ART A news article ** CHAN An I/O channel ** CS Channel state ** CT Channel type ** FNL Funnel, into which other feeds pour ** FT Feed type -- how a site gets told about new articles ** ICD In-core data (primarily the active and sys files) ** LC Local NNTP connection-receiving channel ** CC Control channel (used by ctlinnd) ** NC NNTP client channel ** NG Newsgroup ** NGH Newgroup hashtable ** PROC A process (used to feed a site) ** PS Process state ** RC Remote NNTP connection-receiving channel ** RCHAN A channel in "read" state ** SITE Something that gets told when we get an article ** WCHAN A channel in "write" state */ #include #include #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include #include #include #include "nntp.h" #include "paths.h" #include "logging.h" #include "libinn.h" #include "macros.h" #if defined(DO_TCL) #include #undef EXTERN /* TCL defines EXTERN; this undef prevents error messages when we define it later */ #endif /* defined(DO_TCL) */ typedef short SITEIDX; #define NOSITE ((SITEIDX) -1) /* ** Some convenient shorthands. */ typedef struct in_addr INADDR; /* ** Server's operating mode. */ typedef enum _OPERATINGMODE { OMrunning, OMpaused, OMthrottled } OPERATINGMODE; /* ** An I/O buffer, including a size, an amount used, and a count of how ** much space is left if reading or how much still needs to be written. */ typedef struct _BUFFER { long Size; long Used; long Left; char *Data; } BUFFER; /* ** What program to handoff a connection to. */ typedef enum _HANDOFF { HOnnrpd, HOnnrqd, HOnntpd } HANDOFF; /* ** Set of channel types. */ typedef enum _CHANNELTYPE { CTany, CTfree, CTremconn, CTreject, CTnntp, CTlocalconn, CTcontrol, CTfile, CTexploder, CTprocess } CHANNELTYPE; /* ** The state a channel is in. Interpretation of this depends on the ** channel's type. Used mostly by CTnntp channels. */ typedef enum _CHANNELSTATE { CSerror, CSwaiting, CSgetcmd, CSgetauth, CSwritegoodbye, CSwriting, CSpaused, CSgetarticle, CSeatarticle, CSgetrep, CSgetxbatch } CHANNELSTATE; /* ** I/O channel, the heart of the program. A channel has input and output ** buffers, and functions to call when there is input to be read, or when ** all the output was been written. */ typedef struct _CHANNEL { CHANNELTYPE Type; CHANNELSTATE State; BOOL Streaming ; /* had an '/s' on the end of hosts.nntp entry */ int fd; int Reported; long Received; long Refused; long Rejected; int BadWrites; int BadReads; int BlockedWrites; int BadCommands; time_t LastActive; time_t NextLog; INADDR Address; FUNCPTR Reader; FUNCPTR WriteDone; time_t Waketime; time_t Started; FUNCPTR Waker; POINTER Argument; POINTER Event; BUFFER In; BUFFER Out; BOOL Tracing; BUFFER Sendid; int Lastch; int Rest; int SaveUsed; } CHANNEL; /* ** A newsgroup has a name in different formats, and a high-water count, ** also kept in different formats. It also has a list of sites that ** get this group. */ typedef struct _NEWSGROUP { long Start; /* Offset into the active file */ char *Name; char *Dir; /* The name, as a directory */ int NameLength; ARTNUM Last; ARTNUM Filenum; /* File name to use */ int Lastwidth; int PostCount; /* Have we already put it here? */ char *LastString; char *Rest; SITEIDX nSites; int *Sites; SITEIDX nPoison; int *Poison; struct _NEWSGROUP *Alias; } NEWSGROUP; /* ** How a site is fed. */ typedef enum _FEEDTYPE { FTerror, FTfile, FTchannel, FTexploder, FTfunnel, FTlogonly, FTprogram } FEEDTYPE; /* ** A site may reject something in its subscription list if it has ** too many hops, or a bad distribution. */ typedef struct _SITE { char *Name; char *Entry; int NameLength; char **Exclusions; char **Distributions; char **Patterns; BOOL Poison; BOOL PoisonEntry; BOOL Sendit; BOOL Seenit; BOOL DistRequired; BOOL IgnorePath; int Hops; int Groupcount; FEEDTYPE Type; NEWSGROUP *ng; BOOL Spooling; char *SpoolName; BOOL Working; long StartWriting; long StopWriting; long StartSpooling; char *Param; char FileFlags[FEED_MAXFLAGS + 1]; long MaxSize; long MinSize; CHANNEL *Channel; BOOL IsMaster; int Master; int Funnel; BOOL FNLwantsnames; BUFFER FNLnames; int Process; PID_T pid; long Flushpoint; BUFFER Buffer; BOOL Buffered; int Next; int Prev; } SITE; /* ** A process is something we start up to send articles. */ typedef enum _PROCSTATE { PSfree, PSrunning, PSdead } PROCSTATE; /* ** We track our children and collect them synchronously. */ typedef struct _PROCESS { PROCSTATE State; PID_T Pid; int Status; time_t Started; time_t Collected; int Site; } PROCESS; /* ** Miscellaneous data we want to keep on an article. All the fields ** are not always valid. */ typedef struct _ARTDATA { STRING Poster; STRING Replyto; char *Body; time_t Posted; time_t Arrived; time_t Expires; int Groupcount; int LinesValue; char Lines[SMBUF]; long SizeValue; char Size[SMBUF]; int SizeLength; char Name[SPOOLNAMEBUFF]; int NameLength; char TimeReceived[33]; int TimeReceivedLength; STRING MessageID; int MessageIDLength; STRING Newsgroups; int NewsgroupsLength; STRING Distribution; int DistributionLength; STRING Feedsite; int FeedsiteLength; STRING Replic; int ReplicLength; BUFFER *Headers; BUFFER *Overview; } ARTDATA; /* ** In-line macros for efficiency. */ #if defined(lint) || defined(__CENTERLINE__) extern int KeepLintQuiet; #define JUSTONCE KeepLintQuiet #else #define JUSTONCE 0 #endif /* defined(lint) || defined(__CENTERLINE__) */ /* ** Set or append data to a channel's output buffer. */ #define WCHANset(cp, p, l) BUFFset(&(cp)->Out, (p), (l)) #define WCHANappend(cp, p, l) BUFFappend(&(cp)->Out, (p), (l)) /* ** Append data to a buffer. */ #define BUFFappend(bp_parm, p_parm, l_parm) \ do { \ register int l_; \ register BUFFER *bp_; \ int i_; \ \ if ((l_ = l_parm) != 0) { \ bp_ = bp_parm; \ /* Note end of buffer, grow it if we need more room. */ \ i_ = bp_->Used + bp_->Left; \ if (i_ + l_ > bp_->Size) { \ /* Round size up to next 1K. */ \ bp_->Size += (l_ + 0x3FF) & ~0x3FF; \ RENEW(bp_->Data, char, bp_->Size); \ } \ bp_->Left += l_; \ if (l_ > MEMCPY_THRESHOLD) \ (void)memcpy((POINTER)&bp_->Data[i_], (POINTER)p_parm, (SIZE_T)l_); \ else { \ register STRING p_; \ register char *dest_; \ \ for (p_ = p_parm, dest_ = &bp_->Data[i_], l_++; --l_ > 0; ) \ *dest_++ = *p_++; \ } \ } \ } while (JUSTONCE) /* ** Mark that an I/O error occurred, and block if we got too many. */ #define IOError(WHEN, e) \ if (--ErrorCount <= 0 || (e) == ENOSPC) ThrottleIOError(WHEN); else /* ** Global data. ** ** Do not change "extern" to "EXTERN" in the Global data. The ones ** marked with "extern" are initialized in innd.c. The ones marked ** with "EXTERN" are not explicitly initialized in innd.c. */ #if defined(DEFINE_DATA) #define EXTERN /* NULL */ #else #define EXTERN extern #endif /* defined(DEFINE_DATA) */ extern BOOL AmRoot; extern BOOL BufferedLogs; EXTERN BOOL AmSlave; EXTERN BOOL AnyIncoming; extern BOOL Debug; EXTERN BOOL ICDneedsetup; EXTERN BOOL NeedHeaders; EXTERN BOOL NeedOverview; EXTERN BOOL NNRPFollows; extern BOOL NNRPTracing; extern BOOL StreamingOff; extern BOOL Tracing; EXTERN BUFFER Path; EXTERN BUFFER Xref; EXTERN char *ModeReason; /* NNTP reject message */ EXTERN char *NNRPReason; /* NNRP reject message */ EXTERN char *Reservation; /* Reserved lock message */ EXTERN char *RejectReason; /* NNTP reject message */ extern char SPOOL[]; EXTERN char *Version; EXTERN FILE *Errlog; EXTERN FILE *Log; extern char LogName[]; EXTERN INADDR MyAddress; extern int ErrorCount; EXTERN int ICDactivedirty; EXTERN int KillerSignal; extern int MaxIncoming; EXTERN int MaxOutgoing; EXTERN int nGroups; EXTERN SITEIDX nSites; EXTERN int PROCneedscan; extern int SPOOLlen; EXTERN int Xrefbase; extern long LargestArticle; EXTERN NEWSGROUP **GroupPointers; EXTERN NEWSGROUP *Groups; extern OPERATINGMODE Mode; EXTERN SIGVAR GotTerminate; EXTERN SITE *Sites; EXTERN SITE ME; EXTERN struct timeval TimeOut; EXTERN TIMEINFO Now; /* Reasonably accurate time */ extern time_t Cutoff; /* ** Table size for limiting incoming connects. Do not change the table ** size unless you look at the code manipulating it in rc.c. */ #define REMOTETABLESIZE 128 /* ** Setup the default values. The REMOTETIMER being zero turns off the ** code to limit incoming connects. */ #define REMOTELIMIT 2 #define REMOTETIMER 0 #define REMOTETOTAL 60 #define REJECT_TIMEOUT 10 extern int RemoteLimit; /* Per host limit. */ extern time_t RemoteTimer; /* How long to remember connects. */ extern int RemoteTotal; /* Total limit. */ /* ** Function declarations. */ extern BOOL FormatLong(); extern BOOL MakeSpoolDirectory(); extern BOOL NeedShell(); extern char **CommaSplit(); extern char *MaxLength(); extern PID_T Spawn(); extern NORETURN CleanupAndExit(); extern void FileGlue(); extern void JustCleanup(); extern void ThrottleIOError(); extern void ReopenLog(); extern void xchown(); extern BOOL ARTidok(); extern BOOL ARTreadschema(); extern char *ARTreadarticle(); extern char *ARTreadheader(); extern STRING ARTpost(); extern void ARTcancel(); extern void ARTclose(); extern void ARTsetup(); extern void BUFFset(); extern void BUFFswap(); extern BOOL CHANsleeping(); extern CHANNEL *CHANcreate(); extern CHANNEL *CHANiter(); extern CHANNEL *CHANfromdescriptor(); extern char *CHANname(); extern int CHANreadtext(); extern void CHANclose(); extern void CHANreadloop(); extern void CHANsetup(); extern void CHANtracing(); extern void RCHANadd(); extern void RCHANremove(); extern void SCHANadd(); extern void SCHANremove(); extern void SCHANwakeup(); extern BOOL WCHANflush(); extern void WCHANadd(); extern void WCHANfappend(); extern void WCHANremove(); extern void WCHANsetfrombuffer(); extern void CCcopyargv(); extern STRING CCblock(); extern STRING CCcancel(); extern STRING CCcheckfile(); extern BOOL HIShavearticle(); extern BOOL HISwrite(); extern char *HISfilesfor(); extern void HISclose(); extern void HISsetup(); extern void HISsync(); extern BOOL ICDnewgroup(); extern char *ICDreadactive(); extern BOOL ICDchangegroup(); extern void ICDclose(); extern BOOL ICDrenumberactive(); extern BOOL ICDrmgroup(); extern void ICDsetup(); extern void ICDwrite(); extern void ICDwriteactive(); extern void CCclose(); extern void CCsetup(); extern void LCclose(); extern void LCsetup(); extern char **NGsplit(); extern NEWSGROUP *NGfind(); extern CHANNEL *NCcreate(); extern void NGparsefile(); extern BOOL NGrenumber(); extern void NCclose(); extern void NCsetup(); extern int PROCwatch(); extern void PROCunwatch(); /* extern void PROCclose(); */ extern void PROCscan(); extern void PROCsetup(); extern BOOL RCnolimit(); extern BOOL RCauthorized(); extern BOOL RCcanpost(); extern char *RChostname(); extern int RCismaster(); extern void RCclose(); extern void RChandoff(); extern void RCreadlist(); extern void RCsetup(); extern BOOL SITEfunnelpatch(); extern BOOL SITEsetup(); extern BOOL SITEwantsgroup(); extern BOOL SITEpoisongroup(); extern char **SITEreadfile(); extern SITE *SITEfind(); extern SITE *SITEfindnext(); extern STRING SITEparseone(); extern void SITEchanclose(); extern void SITEdrop(); extern void SITEflush(); extern void SITEflushall(); extern void SITEforward(); extern void SITEfree(); extern void SITEinfo(); extern void SITElinkall(); extern void SITEparsefile(); extern void SITEprocdied(); extern void SITEsend(); extern void SITEwrite(); /* ** TCL Globals */ #if defined(DO_TCL) extern Tcl_Interp *TCLInterpreter; extern BOOL TCLFilterActive; extern BUFFER *TCLCurrArticle; extern ARTDATA *TCLCurrData; #endif /* defined(DO_TCL) */ /* ** TCL Functions */ #if defined(DO_TCL) extern void TCLfilter(); extern void TCLreadfilter(); extern void TCLsetup(); extern void TCLclose(); #endif /* defined(DO_TCL) */ inn-1.7.2/innd/chan.c0100644000175100001440000005642606443103542012651 0ustar mdusers/* $Revision: 1.39 $ ** ** I/O channel (and buffer) processing. */ #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" /* Divisor of the BUFFER size. If the amount free at the beginning of the buffer is bigger than the quotient, then it is compacted in the readloop */ #define COMP_THRESHOLD 10 STATIC FDSET RCHANmask; STATIC FDSET SCHANmask; STATIC FDSET WCHANmask; STATIC int SCHANcount; STATIC int CHANlastfd; STATIC int CHANlastsleepfd; STATIC int CHANccfd; STATIC int CHANtablesize; STATIC CHANNEL *CHANtable; STATIC CHANNEL *CHANcc; STATIC CHANNEL CHANnull = { CTfree, CSerror, -1 }; #define PRIORITISE_REMCONN #ifdef PRIORITISE_REMCONN STATIC int CHANrcfd; STATIC CHANNEL *CHANrc; #endif /* PRIORITISE_REMCONN */ /* ** Set a buffer's contents, ignoring anything that might have ** been there. */ void BUFFset(bp, p, length) register BUFFER *bp; register char *p; register int length; { register char *dest; if ((bp->Left = length) != 0) { /* Need more space? */ if (bp->Size < length) { bp->Size = length; RENEW(bp->Data, char, bp->Size); } /* Try to test for non-overlapping copies. */ if (length > MEMCPY_THRESHOLD && (p < bp->Data || p >= &bp->Data[length])) (void)memcpy((POINTER)bp->Data, (POINTER)p, (SIZE_T)length); else { for (dest = bp->Data, length++; --length > 0; ) *dest++ = *p++; } } bp->Used = 0; } /* ** Swap the contents of two buffers. */ void BUFFswap(b1, b2) register BUFFER *b1; register BUFFER *b2; { BUFFER b; b = *b1; *b1 = *b2; *b2 = b; } /* ** Initialize all the I/O channels. */ void CHANsetup(i) register int i; { register CHANNEL *cp; FD_ZERO(&RCHANmask); FD_ZERO(&SCHANmask); FD_ZERO(&WCHANmask); if (CHANtable) DISPOSE(CHANtable); CHANtablesize = i; CHANtable = NEW(CHANNEL, CHANtablesize); (void)memset((POINTER)CHANtable, 0, (SIZE_T)(CHANtablesize * sizeof *CHANtable)); CHANnull.NextLog = CHANNEL_INACTIVE_TIME; CHANnull.Address.s_addr = MyAddress.s_addr; for (cp = CHANtable; --i >= 0; cp++) *cp = CHANnull; } /* ** Create a channel from a descriptor. */ CHANNEL * CHANcreate(fd, Type, State, Reader, WriteDone) int fd; CHANNELTYPE Type; CHANNELSTATE State; FUNCPTR Reader; FUNCPTR WriteDone; { register CHANNEL *cp; BUFFER in; BUFFER out; cp = &CHANtable[fd]; /* Don't overwrite the buffers with CHANnull. */ in = cp->In; if (in.Size == 0) { in.Size = START_BUFF_SIZE; in.Data = NEW(char, in.Size); } in.Used = 0; in.Left = in.Size; out = cp->Out; if (out.Size == 0) { out.Size = SMBUF; out.Data = NEW(char, out.Size); } out.Used = 0; out.Left = 0; /* Set up the channel's info. */ *cp = CHANnull; cp->fd = fd; cp->Type = Type; cp->State = State; cp->Streaming = FALSE ; cp->Reader = Reader; cp->WriteDone = WriteDone; cp->Started = cp->LastActive = Now.time; cp->In = in; cp->Out = out; cp->Tracing = Tracing; cp->Sendid.Size=0; cp->Rest=0; cp->SaveUsed=0; cp->Lastch=0; /* Make the descriptor close-on-exec and non-blocking. */ CloseOnExec(fd, TRUE); if (SetNonBlocking(fd, TRUE) < 0 #if defined(ENOTSOCK) && errno != ENOTSOCK #endif /* defined(ENOTSOCK) */ #if defined(ENOTTY) && errno != ENOTTY #endif /* defined(ENOTTY) */ ) syslog(L_ERROR, "%s cant nonblock %d %m", LogName, fd); /* Note control channel, for efficiency. */ if (Type == CTcontrol) { CHANcc = cp; CHANccfd = fd; } #ifdef PRIORITISE_REMCONN /* Note remconn channel, for efficiency */ if (Type == CTremconn) { CHANrc = cp; CHANrcfd = fd; } #endif /* PRIORITISE_REMCONN */ return cp; } /* ** Start tracing a channel. */ void CHANtracing(cp, Flag) register CHANNEL *cp; BOOL Flag; { char *p; p = CHANname(cp); syslog(L_NOTICE, "%s trace %s", p, Flag ? "on" : "off"); cp->Tracing = Flag; if (Flag) { syslog(L_NOTICE, "%s trace badwrites %d blockwrites %d badreads %d", p, cp->BadWrites, cp->BlockedWrites, cp->BadReads); syslog(L_NOTICE, "%s trace address %s lastactive %ld nextlog %ld", p, inet_ntoa(cp->Address), cp->LastActive, cp->NextLog); if (FD_ISSET(cp->fd, &SCHANmask)) syslog(L_NOTICE, "%s trace sleeping %ld 0x%x", p, (long)cp->Waketime, cp->Waker); if (FD_ISSET(cp->fd, &RCHANmask)) syslog(L_NOTICE, "%s trace reading %d %s", p, cp->In.Used, MaxLength(cp->In.Data, cp->In.Data)); if (FD_ISSET(cp->fd, &WCHANmask)) syslog(L_NOTICE, "%s trace writing %d %s", p, cp->Out.Left, MaxLength(cp->Out.Data, cp->Out.Data)); } } /* ** Close a channel. */ void CHANclose(cp, name) register CHANNEL *cp; char *name; { if (cp->Type == CTfree) syslog(L_ERROR, "%s internal closing free channel %d", name, cp->fd); else { if (cp->Type == CTnntp) syslog(L_NOTICE, "%s closed seconds %ld accepted %ld refused %ld rejected %ld", name, (long)(Now.time - cp->Started), cp->Received, cp->Refused, cp->Rejected); else if (cp->Type == CTreject) syslog(L_NOTICE, "%s %ld", name, cp->Rejected); else if (cp->Out.Left) syslog(L_NOTICE, "%s closed lost %d", name, cp->Out.Left); else syslog(L_NOTICE, "%s closed", name); WCHANremove(cp); RCHANremove(cp); SCHANremove(cp); if (cp->Argument != NULL) /* Set to NULL below. */ DISPOSE(cp->Argument); if (cp->fd >= 0 && close(cp->fd) < 0) syslog(L_ERROR, "%s cant close %s %m", LogName, name); } /* Mark it unused. */ cp->Type = CTfree; cp->State = CSerror; cp->fd = -1; cp->Argument = NULL; /* Free the buffers if they got big. */ if (cp->In.Size > BIG_BUFFER) { cp->In.Size = 0; DISPOSE(cp->In.Data); } if (cp->Out.Size > BIG_BUFFER) { cp->Out.Size = 0; DISPOSE(cp->Out.Data); } if (cp->Sendid.Size) { cp->Sendid.Size = 0; DISPOSE(cp->Sendid.Data); } } /* ** Return a printable name for the channel. */ char * CHANname(cp) register CHANNEL *cp; { static char buff[SMBUF]; register int i; register SITE *sp; STRING p; PID_T pid; switch (cp->Type) { default: (void)sprintf(buff, "?%d(#%d@%d)?", cp->Type, cp->fd, cp - CHANtable); break; case CTany: (void)sprintf(buff, "any:%d", cp->fd); break; case CTfree: (void)sprintf(buff, "free:%d", cp->fd); break; case CTremconn: (void)sprintf(buff, "remconn:%d", cp->fd); break; case CTreject: (void)sprintf(buff, "%s rejected", RChostname(cp)); break; case CTnntp: (void)sprintf(buff, "%s:%d", cp->Address.s_addr == 0 ? "localhost" : RChostname(cp), cp->fd); break; case CTlocalconn: (void)sprintf(buff, "localconn:%d", cp->fd); break; case CTcontrol: (void)sprintf(buff, "control:%d", cp->fd); break; case CTexploder: case CTfile: case CTprocess: /* Find the site that has this channel. */ for (p = "?", i = nSites, sp = Sites, pid = 0; --i >= 0; sp++) if (sp->Channel == cp) { p = sp->Name; if (cp->Type != CTfile) pid = sp->pid; break; } if (pid == 0) (void)sprintf(buff, "%s:%d:%s", MaxLength(p, p), cp->fd, cp->Type == CTfile ? "file" : "proc"); else (void)sprintf(buff, "%s:%d:%s:%ld", MaxLength(p, p), cp->fd, cp->Type == CTfile ? "file" : "proc", (long)pid); break; } return buff; } /* ** Return the channel for a specified descriptor. */ CHANNEL * CHANfromdescriptor(fd) int fd; { if (fd <0 || fd > CHANtablesize) return NULL; return &CHANtable[fd]; } /* ** Iterate over all channels of a specified type. */ CHANNEL * CHANiter(ip, Type) int *ip; CHANNELTYPE Type; { register CHANNEL *cp; register int i; if ((i = *ip) >= 0 && i < CHANtablesize) { do { cp = &CHANtable[i]; if (cp->Type == CTfree && cp->fd == -1) continue; if (Type == CTany || cp->Type == Type) { *ip = ++i; return cp; } } while (++i < CHANtablesize); } return NULL; } /* ** Mark a channel as an active reader. */ void RCHANadd(cp) register CHANNEL *cp; { FD_SET(cp->fd, &RCHANmask); if (cp->fd > CHANlastfd) CHANlastfd = cp->fd; /* Start reading at the beginning of the buffer. */ cp->In.Used = 0; } /* ** Remove a channel from the set of readers. */ void RCHANremove(cp) register CHANNEL *cp; { if (FD_ISSET(cp->fd, &RCHANmask)) { FD_CLR(cp->fd, &RCHANmask); if (cp->fd == CHANlastfd) { /* This was the highest descriptor, get a new highest. */ while (!FD_ISSET(CHANlastfd, &RCHANmask) && !FD_ISSET(CHANlastfd, &WCHANmask) && CHANlastfd > 1) CHANlastfd--; } } } /* ** Put a channel to sleep, call a function when it wakes. ** Note that the Argument must be NULL or allocated memory! */ void SCHANadd(cp, Waketime, Event, Waker, Argument) register CHANNEL *cp; time_t Waketime; POINTER Event; FUNCPTR Waker; POINTER Argument; { if (!FD_ISSET(cp->fd, &SCHANmask)) { SCHANcount++; FD_SET(cp->fd, &SCHANmask); } if (cp->fd > CHANlastsleepfd) CHANlastsleepfd = cp->fd; cp->Waketime = Waketime; cp->Waker = Waker; if (cp->Argument != Argument) { DISPOSE(cp->Argument); cp->Argument = Argument; } cp->Event = Event; } /* ** Take a channel off the sleep list. */ void SCHANremove(cp) register CHANNEL *cp; { if (FD_ISSET(cp->fd, &SCHANmask)) { FD_CLR(cp->fd, &SCHANmask); SCHANcount--; cp->Waketime = 0; if (cp->fd == CHANlastsleepfd) { /* This was the highest descriptor, get a new highest. */ while (!FD_ISSET(CHANlastsleepfd, &SCHANmask) && CHANlastsleepfd > 1) CHANlastsleepfd--; } } } /* ** Is a channel on the sleep list? */ BOOL CHANsleeping(cp) CHANNEL *cp; { return FD_ISSET(cp->fd, &SCHANmask); } /* ** Wake up channels waiting for a specific event. */ void SCHANwakeup(Event) register POINTER Event; { register CHANNEL *cp; register int i; for (cp = CHANtable, i = CHANtablesize; --i >= 0; cp++) if (cp->Type != CTfree && cp->Event == Event && CHANsleeping(cp)) cp->Waketime = 0; } /* ** Mark a channel as an active writer. Don't reset the Out->Left field ** since we could have buffered I/O already in there. */ void WCHANadd(cp) register CHANNEL *cp; { if (cp->Out.Left > 0) { FD_SET(cp->fd, &WCHANmask); if (cp->fd > CHANlastfd) CHANlastfd = cp->fd; } } /* ** Remove a channel from the set of writers. */ void WCHANremove(cp) register CHANNEL *cp; { if (FD_ISSET(cp->fd, &WCHANmask)) { FD_CLR(cp->fd, &WCHANmask); if (cp->Out.Left <= 0) { /* No data left -- reset used so we don't grow the buffer. */ cp->Out.Used = 0; cp->Out.Left = 0; } if (cp->fd == CHANlastfd) { /* This was the highest descriptor, get a new highest. */ while (!FD_ISSET(CHANlastfd, &RCHANmask) && !FD_ISSET(CHANlastfd, &WCHANmask) && CHANlastfd > 1) CHANlastfd--; } } } /* ** Set a channel to start off with the contents of an existing channel. */ void WCHANsetfrombuffer(cp, bp) CHANNEL *cp; BUFFER *bp; { WCHANset(cp, &bp->Data[bp->Used], bp->Left); } /* ** Read in text data, return the amount we read. */ int CHANreadtext(cp) register CHANNEL *cp; { register int i; register BUFFER *bp; char *p; int oerrno; /* Grow buffer if we're getting close to current limit. */ bp = &cp->In; if (bp->Left <= LOW_WATER) { i = GROW_AMOUNT(bp->Size); bp->Size += i; bp->Left += i; RENEW(bp->Data, char, bp->Size); } /* Read in whatever is there, up to some reasonable limit. */ /* * XXX We really want to limit the amount of time it takes to * process the incoming data for this channel. But there's * no easy way of doing that, so we restrict the data size instead. * If the data is part of a single large article, then reading * and processing many kilobytes at a time costs very little. * If the data is a long list of CHECK commands from a streaming * feed, then every line of data will require a history lookup, and * we probably don't want to do more than about 10 of those per * channel on each cycle of the main select() loop (otherwise we * might take too long before giving other channels a turn). 10 * lines of CHECK commands suggests a limit of about 1 kilobyte of * data, or less. BUFSIZ is often about 1 kilobyte, and is * attractive for other reasons, so let's use that as our size limit. */ bp->Left = bp->Size - bp->Used; i = read(cp->fd, &bp->Data[bp->Used], (bp->Left - 1 > BUFSIZ ? BUFSIZ : bp->Left - 1)); if (i < 0) { #ifdef POLL_BUG /* return of -2 indicates EAGAIN, for SUNOS5.4 poll() bug workaround */ if (errno == EAGAIN) { return -2; } #endif oerrno = errno; p = CHANname(cp); errno = oerrno; syslog(L_ERROR, "%s cant read %m", p); return -1; } if (i == 0) { p = CHANname(cp); syslog(L_NOTICE, "%s readclose", p); return 0; } bp->Used += i; bp->Left -= i; return i; } /* ** If I/O backs up a lot, we can get EMSGSIZE on some systems. If that ** happens we want to do the I/O in chunks. We assume stdio's BUFSIZ is ** a good chunk value. */ STATIC int largewrite(fd, p, length) register int fd; register char *p; register int length; { register int i; register char *save; do { /* Try the standard case -- write it all. */ i = write(fd, (POINTER)p, (SIZE_T)length); if (i > 0 || (i < 0 && errno != EMSGSIZE && errno != EINTR)) return i; } while (i < 0 && errno == EINTR); /* Write it in pieces. */ for (save = p, i = 0; length; p += i, length -= i) { i = write(fd, (POINTER)p, (SIZE_T)(length > BUFSIZ ? BUFSIZ : length)); if (i <= 0) break; } /* Return error, or partial results if we got something. */ return p == save ? i : p - save; } /* ** Try to flush out the buffer. Use this only on file channels! */ BOOL WCHANflush(cp) register CHANNEL *cp; { register BUFFER *bp; register int i; /* Write it. */ for (bp = &cp->Out; bp->Left > 0; bp->Left -= i, bp->Used += i) { i = largewrite(cp->fd, &bp->Data[bp->Used], bp->Left); if (i < 0) { syslog(L_ERROR, "%s cant flush count %d %m", CHANname(cp), bp->Left); return FALSE; } if (i == 0) { syslog(L_ERROR, "%s cant flush count %d", CHANname(cp), bp->Left); return FALSE; } } WCHANremove(cp); return TRUE; } /* ** Wakeup routine called after a write channel was put to sleep. */ STATIC FUNCTYPE CHANwakeup(cp) CHANNEL *cp; { syslog(L_NOTICE, "%s wakeup", CHANname(cp)); WCHANadd(cp); } /* ** Attempting to write would block; stop output or give up. */ STATIC void CHANwritesleep(cp, p) register CHANNEL *cp; char *p; { int i; if ((i = ++(cp->BlockedWrites)) > BAD_IO_COUNT) switch (cp->Type) { default: break; case CTreject: case CTnntp: case CTfile: case CTexploder: case CTprocess: syslog(L_ERROR, "%s blocked closing", p); SITEchanclose(cp); CHANclose(cp, p); return; } i *= BLOCK_BACKOFF; syslog(L_ERROR, "%s blocked sleeping %d", p, i); SCHANadd(cp, (time_t)(Now.time + i), (POINTER)NULL, CHANwakeup, (POINTER)NULL); } #if defined(INND_FIND_BAD_FDS) /* ** We got an unknown error in select. Find out the culprit. ** Not really ready for production use yet, and it's expensive, too. */ STATIC void CHANdiagnose() { FDSET Test; int i; struct timeval t; FD_ZERO(&Test); for (i = CHANlastfd; i >= 0; i--) { if (FD_ISSET(i, &RCHANmask)) { FD_SET(i, &Test); t.tv_sec = 0; t.tv_usec = 0; if (select(i + 1, &Test, (FDSET *)NULL, (FDSET *)NULL, &t) < 0 && errno != EINTR) { syslog(L_ERROR, "%s Bad Read File %d", LogName, i); FD_CLR(i, &RCHANmask); /* Probably do something about the file descriptor here; call * CHANclose on it? */ } FD_CLR(i, &Test); } if (FD_ISSET(i, &WCHANmask)) { FD_SET(i, &Test); t.tv_sec = 0; t.tv_usec = 0; if (select(i + 1, (FDSET *)NULL, &Test, (FDSET *)NULL, &t) < 0 && errno != EINTR) { syslog(L_ERROR, "%s Bad Write File %d", LogName, i); FD_CLR(i, &WCHANmask); /* Probably do something about the file descriptor here; call * CHANclose on it? */ } FD_CLR(i, &Test); } } } #endif /* defined(INND_FIND_BAD_FDS) */ /* ** Main I/O loop. Wait for data, call the channel's handler when there is ** something to read or when the queued write is finished. In order to ** be fair (i.e., don't always give descriptor n priority over n+1), we ** remember where we last had something and pick up from there. ** ** Yes, the main code has really wandered over to the side a lot. */ void CHANreadloop() { static char EXITING[] = "INND exiting because of signal\n"; static int fd; register int i; register int startpoint; register int count; register int lastfd; int oerrno; register CHANNEL *cp; register BUFFER *bp; FDSET MyRead; FDSET MyWrite; struct timeval MyTime; long silence; char *p; time_t LastUpdate; LastUpdate = GetTimeInfo(&Now) < 0 ? 0 : Now.time; for ( ; ; ) { /* See if any processes died. */ PROCscan(); /* Wait for data, note the time. */ MyRead = RCHANmask; MyWrite = WCHANmask; MyTime = TimeOut; count = select(CHANlastfd + 1, &MyRead, &MyWrite, (FDSET *)NULL, &MyTime); if (GotTerminate) { (void)write(2, EXITING, STRLEN(EXITING)); CleanupAndExit(0, (char *)NULL); } if (count < 0) { if (errno != EINTR) { syslog(L_ERROR, "%s cant select %m", LogName); #if defined(INND_FIND_BAD_FDS) CHANdiagnose(); #endif /* defined(INND_FIND_BAD_FDS) */ } continue; } /* Update the "reasonably accurate" time. */ if (GetTimeInfo(&Now) < 0) syslog(L_ERROR, "%s cant gettimeinfo %m", LogName); if (Now.time > LastUpdate + TimeOut.tv_sec) { HISsync(); if (ICDactivedirty) { ICDwriteactive(); ICDactivedirty = 0; } LastUpdate = Now.time; } if (count == 0) { /* No channels active, so flush and skip if nobody's * sleeping. */ if (Mode == OMrunning) ICDwrite(); if (SCHANcount == 0) continue; } /* Try the control channel first. */ if (FD_ISSET(CHANccfd, &RCHANmask) && FD_ISSET(CHANccfd, &MyRead)) { count--; if (count > 3) count = 3; /* might be more requests */ (*CHANcc->Reader)(CHANcc); FD_CLR(CHANccfd, &MyRead); } #ifdef PRIORITISE_REMCONN /* Try the remconn channel next. */ if (FD_ISSET(CHANrcfd, &RCHANmask) && FD_ISSET(CHANrcfd, &MyRead)) { count--; if (count > 3) count = 3; /* might be more requests */ (*CHANrc->Reader)(CHANrc); FD_CLR(CHANrcfd, &MyRead); } #endif /* PRIORITISE_REMCONN */ /* Loop through all active channels. Somebody could have closed * closed a channel so we double-check the global mask before * looking at what select returned. The code here is written so * that a channel could be reading and writing and sleeping at the * same time, even though that's not possible. (Just as well, * since in SysVr4 the count would be wrong.) */ lastfd = CHANlastfd; if (lastfd < CHANlastsleepfd) lastfd = CHANlastsleepfd; if (fd > lastfd) fd = 0; startpoint = fd; do { cp = &CHANtable[fd]; /* Anything to read? */ if (FD_ISSET(fd, &RCHANmask) && FD_ISSET(fd, &MyRead)) { count--; if (cp->Type == CTfree) { syslog(L_ERROR, "%s %d free but was in RMASK", CHANname(cp), fd); /* Don't call RCHANremove since cp->fd will be -1. */ FD_CLR(fd, &RCHANmask); (void)close(fd); } else { cp->LastActive = Now.time; (*cp->Reader)(cp); } } #define MAX(a,b) ((a) > (b) ? (a) : (b)) /* Check and see if the buffer is grossly overallocated and shrink if needed */ if (cp->In.Size > (START_BUFF_SIZE * 4)) { if (cp->In.Used) { if ((cp->In.Size / cp->In.Used) > 10) { cp->In.Size = MAX(cp->In.Used * 2, START_BUFF_SIZE); cp->In.Data = RENEW(cp->In.Data, char, cp->In.Size); cp->In.Left = cp->In.Size - cp->In.Used; } } else { cp->In.Data = RENEW(cp->In.Data, char, START_BUFF_SIZE); cp->In.Size = cp->In.Left = START_BUFF_SIZE; } } /* Possibly recheck for dead children so we don't get SIGPIPE * on readerless channels. */ if (PROCneedscan) PROCscan(); /* Ready to write? */ if (FD_ISSET(fd, &WCHANmask) && FD_ISSET(fd, &MyWrite)) { count--; if (cp->Type == CTfree) { syslog(L_ERROR, "%s %d free but was in WMASK", CHANname(cp), fd); /* Don't call WCHANremove since cp->fd will be -1. */ FD_CLR(fd, &WCHANmask); (void)close(fd); } else { bp = &cp->Out; if (bp->Left) { cp->LastActive = Now.time; i = largewrite(fd, &bp->Data[bp->Used], bp->Left); if (i <= 0) { oerrno = errno; p = CHANname(cp); errno = oerrno; if (i < 0) syslog(L_ERROR, "%s cant write %m", p); else syslog(L_ERROR, "%s cant write", p); cp->BadWrites++; if (i < 0 && oerrno == EPIPE) { SITEchanclose(cp); CHANclose(cp, p); } else if (i < 0 && oerrno == EWOULDBLOCK) { WCHANremove(cp); CHANwritesleep(cp, p); } else if (cp->BadWrites >= BAD_IO_COUNT) { syslog(L_ERROR, "%s sleeping", p); WCHANremove(cp); SCHANadd(cp, (time_t)(Now.time + PAUSE_RETRY_TIME), (POINTER)NULL, CHANwakeup, (POINTER)NULL); } } else { cp->BadWrites = 0; cp->BlockedWrites = 0; bp->Left -= i; bp->Used += i; if (bp->Left <= 0) { WCHANremove(cp); (*cp->WriteDone)(cp); } else if (bp->Used > (bp->Size/COMP_THRESHOLD)) { /* compact the buffer, shoving the data back to the beginning. */ BUFFset(bp, &bp->Data[bp->Used], bp->Left); } } } else /* Should not be possible. */ WCHANremove(cp); } } /* Coming off a sleep? */ if (FD_ISSET(fd, &SCHANmask) && cp->Waketime <= Now.time) { if (cp->Type == CTfree) { syslog(L_ERROR,"%s ERROR s-select free %d",CHANname(cp),fd); FD_CLR(fd, &SCHANmask); (void) close(fd); } else { cp->LastActive = Now.time; SCHANremove(cp); (*cp->Waker)(cp); } } /* Toss CTreject channel early if it's inactive. */ if (cp->Type == CTreject && cp->LastActive + REJECT_TIMEOUT < Now.time) { p = CHANname(cp); syslog(L_NOTICE, "%s timeout reject", p); CHANclose(cp, p); } /* Has this channel been inactive very long? */ if (cp->Type == CTnntp && cp->LastActive + cp->NextLog < Now.time) { p = CHANname(cp); silence = Now.time - cp->LastActive; cp->NextLog += CHANNEL_INACTIVE_TIME; syslog(L_NOTICE, "%s inactive %ld", p, silence / 60L); if (silence > PEER_TIMEOUT) { syslog(L_NOTICE, "%s timeout", p); CHANclose(cp, p); } } /* Bump pointer, modulo the table size. */ if (fd >= lastfd) fd = 0; else fd++; /* If there is nothing to do, break out. */ if (count == 0 && SCHANcount == 0) break; } while (fd != startpoint); } } inn-1.7.2/innd/art.h0100644000175100001440000000152006443103542012514 0ustar mdusers/* $Revision: 1.1 $ ** ** Net News Reading Protocol server. */ /* ** Header types. */ typedef enum _ARTHEADERTYPE { HTreq, /* Drop article if this is missing */ HTobs, /* Delete this header if found */ HTstd /* Standard optional header */ } ARTHEADERTYPE; /* ** Entry in the header table. */ typedef struct _ARTHEADER { STRING Name; ARTHEADERTYPE Type; int Size; /* Length of Name */ char *Value; int Length; /* Length of Value */ int Found; BOOL Allocated; } ARTHEADER; /* ** A way to index into the header table. */ #define HDR(_x) (ARTheaders[(_x)].Value) inn-1.7.2/innd/art.c0100644000175100001440000016264406443103542012526 0ustar mdusers/* $Revision: 1.68 $ ** ** Article-processing. */ #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" #include "dbz.h" #include "art.h" #include typedef struct iovec IOVEC; extern BOOL DoLinks; extern BOOL DoCancels; #if defined(S_IXUSR) #define EXECUTE_BITS (S_IXUSR | S_IXGRP | S_IXOTH) #else #define EXECUTE_BITS 0111 #endif /* defined(S_IXUSR) */ /* ** Mark that the site gets this article. */ #define SITEmark(sp_, ngp_) \ do { \ SITE *funnel; \ \ sp_->Sendit = TRUE; \ if (sp_->ng == NULL) \ sp_->ng = ngp_; \ if (sp_->Funnel != NOSITE) { \ funnel = &Sites[sp_->Funnel]; \ if (funnel->ng == NULL) \ funnel->ng = ngp_; \ } \ } while (JUSTONCE) /* ** For speed we build a binary tree of the headers, sorted by their ** name. We also store the header's Name fields in the tree to avoid ** doing an extra indirection. */ typedef struct _TREE { STRING Name; ARTHEADER *Header; struct _TREE *Before; struct _TREE *After; } TREE; STATIC TREE *ARTheadertree; /* ** For doing the overview database, we keep a list of the headers and ** a flag saying if they're written in brief or full format. */ typedef struct _ARTOVERFIELD { ARTHEADER *Header; BOOL NeedHeader; } ARTOVERFIELD; STATIC ARTOVERFIELD *ARTfields; /* ** General newsgroup we care about, and what we put in the Path line. */ STATIC char ARTctl[] = "control"; STATIC char ARTjnk[] = "junk"; STATIC char *ARTpathme; /* ** Flag array, indexed by character. Character classes for Message-ID's. */ STATIC char ARTcclass[256]; #define CC_MSGID_ATOM 01 #define CC_MSGID_NORM 02 #define CC_HOSTNAME 04 #define ARTnormchar(c) ((ARTcclass[(unsigned char)(c)] & CC_MSGID_NORM) != 0) #define ARTatomchar(c) ((ARTcclass[(unsigned char)(c)] & CC_MSGID_ATOM) != 0) #define ARThostchar(c) ((ARTcclass[(unsigned char)(c)] & CC_HOSTNAME) != 0) /* ** The header table. Not necessarily sorted, but the first character ** must be uppercase. */ ARTHEADER ARTheaders[] = { /* Name Type ... */ { "Approved", HTstd }, #define _approved 0 { "Control", HTstd }, #define _control 1 { "Date", HTreq }, #define _date 2 { "Distribution", HTstd }, #define _distribution 3 { "Expires", HTstd }, #define _expires 4 { "From", HTreq }, #define _from 5 { "Lines", HTstd }, #define _lines 6 { "Message-ID", HTreq }, #define _message_id 7 { "Newsgroups", HTreq }, #define _newsgroups 8 { "Path", HTreq }, #define _path 9 { "Reply-To", HTstd }, #define _reply_to 10 { "Sender", HTstd }, #define _sender 11 { "Subject", HTreq }, #define _subject 12 { "Supersedes", HTstd }, #define _supersedes 13 { "Bytes", HTstd }, #define _bytes 14 { "Also-Control", HTstd }, #define _alsocontrol 15 { "References", HTstd }, #define _references 16 { "Xref", HTobs }, #define _xref 17 { "Keywords", HTstd }, #define _keywords 18 { "Date-Received", HTobs }, { "Posted", HTobs }, { "Posting-Version", HTobs }, { "Received", HTobs }, { "Relay-Version", HTobs }, }; ARTHEADER *ARTheadersENDOF = ENDOF(ARTheaders); const char *pathForPerl ; /* ** */ BOOL ARTreadschema() { static char SCHEMA[] = _PATH_SCHEMA; register FILE *F; register int i; register char *p; register ARTOVERFIELD *fp; register ARTHEADER *hp; BOOL ok; char buff[SMBUF]; if (ARTfields != NULL) { DISPOSE(ARTfields); ARTfields = NULL; } /* Open file, count lines. */ if ((F = fopen(SCHEMA, "r")) == NULL) return FALSE; for (i = 0; fgets(buff, sizeof buff, F) != NULL; i++) continue; (void)fseek(F, (OFFSET_T)0, SEEK_SET); ARTfields = NEW(ARTOVERFIELD, i + 1); /* Parse each field. */ for (ok = TRUE, fp = ARTfields; fgets(buff, sizeof buff, F) != NULL; ) { /* Ignore blank and comment lines. */ if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; if ((p = strchr(buff, COMMENT_CHAR)) != NULL) *p = '\0'; if (buff[0] == '\0') continue; if ((p = strchr(buff, ':')) != NULL) { *p++ = '\0'; fp->NeedHeader = EQ(p, "full"); } else fp->NeedHeader = FALSE; for (hp = ARTheaders; hp < ENDOF(ARTheaders); hp++) if (EQ(buff, hp->Name)) { fp->Header = hp; break; } if (hp == ENDOF(ARTheaders)) { syslog(L_ERROR, "%s bad_schema unknown header \"%s\"", LogName, buff); ok = FALSE; continue; } fp++; } fp->Header = NULL; (void)fclose(F); return ok; } /* ** Build a balanced tree for the headers in subscript range [lo..hi). ** This only gets called once, and the tree only has about 20 entries, ** so we don't bother to unroll the recursion. */ static TREE * ARTbuildtree(Table, lo, hi) ARTHEADER **Table; int lo; int hi; { int mid; TREE *tp; mid = lo + (hi - lo) / 2; tp = NEW(TREE, 1); tp->Header = Table[mid]; tp->Name = tp->Header->Name; if (mid == lo) tp->Before = NULL; else tp->Before = ARTbuildtree(Table, lo, mid); if (mid == hi - 1) tp->After = NULL; else tp->After = ARTbuildtree(Table, mid + 1, hi); return tp; } /* ** Sorting predicate for qsort call in ARTsetup. */ STATIC int ARTcompare(p1, p2) CPOINTER p1; CPOINTER p2; { ARTHEADER **h1; ARTHEADER **h2; h1 = CAST(ARTHEADER**, p1); h2 = CAST(ARTHEADER**, p2); return strcasecmp(h1[0]->Name, h2[0]->Name); } /* ** Setup the article processing. */ void ARTsetup() { register STRING p; register ARTHEADER *hp; ARTHEADER **table; register int i; /* Set up the character class tables. These are written a * little strangely to work around a GCC2.0 bug. */ (void)memset((POINTER)ARTcclass, 0, sizeof ARTcclass); p = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; while ((i = *p++) != 0) { ARTcclass[i] = CC_HOSTNAME | CC_MSGID_ATOM | CC_MSGID_NORM; } p = "!#$%&'*+-/=?^_`{|}~"; while ((i = *p++) != 0) { ARTcclass[i] = CC_MSGID_ATOM | CC_MSGID_NORM; } p = "\"(),.:;<@[\\]"; while ((i = *p++) != 0) { ARTcclass[i] = CC_MSGID_NORM; } /* The RFC's don't require it, but we add underscore to the list of valid * hostname characters. */ ARTcclass['.'] |= CC_HOSTNAME; ARTcclass['-'] |= CC_HOSTNAME; ARTcclass['_'] |= CC_HOSTNAME; /* Allocate space in the header table. */ for (hp = ARTheaders; hp < ENDOF(ARTheaders); hp++) { hp->Size = strlen(hp->Name); hp->Allocated = hp->Value == NULL && hp->Type != HTobs && hp != &ARTheaders[_bytes]; if (hp->Allocated) hp->Value = NEW(char, MAXHEADERSIZE + 1); } /* Build the header tree. */ table = NEW(ARTHEADER*, SIZEOF(ARTheaders)); for (i = 0; i < SIZEOF(ARTheaders); i++) table[i] = &ARTheaders[i]; qsort((POINTER)table, SIZEOF(ARTheaders), sizeof *table, ARTcompare); ARTheadertree = ARTbuildtree(table, 0, SIZEOF(ARTheaders)); DISPOSE(table); /* Get our Path name, kill trailing !. */ ARTpathme = COPY(Path.Data); ARTpathme[Path.Used - 1] = '\0'; /* Set up database; ignore errors. */ (void)ARTreadschema(); } STATIC void ARTfreetree(tp) TREE *tp; { TREE *next; for ( ; tp != NULL; tp = next) { if (tp->Before) ARTfreetree(tp->Before); next = tp->After; DISPOSE(tp); } } void ARTclose() { register ARTHEADER *hp; /* Free space in the header table. */ for (hp = ARTheaders; hp < ENDOF(ARTheaders); hp++) if (hp->Allocated) DISPOSE(hp->Value); if (ARTfields != NULL) { DISPOSE(ARTfields); ARTfields = NULL; } ARTfreetree(ARTheadertree); } /* ** Read in a file, return a pointer to static space that is reused. */ STATIC char * ARTreadfile(name) char *name; { static BUFFER File; struct stat Sb; int fd; int oerrno; /* Open the file, get its size. */ if ((fd = open(name, O_RDONLY)) < 0) return NULL; if (fstat(fd, &Sb) < 0) { oerrno = errno; (void)close(fd); errno = oerrno; return NULL; } /* Make sure we have enough space. */ if (File.Size == 0) { File.Size = Sb.st_size; File.Data = NEW(char, File.Size + 1); } else if (File.Size <= Sb.st_size) { File.Size = Sb.st_size + 16; RENEW(File.Data, char, File.Size + 1); } /* Read in the file. */ if (xread(fd, File.Data, Sb.st_size) < 0) { oerrno = errno; (void)close(fd); errno = oerrno; return NULL; } /* Clean up and return the data. */ File.Data[Sb.st_size] = '\0'; (void)close(fd); return File.Data; } /* ** Open the article file and return a copy of it. The files parameter is ** actually a whitespace-separated list of names. */ char * ARTreadarticle(files) register char *files; { register char *p; register BOOL more; char *art; if (files == NULL) return NULL; /* Loop over all filenames until we can open one. */ for ( ; *files; files = p + 1) { /* Snip off next name, turn dots to slashes. */ for (p = files; ISWHITE(*p); p++) continue; for (files = p; *p && *p != ' '; p++) if (*p == '.') *p = '/'; more = *p == ' '; if (more) *p = '\0'; art = ARTreadfile(files); if (more) *p = ' '; if (art != NULL) return art; if (!more) break; } return NULL; } /* ** Open the article file and return a copy of the headers. */ char * ARTreadheader(files) char *files; { register char *p; register char *head; if ((head = ARTreadarticle(files)) == NULL) return NULL; /* Find \n\n which means the end of the header. */ for (p = head; (p = strchr(p, '\n')) != NULL; p++) if (p[1] == '\n') { p[1] = '\0'; return head; } syslog(L_NOTICE, "%s bad_article %s is all headers", LogName, files); DISPOSE(head); return NULL; } /* ** Parse a Path line, splitting it up into NULL-terminated array of strings. ** The argument is modified! */ STATIC char ** ARTparsepath(p, countp) register char *p; int *countp; { static char *NULLPATH[1] = { NULL }; static int oldlength; static char **hosts; register int i; register char **hp; /* We can be called with a non-existant or empty path. */ if (p == NULL || *p == '\0') { *countp = 0; return NULLPATH; } /* Get an array of character pointers. */ i = strlen(p); if (hosts == NULL) { oldlength = i; hosts = NEW(char*, oldlength + 1); } else if (oldlength <= i) { oldlength = i; RENEW(hosts, char*, oldlength + 1); } /* Loop over text. */ for (hp = hosts; *p; *p++ = '\0') { /* Skip leading separators. */ for (; *p && !ARThostchar(*p); p++) continue; if (*p == '\0') break; /* Mark the start of the host, move to the end of it. */ for (*hp++ = p; *p && ARThostchar(*p); p++) continue; if (*p == '\0') break; } *hp = NULL; *countp = hp - hosts; return hosts; } /* ** Write an article using writev. The article is split into pieces, ** shown below separated by pipe signs. The items in square brackets are ** "inserted" by this routine. ** |headers... ** Path: |[Path.Data]|rest of path... ** headers... ** |[Lines header, if needed]| ** |[Xref header]| ** ** Article body. ** Also, the Data->Size field is filled in. */ STATIC int ARTwrite(name, Article, Data) char *name; BUFFER *Article; ARTDATA *Data; { static char WHEN[] = "article"; static char NL[] = "\n"; static BUFFER Headers; register int fd; register IOVEC *vp; register long size; register char *p; IOVEC iov[7]; IOVEC *end; char bytesbuff[SMBUF]; int i; if ((p = HeaderFind(Article->Data, "Path", 4)) == NULL || p == Article->Data) { /* This should not happen. */ syslog(L_ERROR, "%s internal %s no Path header", Data->MessageID, LogName); return -1; } /* Open the file. */ if ((fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, ARTFILE_MODE)) < 0) { if (errno != ENOENT) IOError(WHEN, errno); return -1; } /* Set up the scatter/gather vectors. */ vp = iov; size = 0; vp->iov_base = Article->Data; vp->iov_len = p - Article->Data; size += (vp++)->iov_len; /* Do not append the same path twice */ if (strncmp(Path.Data, p, Path.Used) != 0) { vp->iov_base = Path.Data; vp->iov_len = Path.Used; size += (vp++)->iov_len; } vp->iov_base = p; vp->iov_len = Data->Body - p; size += (vp++)->iov_len; if (ARTheaders[_lines].Found == 0) { (void)sprintf(Data->Lines, "Lines: %d\n", Data->LinesValue); i = strlen(Data->Lines); vp->iov_base = Data->Lines; (vp++)->iov_len = i; size += i; /* Install in header table; STRLEN("Lines: ") == 7. */ (void)strcpy(ARTheaders[_lines].Value, Data->Lines + 7); ARTheaders[_lines].Length = i - 7; ARTheaders[_lines].Found = 1; } /* Install in header table; STRLEN("Xref: ") == 6. */ HDR(_xref) = Xref.Data + 6; ARTheaders[_xref].Length = Xref.Used - 6; ARTheaders[_xref].Found = 1; vp->iov_base = Xref.Data; vp->iov_len = Xref.Used; size += (vp++)->iov_len; end = vp; vp->iov_base = NL; vp->iov_len = 1; size += (vp++)->iov_len; vp->iov_base = Data->Body; vp->iov_len = &Article->Data[Article->Used] - Data->Body; size += (vp++)->iov_len; Data->SizeValue = size; (void)sprintf(Data->Size, "%ld", Data->SizeValue); Data->SizeLength = strlen(Data->Size); HDR(_bytes) = Data->Size; ARTheaders[_bytes].Length = Data->SizeLength; ARTheaders[_bytes].Found = 1; /* Now do the write. */ if (xwritev(fd, iov, vp - iov) < 0) { i = errno; syslog(L_ERROR, "%s cant write %s %m", LogName, name); IOError(WHEN, i); (void)close(fd); if (unlink(name) < 0 && errno != ENOENT) { i = errno; syslog(L_ERROR, "%s cant unlink %s %m", LogName, name); IOError(WHEN, i); } return -1; } if (close(fd) < 0) { i = errno; syslog(L_ERROR, "%s cant close %s %m", LogName, name); IOError(WHEN, i); if (unlink(name) < 0 && errno != ENOENT) { i = errno; syslog(L_ERROR, "%s cant unlink %s %m", LogName, name); IOError(WHEN, i); } return -1; } /* Set the owner. */ if (AmRoot) xchown(name); /* Need the header data? */ if (!NeedHeaders) return 0; /* Figure out how much space we'll need and get it. */ (void)sprintf(bytesbuff, "Bytes: %ld\n", size); for (i = strlen(bytesbuff), vp = iov; vp < end; vp++) i += vp->iov_len; if (Headers.Data == NULL) { Headers.Size = i; Headers.Data = NEW(char, Headers.Size + 1); } else if (Headers.Size <= i) { Headers.Size = i; RENEW(Headers.Data, char, Headers.Size + 1); } /* Add the data. */ BUFFset(&Headers, bytesbuff, strlen(bytesbuff)); for (vp = iov; vp < end; vp++) BUFFappend(&Headers, vp->iov_base, vp->iov_len); Data->Headers = &Headers; return 0; } /* ** Parse a header that starts at in, copying it to out. Return pointer to ** the start of the next header and fill in *deltap with what should ** get added to the output pointer. (This nicely lets us clobber obsolete ** headers by setting it to zero.) */ STATIC char * ARTparseheader(in, out, deltap, errorp) register char *in; register char *out; int *deltap; STRING *errorp; { static char buff[SMBUF]; static char COLONSPACE[] = "No colon-space in \"%s\" header"; register char *start; register TREE *tp; register ARTHEADER *hp; register char c; register char *p; register char *dest; register int i; register char *colon; /* Find a non-continuation line. */ for (colon = NULL, start = out; ; ) { switch (*in) { case '\0': *errorp = "EOF in headers"; return NULL; case ':': if (colon == NULL) { colon = out; if (start == colon) { *errorp = "Field without name in header"; return NULL; } } break; } if ((*out++ = *in++) == '\n' && !ISWHITE(*in)) break; } *deltap = out - start; if (colon == NULL || !ISWHITE(colon[1])) { if ((p = strchr(start, '\n')) != NULL) *p = '\0'; (void)sprintf(buff, COLONSPACE, MaxLength(start, start)); *errorp = buff; return NULL; } /* See if this is a system header. A fairly tightly-coded * binary search. */ c = CTYPE(islower, *start) ? toupper(*start) : *start; for (*colon = '\0', tp = ARTheadertree; tp; ) { if ((i = c - tp->Name[0]) == 0 && (i = strcasecmp(start, tp->Name)) == 0) break; if (i < 0) tp = tp->Before; else tp = tp->After; } *colon = ':'; if (tp == NULL) { /* Not a system header, make sure we have . */ for (p = colon; --p != start; ) if (ISWHITE(*p)) { (void)sprintf(buff, "Space before colon in \"%s\" header", MaxLength(start, start)); *errorp = buff; return NULL; } return in; } /* Found a known header; is it obsolete? */ hp = tp->Header; if (hp->Type == HTobs) { *deltap = 0; return in; } /* If body of header is all blanks, drop the header. */ for (p = colon + 1; ISWHITE(*p); p++) continue; if (*p == '\0' || *p == '\n') { *deltap = 0; return in; } hp->Found++; /* Zap in the canonical form of the header, undoing the \0 that * strcpy put out (strncpy() spec isn't trustable, unfortunately). */ (void)strcpy(start, hp->Name); start[hp->Size] = ':'; /* Copy the header if not too big. */ i = (out - 1) - p; if (i >= MAXHEADERSIZE) { (void)sprintf(buff, "\"%s\" header too long", hp->Name); *errorp = buff; return NULL; } hp->Length = i; if (i > MEMCPY_THRESHOLD) { (void)memcpy((POINTER)hp->Value, (POINTER)p, (SIZE_T)i); hp->Value[i] = '\0'; } else { for (dest = hp->Value, i++; --i > 0; ) *dest++ = *p++; *dest = '\0'; } return in; } /* ** Check Message-ID format based on RFC 822 grammar, except that (as per ** RFC 1036) whitespace, non-printing, and '>' characters are excluded. ** Based on code by Paul Eggert posted to news.software.b on 22-Nov-90 ** in <#*tyo2'~n@twinsun.com>, with additional email discussion. ** Thanks, Paul. */ BOOL ARTidok(save) char *save; { register int c; register char *p; /* Scan local-part: "< atom|quoted [ . atom|quoted]" */ p = save; if (*p++ != '<') return FALSE; for (; ; p++) { if (ARTatomchar(*p)) while (ARTatomchar(*++p)) continue; else { if (*p++ != '"') return FALSE; for ( ; ; ) { switch (c = *p++) { case '\\': c = *p++; /* FALLTHROUGH */ default: if (ARTnormchar(c)) continue; return FALSE; case '"': break; } break; } } if (*p != '.') break; } /* Scan domain part: "@ atom|domain [ . atom|domain] > \0" */ if (*p++ != '@') return FALSE; for ( ; ; p++) { if (ARTatomchar(*p)) while (ARTatomchar(*++p)) continue; else { if (*p++ != '[') return FALSE; for ( ; ; ) { switch (c = *p++) { case '\\': c = *p++; /* FALLTHROUGH */ default: if (ARTnormchar(c)) continue; /* FALLTHROUGH */ case '[': return FALSE; case ']': break; } break; } } if (*p != '.') break; } return *p == '>' && *++p == '\0' && (1 + p - save) < DBZMAXKEY; } /* ** Clean up an article. This is mainly copying in-place, stripping bad ** headers. Also fill in the article data block with what we can find. ** Return NULL if the article is okay, or a string describing the error. */ STATIC STRING ARTclean(Article, Data) BUFFER *Article; ARTDATA *Data; { static char buff[SMBUF]; ARTHEADER *hp; register char *in; register char *out; register int i; register char *p; STRING error; int delta; /* Read through the headers one at a time. */ Data->Feedsite = "?"; Data->Size[0] = '0'; Data->Size[1] = '\0'; for (hp = ARTheaders; hp < ENDOF(ARTheaders); hp++) { if (hp->Value && hp->Type != HTobs) *hp->Value = '\0'; hp->Found = 0; } for (error = NULL, in = out = Article->Data; ; out += delta, in = p) { if (*in == '\0') { error = "No body"; break; } if (*in == '\n' && out > Article->Data && out[-1] == '\n') /* Found a \n after another \n; break out. */ break; /* Check the validity of this header. */ if ((p = ARTparseheader(in, out, &delta, &error)) == NULL) break; } Data->Body = out; in++; /* Try to set this now, so we can report it in errors. */ p = HDR(_message_id); if (*p) { Data->MessageID = p; Data->MessageIDLength = strlen(p); if (error == NULL) { if (Data->MessageIDLength + 1 >= DBZMAXKEY) error = "\"Message-ID\" header too long"; else if (!ARTidok(p)) error = "Bad \"Message-ID\" header"; } } if (error) return error; /* Make sure all the headers we need are there, and no duplicates. */ for (hp = ARTheaders; hp < ENDOF(ARTheaders); hp++) if (hp->Type == HTreq) { if (*hp->Value == '\0') { (void)sprintf(buff, "Missing \"%s\" header", hp->Name); return buff; } if (hp->Found > 1) { (void)sprintf(buff, "Duplicate \"%s\" header", hp->Name); return buff; } } /* Scan the body, counting lines. */ for (i = 0; *in; ) { if (*in == '\n') i++; *out++ = *in++; } *out = '\0'; Article->Used = out - Article->Data; Data->LinesValue = i; #if defined(DO_CHECK_LINECOUNT) p = HDR(_lines); if (*p && (delta = i - atoi(p)) != 0 && abs(delta) > LINECOUNT_FUZZ) { if ((in = strchr(p, '\n')) != NULL) *in = '\0'; (void)sprintf(buff, "Linecount %s != %d +- %d", MaxLength(p, p), i, LINECOUNT_FUZZ); return buff; } #endif /* defined(DO_CHECK_LINECOUNT) */ /* Is article too old? */ p = HDR(_date); if ((Data->Posted = parsedate(p, &Now)) == -1) { (void)sprintf(buff, "Bad \"Date\" header -- \"%s\"", MaxLength(p, p)); return buff; } if (Cutoff && Data->Posted < Now.time - Cutoff) { (void)sprintf(buff, "Too old -- \"%s\"", MaxLength(p, p)); return buff; } if (Data->Posted > Now.time + DATE_FUZZ) { (void)sprintf(buff, "Article posted in the future -- \"%s\"", MaxLength(p, p)); return buff; } Data->Arrived = Now.time; p = HDR(_expires); Data->Expires = 0; if (*p != '\0' && (Data->Expires = parsedate(p, &Now)) == -1) { #if 0 (void)sprintf(buff, "Bad \"Expires\" header -- \"%s\"", MaxLength(p, p)); return buff; #endif } /* Colon or whitespace in the Newsgroups header? */ if (strchr(HDR(_newsgroups), ':') != NULL) return "Colon in \"Newsgroups\" header"; for (p = HDR(_newsgroups); *p; p++) if (ISWHITE(*p)) { (void)sprintf(buff, "Whitespace in \"Newsgroups\" header -- \"%s\"", MaxLength(HDR(_newsgroups), p)); return buff; } /* If there is no control header, see if the article starts with * "cmsg ". */ in = HDR(_control); if (*in == '\0') { p = HDR(_subject); if (*p == 'c' && EQn(p, "cmsg ", 5)) { for (p += 5; *p && ISWHITE(*p); ) p++; if (*p) (void)strcpy(in, p); } } return NULL; } /* ** Start a log message about an article. */ STATIC void ARTlog(Data, code, text) ARTDATA *Data; char code; char *text; { int i; BOOL Done; /* We could be a bit faster by not dividing Now.usec by 1000, * but who really wants to log at the Microsec level? */ Done = code == ART_ACCEPT || code == ART_JUNK; if (text) i = fprintf(Log, "%.15s.%03d %c %s %s %s%s", ctime(&Now.time) + 4, (int)(Now.usec / 1000), code, Data->Feedsite, Data->MessageID == NULL ? "(null)" : Data->MessageID, text, Done ? "" : "\n"); else i = fprintf(Log, "%.15s.%03d %c %s %s%s", ctime(&Now.time) + 4, (int)(Now.usec / 1000), code, Data->Feedsite, Data->MessageID == NULL ? "(null)" : Data->MessageID, Done ? "" : "\n"); if (i == EOF || (Done && !BufferedLogs && fflush(Log)) || ferror(Log)) { i = errno; syslog(L_ERROR, "%s cant write log_start %m", LogName); IOError("logging article", i); clearerr(Log); } } /* ** We are going to reject an article, record the reason and ** and the article. For now, this is just a placeholder. */ /* ARGSUSED0 */ STATIC void ARTreject(buff, article) char *buff; BUFFER *article; { } #if defined(DO_VERIFY_CANCELS) /* ** Verify if a cancel message is valid. If the user posting the cancel ** matches the user who posted the article, return the list of filenames ** otherwise return NULL. */ STATIC char * ARTcancelverify(Data, MessageID) ARTDATA *Data; char *MessageID; { register char *files; register char *p; register char *local; char *head; char buff[SMBUF]; files = HISfilesfor(MessageID); if ((head = ARTreadheader(files)) == NULL) return NULL; /* Get the author header. */ if ((local = HeaderFind(head, "Sender", 6)) == NULL && (local = HeaderFind(head, "From", 4)) == NULL) { syslog(L_ERROR, "%s bad_article %s checking cancel", LogName, MessageID); return NULL; } HeaderCleanFrom(local); /* Compare canonical forms. */ p = COPY(Data->Poster); HeaderCleanFrom(p); if (!EQ(local, p)) { files = NULL; (void)sprintf(buff, "\"%.50s\" wants to cancel %s by \"%.50s\"", p, MaxLength(MessageID, MessageID), local); ARTlog(Data, ART_REJECT, buff); } DISPOSE(p); return files; } #endif /* defined(DO_VERIFY_CANCELS) */ /* ** Process a cancel message. */ /* ARGSUSED2 */ void ARTcancel(Data, MessageID, Trusted) ARTDATA *Data; char *MessageID; BOOL Trusted; { register char *files; register char *p; register char *msgid; register char *next; register BOOL more; STRING save; char buff[SMBUF+16]; char c; if (!DoCancels && !Trusted) { return; } for (msgid = MessageID; msgid && *msgid; msgid = next) { for (next = msgid; *next && !ISWHITE(*next); next++) continue; if ((c = *next) != '\0') *next++ = '\0'; if (c && msgid == MessageID) syslog(L_NOTICE, "%s multiple cancel %s", Data->Feedsite, MaxLength(Data->MessageID, Data->MessageID)); if (*msgid == '\0') { if (c) next[-1] = c; continue; } if (!ARTidok(msgid)) { syslog(L_NOTICE, "%s bad cancel Message-ID %s", Data->Feedsite, MaxLength(msgid, msgid)); continue; } if (!HIShavearticle(msgid)) { /* Article hasn't arrived here, so write a fake entry using * most of the information from the cancel message. */ #if defined(DO_VERIFY_CANCELS) if (!Trusted) { if (c) next[-1] = c; continue; } #endif /* defined(DO_VERIFY_CANCELS) */ save = Data->MessageID; Data->MessageID = msgid; (void)HISwrite(Data, (char *)NULL); if (save != MessageID) Data->MessageID = save; (void)sprintf(buff, "Cancelling %s", MaxLength(msgid, msgid)); ARTlog(Data, ART_CANC, buff); Data->MessageID = save; if (c) next[-1] = c; continue; } #if defined(DO_VERIFY_CANCELS) files = Trusted ? HISfilesfor(msgid) : ARTcancelverify(Data, msgid); #else files = HISfilesfor(msgid); #endif /* !defined(DO_VERIFY_CANCELS) */ if (files == NULL) { if (c) next[-1] = c; continue; } /* Get the files where the message is stored and and zap them. */ for ( ; *files; files = p + 1) { /* Snip off next name, turn dots to slashes. */ for (p = files; ISWHITE(*p); p++) continue; for (files = p; *p && *p != ' '; p++) if (*p == '.') *p = '/'; more = *p == ' '; if (more) *p = '\0'; /* Remove this file, go back for the next one if there's more. */ if (unlink(files) < 0 && errno != ENOENT) syslog(L_ERROR, "%s cant unlink %s %m", LogName, files); if (!more) break; } if (c) next[-1] = c; } } /* ** Process a control message. Cancels are handled here, but any others ** are passed out to an external program in a specific directory that ** has the same name as the first word of the control message. */ STATIC void ARTcontrol(Data, Control) ARTDATA *Data; char *Control; { static char CTLBIN[] = _PATH_CONTROLPROGS; register char *p; char buff[SMBUF]; char *av[6]; struct stat Sb; register char c; /* See if it's a cancel message. */ c = *Control; if (c == 'c' && EQn(Control, "cancel", 6)) { for (p = &Control[6]; ISWHITE(*p); p++) continue; if (*p && ARTidok(p)) ARTcancel(Data, p, FALSE); return; } /* Nip off the first word into lowercase. */ for (p = Control; *p && !ISWHITE(*p); p++) if (CTYPE(isupper, *p)) *p = tolower(*p); if (*p) *p++ = '\0'; /* Treat the control message as a place to send the article, if * the name is "safe" -- no slashes in the pathname. */ if (p - Control + STRLEN( _PATH_BADCONTROLPROG) >= SMBUF-4 || strchr(Control, '/') != NULL) FileGlue(buff, CTLBIN, '/', _PATH_BADCONTROLPROG); else { FileGlue(buff, CTLBIN, '/', Control); if (stat(buff, &Sb) < 0 || (Sb.st_mode & EXECUTE_BITS) == 0) FileGlue(buff, CTLBIN, '/', _PATH_BADCONTROLPROG); } /* If it's an ihave or sendme, check the site named in the message. */ if ((c == 'i' && EQ(Control, "ihave")) || (c == 's' && EQ(Control, "sendme"))) { while (ISWHITE(*p)) p++; if (*p == '\0') { syslog(L_NOTICE, "%s malformed %s no site %s", LogName, Control, Data->Name); return; } if (EQ(p, ARTpathme)) { /* Do nothing -- must have come from a replicant. */ syslog(L_NOTICE, "%s %s_from_me %s", Data->Feedsite, Control, Data->Name); return; } if (!SITEfind(p)) { if (c == 'i') syslog(L_ERROR, "%s bad_ihave in %s", Data->Feedsite, Data->Newsgroups); else syslog(L_ERROR, "%s bad_sendme dont feed %s", Data->Feedsite, Data->Name); return; } } /* Build the command vector and execute it. */ av[0] = buff; av[1] = COPY(Data->Poster); av[2] = COPY(Data->Replyto); av[3] = Data->Name; av[4] = (char *)Data->Feedsite; av[5] = NULL; HeaderCleanFrom(av[1]); HeaderCleanFrom(av[2]); if (Spawn(STDIN, (int)fileno(Errlog), (int)fileno(Errlog), av) < 0) /* We know the strrchr below can't fail. */ syslog(L_ERROR, "%s cant spawn %s for %s %m", LogName, MaxLength(av[0], strrchr(av[0], '/')), Data->Name); DISPOSE(av[1]); DISPOSE(av[2]); } /* ** Split a Distribution header, making a copy and skipping leading and ** trailing whitespace (which the RFC allows). */ STATIC void DISTparse(list, Data) register char **list; ARTDATA *Data; { static BUFFER Dist; register char *p; register char *q; register int i; register int j; /* Get space to store the copy. */ for (i = 0, j = 0; (p = list[i]) != NULL; i++) j += 1 + strlen(p); if (Dist.Data == NULL) { Dist.Size = j; Dist.Data = NEW(char, Dist.Size + 1); } else if (Dist.Size <= j) { Dist.Size = j + 16; RENEW(Dist.Data, char, Dist.Size + 1); } /* Loop over each element, skip and trim whitespace. */ for (q = Dist.Data, i = 0, j = 0; (p = list[i]) != NULL; i++) { while (ISWHITE(*p)) p++; if (*p) { if (j) *q++ = ','; for (list[j++] = p; *p && !ISWHITE(*p); ) *q++ = *p++; *p = '\0'; } } list[j] = NULL; *q = '\0'; Data->Distribution = Dist.Data; Data->DistributionLength = q - Dist.Data; } /* ** A somewhat similar routine, except that this handles negated entries ** in the list and is used to check the distribution sub-field. */ STATIC BOOL DISTwanted(list, p) register char **list; register char *p; { register char *q; register char c; register BOOL sawbang; for (sawbang = FALSE, c = *p; (q = *list) != NULL; list++) if (*q == '!') { sawbang = TRUE; if (c == *++q && EQ(p, q)) return FALSE; } else if (c == *q && EQ(p, q)) return TRUE; /* If we saw any !foo's and didn't match, then assume they are all * negated distributions and return TRUE, else return false. */ return sawbang; } /* ** See if any of the distributions in the article are wanted by the site. */ STATIC BOOL DISTwantany(site, article) char **site; register char **article; { for ( ; *article; article++) if (DISTwanted(site, *article)) return TRUE; return FALSE; } /* ** Sort an array of newsgroups for optimal disk access. This may be ** of marginal benefit. */ STATIC void ARTsortfordisk() { static NEWSGROUP *save; register NEWSGROUP **ngptr; if (save && GroupPointers[1] != NULL) { /* If one of the groups we want to access is the group we last * wrote to, move it to the front of the list. */ for (ngptr = GroupPointers; *++ngptr; ) if (*ngptr == save) { *ngptr = GroupPointers[0]; GroupPointers[0] = save; return; } } save = GroupPointers[0]; } /* ** Send the current article to all sites that would get it if the ** group were created. */ STATIC void ARTsendthegroup(name) register char *name; { register SITE *sp; register int i; NEWSGROUP *ngp; for (ngp = NGfind(ARTctl), sp = Sites, i = nSites; --i >= 0; sp++) if (sp->Name != NULL && SITEwantsgroup(sp, name)) { SITEmark(sp, ngp); } } /* ** Check if site doesn't want this group even if it's crossposted ** to a wanted group. */ STATIC void ARTpoisongroup(name) register char *name; { register SITE *sp; register int i; for (sp = Sites, i = nSites; --i >= 0; sp++) if (sp->Name != NULL && (sp->PoisonEntry || ME.PoisonEntry) && SITEpoisongroup(sp, name)) sp->Poison = TRUE; } /* ** Assign article numbers to the article and create the Xref line. ** If we end up not being able to write the article, we'll get "holes" ** in the directory and active file. */ STATIC void ARTassignnumbers() { register char *p; register int i; register NEWSGROUP *ngp; p = &Xref.Data[Xref.Used]; for (i = 0; (ngp = GroupPointers[i]) != NULL; i++) { /* If already went to this group (i.e., multiple groups are aliased * into it), then skip it. */ if (ngp->PostCount > 0) continue; /* Bump the number. */ ngp->PostCount++; ngp->Last++; if (!FormatLong(ngp->LastString, (long)ngp->Last, ngp->Lastwidth)) { syslog(L_ERROR, "%s cant update_active %s", LogName, ngp->Name); continue; } ngp->Filenum = ngp->Last; (void)sprintf(p, " %s:%lu", ngp->Name, ngp->Filenum); p += strlen(p); } Xref.Used = p - Xref.Data; Xref.Data[Xref.Used++] = '\n'; } /* ** Parse the data from the xreplic command and assign the numbers. ** This involves replacing the GroupPointers entries. */ STATIC void ARTreplic(Replic) BUFFER *Replic; { register char *p; register char *q; register char *name; register char *next; register NEWSGROUP *ngp; register int i; p = &Xref.Data[Xref.Used]; for (i = 0, name = Replic->Data; *name; name = next) { /* Mark end of this entry and where next one starts. */ if ((next = strchr(name, ',')) != NULL) *next++ = '\0'; else next = ""; /* Split into news.group/# */ if ((q = strchr(name, '/')) == NULL) { syslog(L_ERROR, "%s bad_format %s", LogName, name); continue; } *q = '\0'; if ((ngp = NGfind(name)) == NULL) { syslog(L_ERROR, "%s bad_newsgroup %s", LogName, name); continue; } ngp->Filenum = atol(q + 1); /* Update active file if we got a new high-water mark. */ if (ngp->Last < ngp->Filenum) { ngp->Last = ngp->Filenum; if (!FormatLong(ngp->LastString, (long)ngp->Last, ngp->Lastwidth)) { syslog(L_ERROR, "%s cant update_active %s", LogName, ngp->Name); continue; } } /* Mark that this group gets the article. */ ngp->PostCount++; GroupPointers[i++] = ngp; /* Turn news.group/# into news.group:#, append to Xref. */ *q = ':'; *p++ = ' '; p += strlen(strcpy(p, name)); } Xref.Used = p - Xref.Data; Xref.Data[Xref.Used++] = '\n'; } /* ** Return TRUE if a list of strings has a specific one. This is a ** generic routine, but is used for seeing if a host is in the Path line. */ STATIC BOOL ListHas(list, p) register char **list; register char *p; { register char *q; register char c; for (c = *p; (q = *list) != NULL; list++) if (c == *q && caseEQ(p, q)) return TRUE; return FALSE; } /* ** Propagate an article to the sites have "expressed an interest." */ STATIC void ARTpropagate(Data, hops, hopcount, list) ARTDATA *Data; char **hops; int hopcount; char **list; { register SITE *sp; register int i; register int j; register int Groupcount; register char *p; register SITE *funnel; register BUFFER *bp; /* Work out which sites should really get it. */ Groupcount = Data->Groupcount; for (sp = Sites, i = nSites; --i >= 0; sp++) { if (sp->Seenit || !sp->Sendit) continue; sp->Sendit = FALSE; if (sp->Master != NOSITE && Sites[sp->Master].Seenit) continue; if (sp->MaxSize && Data->SizeValue > sp->MaxSize) /* Too big for the site. */ continue; if (sp->MinSize && Data->SizeValue < sp->MinSize) /* Too small for the site. */ continue; if ((!sp->IgnorePath && ListHas(hops, sp->Name)) || (sp->Hops && hopcount > sp->Hops) || (sp->Groupcount && Groupcount > sp->Groupcount)) /* Site already saw the article; path too long; or too much * cross-posting. */ continue; if (list && sp->Distributions && !DISTwantany(sp->Distributions, list)) /* Not in the site's desired list of distributions. */ continue; if (sp->DistRequired && list == NULL) /* Site requires Distribution header and there isn't one. */ continue; if (sp->Exclusions) { for (j = 0; (p = sp->Exclusions[j]) != NULL; j++) if (ListHas(hops, p)) break; if (p != NULL) /* A host in the site's exclusion list was in the Path. */ continue; } /* Write that the site is getting it, and flag to send it. */ if (fprintf(Log, " %s", sp->Name) == EOF || ferror(Log)) { j = errno; syslog(L_ERROR, "%s cant write log_site %m", LogName); IOError("logging site", j); clearerr(Log); } sp->Sendit = TRUE; sp->Seenit = TRUE; if (sp->Master != NOSITE) Sites[sp->Master].Seenit = TRUE; } if (putc('\n', Log) == EOF || (!BufferedLogs && fflush(Log)) || ferror(Log)) { syslog(L_ERROR, "%s cant write log_end %m", LogName); clearerr(Log); } /* Handle funnel sites. */ for (sp = Sites, i = nSites; --i >= 0; sp++) if (sp->Sendit && sp->Funnel != NOSITE) { sp->Sendit = FALSE; funnel = &Sites[sp->Funnel]; funnel->Sendit = TRUE; if (funnel->FNLwantsnames) { bp = &funnel->FNLnames; p = &bp->Data[bp->Used]; if (bp->Used) { *p++ = ' '; bp->Used++; } bp->Used += strlen(strcpy(p, sp->Name)); } } } /* ** Build up the overview data. */ STATIC void ARTmakeoverview(Data) ARTDATA *Data; { static char SEP[] = "\t"; static char COLONSPACE[] = ": "; static BUFFER Overview; register ARTOVERFIELD *fp; register ARTHEADER *hp; register char *p; register int i; /* Setup. */ if (Overview.Data == NULL) Overview.Data = NEW(char, 1); Data->Overview = &Overview; BUFFset(&Overview, Xref.Data + Xrefbase + 1, Xref.Used - (Xrefbase + 2)); for (i = Overview.Left, p = Overview.Data; --i >= 0; p++) if (*p == '.' || *p == ':') *p = '/'; if (ARTfields == NULL) { /* User error. */ return; } /* Write the data, a field at a time. */ for (fp = ARTfields; fp->Header; fp++) { BUFFappend(&Overview, SEP, STRLEN(SEP)); hp = fp->Header; if (!hp->Found) continue; if (fp->NeedHeader) { BUFFappend(&Overview, hp->Name, hp->Size); BUFFappend(&Overview, COLONSPACE, STRLEN(COLONSPACE)); } i = Overview.Left; BUFFappend(&Overview, hp->Value, hp->Length); for (p = &Overview.Data[i]; i < Overview.Left; p++, i++) if (*p == '\t' || *p == '\n' || *p == '\r') *p = ' '; } } /* ** This routine is the heart of it all. Take a full article, parse it, ** file or reject it, feed it to the other sites. Return the NNTP ** message to send back. */ STRING ARTpost(cp, Replic, ihave) CHANNEL *cp; BUFFER *Replic; char *ihave; { static BUFFER Files; static BUFFER Header; static char buff[SPOOLNAMEBUFF]; register char *p; register int i; register int j; register NEWSGROUP *ngp; register NEWSGROUP **ngptr; register int *isp; register SITE *sp; ARTDATA Data; BOOL Approved; BOOL Accepted; BOOL LikeNewgroup; BOOL ToGroup; BOOL GroupMissing; BUFFER *article; char linkname[SPOOLNAMEBUFF]; char **groups; char **hops; int hopcount; char **distributions; STRING error; char ControlWord[SMBUF]; int ControlHeader; int oerrno; #if defined(DO_PERL) char *perlrc; #endif /* DO_PERL */ /* Preliminary clean-ups. */ article = &cp->In; Data.MessageID = ihave; error = ARTclean(article, &Data); /* Not much we can do here except toss it and report the error. */ if (error != NULL) { (void)sprintf(buff, "%d %s", NNTP_REJECTIT_VAL, error); return buff ; } /* Fill in other Data fields. */ Data.Poster = HDR(_sender); if (*Data.Poster == '\0') Data.Poster = HDR(_from); Data.Replyto = HDR(_reply_to); if (*Data.Replyto == '\0') Data.Replyto = HDR(_from); hops = ARTparsepath(HDR(_path), &hopcount); #if defined(DO_IPADDR_LOG) Data.Feedsite = RChostname(cp); if (Data.Feedsite == NULL) Data.Feedsite = CHANname(cp); #else Data.Feedsite = hops && hops[0] ? hops[0] : CHANname(cp); #endif /* defined(DO_IPADDRLOG) */ Data.FeedsiteLength = strlen(Data.Feedsite); (void)sprintf(Data.TimeReceived, "%lu", Now.time); Data.TimeReceivedLength = strlen(Data.TimeReceived); /* A duplicate? */ if (error == NULL && HIShavearticle(Data.MessageID)){ error = "Duplicate article"; (void)sprintf(buff, "%d %s", NNTP_REJECTIT_VAL, error); ARTreject(buff, article); return buff; } else if (error == NULL) { /* And now check the path for unwanted sites -- Andy */ for( j = 0 ; ME.Exclusions && ME.Exclusions[j] ; j++ ) { if( ListHas(hops, ME.Exclusions[j]) ) { sprintf(ControlWord, "Unwanted site %s in path", ME.Exclusions[j]); error = ControlWord; break; } } } /* Now see if we got an error in the article. */ if (error != NULL) { (void)sprintf(buff, "%d %s", NNTP_REJECTIT_VAL, error); ARTlog(&Data, ART_REJECT, buff); #if defined(DO_REMEMBER_TRASH) if (Data.MessageID != NULL && Mode == OMrunning && !HISwrite(&Data, "")) syslog(L_ERROR, "%s cant write history %s %m", LogName, Data.MessageID); #endif /* defined(DO_REMEMBER_TRASH) */ ARTreject(buff, article); return buff; } #if defined(DO_PERL) pathForPerl = HeaderFind(article->Data, "Path", 4) ; if ((perlrc = (char *)HandleArticle()) != NULL) { (void)sprintf(buff, "%d %s", NNTP_REJECTIT_VAL, perlrc); syslog(L_NOTICE, "rejecting[perl] %s %s", HDR(_message_id), buff); ARTlog(&Data, ART_REJECT, buff); #if defined(DO_REMEMBER_TRASH) if (Data.MessageID && Mode == OMrunning && !HISwrite(&Data, "")) syslog(L_ERROR, "%s cant write history %s %m", LogName, Data.MessageID); #endif /* defined(DO_REMEMBER_TRASH) */ ARTreject(buff, article); return buff; } #endif /* DO_PERL */ /* I suppose some masochist will run with both TCP and PERL in together */ #if defined(DO_TCL) if (TCLFilterActive) { int code; ARTHEADER *hp; /* make info available to Tcl */ TCLCurrArticle = article; TCLCurrData = &Data; (void)Tcl_UnsetVar(TCLInterpreter, "Body", TCL_GLOBAL_ONLY); (void)Tcl_UnsetVar(TCLInterpreter, "Headers", TCL_GLOBAL_ONLY); for (hp = ARTheaders; hp < ENDOF(ARTheaders); hp++) { if (hp->Found) { Tcl_SetVar2(TCLInterpreter, "Headers", (char *) hp->Name, hp->Value, TCL_GLOBAL_ONLY); } } #if 1 Tcl_SetVar(TCLInterpreter, "Body", Data.Body, TCL_GLOBAL_ONLY); #endif /* call filter */ code = Tcl_Eval(TCLInterpreter, "filter_news"); (void)Tcl_UnsetVar(TCLInterpreter, "Body", TCL_GLOBAL_ONLY); (void)Tcl_UnsetVar(TCLInterpreter, "Headers", TCL_GLOBAL_ONLY); if (code == TCL_OK) { if (strcmp(TCLInterpreter->result, "accept") != 0) { (void)sprintf(buff, "%d %s", NNTP_REJECTIT_VAL, TCLInterpreter->result); syslog(L_NOTICE, "rejecting[tcl] %s %s", HDR(_message_id), buff); ARTlog(&Data, ART_REJECT, buff); #if defined(DO_REMEMBER_TRASH) if (Data.MessageID && Mode == OMrunning && !HISwrite(&Data,"")) syslog(L_ERROR, "%s cant write history %s %m", LogName, Data.MessageID); #endif /* defined(DO_REMEMBER_TRASH) */ ARTreject(buff, article); return buff; } } else { /* the filter failed: complain and then turn off filtering */ syslog(L_ERROR, "TCL proc filter_news failed: %s", TCLInterpreter->result); TCLfilter(FALSE); } } #endif /* defined(DO_TCL) */ /* Stash a copy of the Newsgroups header. */ p = HDR(_newsgroups); i = strlen(p); if (Header.Data == NULL) { Header.Size = i; Header.Data = NEW(char, Header.Size + 1); } else if (Header.Size <= i) { Header.Size = i + 16; RENEW(Header.Data, char, Header.Size + 1); } (void)strcpy(Header.Data, p); Data.Newsgroups = Header.Data; Data.NewsgroupsLength = i; /* If we limit what distributions we get, see if we want this one. */ p = HDR(_distribution); distributions = *p ? CommaSplit(p) : NULL; if (distributions) { DISTparse(distributions, &Data); if (ME.Distributions && !DISTwantany(ME.Distributions, distributions)) { (void)sprintf(buff, "%d Unwanted distribution \"%s\"", NNTP_REJECTIT_VAL, MaxLength(distributions[0], distributions[0])); ARTlog(&Data, ART_REJECT, buff); #if defined(DO_REMEMBER_TRASH) if (Mode == OMrunning && !HISwrite(&Data, "")) syslog(L_ERROR, "%s cant write history %s %m", LogName, Data.MessageID); #endif /* defined(DO_REMEMBER_TRASH) */ DISPOSE(distributions); ARTreject(buff, article); return buff; } } else { Data.Distribution = "?"; Data.DistributionLength = 1; } /* Clear all groups and sites -- assume nobody gets the article. */ for (i = nGroups, ngp = Groups; --i >= 0; ngp++) ngp->PostCount = 0; for (i = nSites, sp = Sites; --i >= 0; sp++) { sp->Poison = FALSE; sp->Sendit = FALSE; sp->Seenit = FALSE; sp->FNLnames.Used = 0; sp->ng = NULL; } /* Parse the Control or Also-Control header. */ groups = NGsplit(HDR(_newsgroups)); for (i = 0; groups[i] != NULL; i++) continue; Data.Groupcount = i; if (HDR(_control)[0] != '\0') ControlHeader = _control; else if (HDR(_alsocontrol)[0] != '\0') ControlHeader = _alsocontrol; else { ControlHeader = -1; LikeNewgroup = FALSE; } if (ControlHeader >= 0) { /* Nip off the first word into lowercase. */ (void)strncpy(ControlWord, HDR(ControlHeader), sizeof ControlWord); ControlWord[sizeof ControlWord - 1] = '\0'; for (p = ControlWord; *p && !ISWHITE(*p); p++) if (CTYPE(isupper, *p)) *p = tolower(*p); *p = '\0'; LikeNewgroup = EQ(ControlWord, "newgroup") || EQ(ControlWord, "rmgroup"); /* Control messages to "foo.ctl" are treated as if they were * posted to "foo". I should probably apologize for all the * side-effects in the if. */ for (i = 0; (p = groups[i++]) != NULL; ) if ((j = strlen(p) - 4) > 0 && *(p += j) == '.' && p[1] == 'c' && p[2] == 't' && p[3] == 'l') *p = '\0'; } /* Loop over the newsgroups, see which ones we want, and get the * total space needed for the Xref line. At the end of this section * of code, j will have the needed length, the appropriate site * entries will have their Sendit and ng fields set, and GroupPointers * will have pointers to the relevant newsgroups. */ ToGroup = FALSE; p = HDR(_approved); Approved = *p != '\0'; ngptr = GroupPointers; j = 0; for (GroupMissing = Accepted = FALSE; (p = *groups) != NULL; groups++) { if (!RCcanpost(cp, p)) continue; if ((ngp = NGfind(p)) == NULL) { GroupMissing = TRUE; if (LikeNewgroup && Approved) { /* Newgroup/rmgroup being sent to a group that doesn't * exist. Assume it is being sent to the group being * created or removed, nd send the group to all sites that * would or would have had the group if it were created. */ ARTsendthegroup(*groups); Accepted = TRUE; } ARTpoisongroup(*groups); #if defined(DO_MERGE_TO_GROUPS) /* Try to collapse all "to" newsgroups. */ if (*p != 't' || *++p != 'o' || *++p != '.' || *++p == '\0') continue; ngp = NGfind("to"); ToGroup = TRUE; if ((sp = SITEfind(p)) != NULL) { SITEmark(sp, ngp); } #else continue; #endif /* defined(DO_MERGE_TO_GROUPS) */ } /* Ignore this group? */ if (ngp->Rest[0] == NF_FLAG_IGNORE) continue; /* Basic validity check. */ if (ngp->Rest[0] == NF_FLAG_MODERATED && !Approved) { (void)sprintf(buff, "%d Unapproved for \"%s\"", NNTP_REJECTIT_VAL, ngp->Name); ARTlog(&Data, ART_REJECT, buff); #if defined(DO_REMEMBER_TRASH) if (Mode == OMrunning && !HISwrite(&Data, "")) syslog(L_ERROR, "%s cant write history %s %m", LogName, Data.MessageID); #endif /* defined(DO_REMEMBER_TRASH) */ if (distributions) DISPOSE(distributions); ARTreject(buff, article); return buff; } /* See if any of this group's sites considers this group poison. */ for (isp = ngp->Poison, i = ngp->nPoison; --i >= 0; isp++) if (*isp >= 0) Sites[*isp].Poison = TRUE; /* Valid group, feed it to that group's sites. */ Accepted = TRUE; for (isp = ngp->Sites, i = ngp->nSites; --i >= 0; isp++) if (*isp >= 0) { sp = &Sites[*isp]; if (!sp->Poison) SITEmark(sp, ngp); } /* If it's excluded, don't file it. */ if (ngp->Rest[0] == NF_FLAG_EXCLUDED) continue; /* Expand aliases, mark the article as getting filed in the group. */ if (ngp->Alias != NULL) ngp = ngp->Alias; *ngptr++ = ngp; ngp->PostCount = 0; j += ngp->NameLength + 1 + MAXARTFNAME + 1; } /* Loop over sites to find Poisons and undo Sendit flags. */ for (i = nSites, sp = Sites; --i >= 0; sp++) if (sp->Poison) sp->Sendit = FALSE; /* Control messages not filed in "to" get filed only in control.name * or control. */ if (ControlHeader >= 0 && Accepted && !ToGroup) { FileGlue(buff, "control", '.', ControlWord); if ((ngp = NGfind(buff)) == NULL) ngp = NGfind(ARTctl); ngp->PostCount = 0; ngptr = GroupPointers; *ngptr++ = ngp; j = ngp->NameLength + 1 + MAXARTFNAME; for (isp = ngp->Sites, i = ngp->nSites; --i >= 0; isp++) if (*isp >= 0) { sp = &Sites[*isp]; SITEmark(sp, ngp); } } /* If !Accepted, then none of the article's newgroups exist in our * active file. Proper action is to drop the article on the floor. * If ngp == GroupPointers, then all the new articles newsgroups are * "j" entries in the active file. In that case, we have to file it * under junk so that downstream feeds can get it. */ if (!Accepted || ngptr == GroupPointers) { if (!Accepted) { (void)sprintf(buff, "%d Unwanted newsgroup \"%s\"", NNTP_REJECTIT_VAL, MaxLength(HDR(_newsgroups), HDR(_newsgroups))); ARTlog(&Data, ART_REJECT, buff); #if defined(DONT_WANT_TRASH) #if defined(DO_REMEMBER_TRASH) if (Mode == OMrunning && !HISwrite(&Data, "")) syslog(L_ERROR, "%s cant write history %s %m", LogName, Data.MessageID); #endif /* defined(DO_REMEMBER_TRASH) */ if (distributions) DISPOSE(distributions); ARTreject(buff, article); return buff; #else /* if !GroupMissing, then all the groups the article was posted * to have a flag of "x" in our active file, and therefore * we should throw the article away: if you have define * DO_WANT_TRASH, then you want all trash except that which * you explicitly excluded in your active file. */ if (!GroupMissing) { #if defined(DO_REMEMBER_TRASH) if (Mode == OMrunning && !HISwrite(&Data, "")) syslog(L_ERROR, "%s cant write history %s %m", LogName, Data.MessageID); #endif /* defined(DO_REMEMBER_TRASH) */ if (distributions) DISPOSE(distributions); ARTreject(buff, article); return buff; } #endif /* defined(DONT_WANT_TRASH) */ } ngp = NGfind(ARTjnk); *ngptr++ = ngp; ngp->PostCount = 0; j = STRLEN(ARTjnk) + 1 + MAXARTFNAME; /* Junk can be fed to other sites. */ for (isp = ngp->Sites, i = ngp->nSites; --i >= 0; isp++) if (*isp >= 0) { sp = &Sites[*isp]; if (!sp->Poison) SITEmark(sp, ngp); } } *ngptr = NULL; j++; if (Replic) j = Replic->Used + 1; /* Make sure the Xref buffer has room. */ Xref.Used = Xrefbase; if (Xref.Size <= j + Xrefbase + 2) { Xref.Size = j + Xrefbase + 2; RENEW(Xref.Data, char, Xref.Size + 1); } /* Make sure the filename buffer has room. */ if (Files.Data == NULL) { Files.Size = j; Files.Data = NEW(char, Files.Size + 1); } else if (Files.Size <= j) { Files.Size = j; RENEW(Files.Data, char, Files.Size + 1); } /* Assign article numbers, fill in Xref buffer. */ if (Replic == NULL) ARTassignnumbers(); else ARTreplic(Replic); /* Optimize how we place the article on the disk. */ ARTsortfordisk(); /* Now we can file it. */ if (++ICDactivedirty >= ICD_SYNC_COUNT) { ICDwriteactive(); ICDactivedirty = 0; } Data.Name[0] = '\0'; p = Files.Data; *p = '\0'; for (i = 0; (ngp = GroupPointers[i]) != NULL; i++) { if (!ngp->PostCount) continue; ngp->PostCount = 0; if (Data.Name[0] == '\0') { /* Write the article the first time. */ (void)sprintf(Data.Name, "%s/%lu", ngp->Dir, ngp->Filenum); if (ARTwrite(Data.Name, article, &Data) < 0 && (!MakeSpoolDirectory(ngp->Dir) || ARTwrite(Data.Name, article, &Data) < 0)) { i = errno; syslog(L_ERROR, "%s cant write %s %m", LogName, Data.Name); (void)sprintf(buff, "%d cant write article %s, %s", NNTP_RESENDIT_VAL, Data.Name, strerror(i)); ARTlog(&Data, ART_REJECT, buff); #if defined(DO_REMEMBER_TRASH) if (Mode == OMrunning && !HISwrite(&Data, "")) syslog(L_ERROR, "%s cant write history %s %m", LogName, Data.MessageID); #endif /* defined(DO_REMEMBER_TRASH) */ if (distributions) DISPOSE(distributions); ARTreject(buff, article); return buff; } p += strlen(strcpy(p, Data.Name)); Data.NameLength = strlen(Data.Name); } else { /* Link to the main article. */ (void)sprintf(linkname, "%s/%lu", ngp->Dir, ngp->Filenum); if (DoLinks && link(Data.Name, linkname) < 0 && (!MakeSpoolDirectory(ngp->Dir) || link(Data.Name, linkname) < 0)) { #if defined(DONT_HAVE_SYMLINK) oerrno = errno; syslog(L_ERROR, "%s cant link %s and %s %m", LogName, Data.Name, linkname); IOError("linking article", oerrno); continue; #else /* Try to make a symbolic link to the full pathname. */ FileGlue(buff, SPOOL, '/', Data.Name); if (symlink(buff, linkname) < 0 && (!MakeSpoolDirectory(ngp->Dir) || symlink(buff, linkname) < 0)) { oerrno = errno; syslog(L_ERROR, "%s cant symlink %s and %s %m", LogName, buff, linkname); IOError("symlinking article", oerrno); continue; } #endif /* defined(DONT_HAVE_SYMLINK) */ } *p++ = ' '; p += strlen(strcpy(p, linkname)); } } /* Update history if we didn't get too many I/O errors above. */ if (Mode != OMrunning || !HISwrite(&Data, Files.Data)) { i = errno; syslog(L_ERROR, "%s cant write history %s %m", LogName, Data.MessageID); (void)sprintf(buff, "%d cant write history, %s", NNTP_RESENDIT_VAL, strerror(errno)); ARTlog(&Data, ART_REJECT, buff); if (distributions) DISPOSE(distributions); ARTreject(buff, article); return buff; } /* If we just flushed the active (above), now flush history. */ if (ICDactivedirty == 0) HISsync(); /* We wrote the history, so modify it and save it for output. */ for (Data.Replic = Files.Data, p = (char *)Data.Replic; *p; p++) if (*p == ' ') *p = ','; Data.ReplicLength = p - Data.Replic; /* Start logging, then propagate the article. */ ARTlog(&Data, Accepted ? ART_ACCEPT : ART_JUNK, (char *)NULL); #if defined(DO_NNTPLINK_LOG) if (fprintf(Log, " (%s)", Data.Name) == EOF || ferror(Log)) { oerrno = errno; syslog(L_ERROR, "%s cant write log_nntplink %m", LogName); IOError("logging nntplink", oerrno); clearerr(Log); } #endif /* defined(DO_NNTPLINK_LOG) */ #if defined(DO_LOG_SIZE) if (fprintf(Log, " %ld",Data.SizeValue) == EOF || ferror (Log)) { oerrno = errno; syslog(L_ERROR, "%s cant write log_nntplink %m", LogName); IOError("logging nntplink", oerrno); clearerr(Log); } #endif ARTpropagate(&Data, hops, hopcount, distributions); if (distributions) DISPOSE(distributions); /* Now that it's been written, process the control message. This has * a small window, if we get a new article before the newgroup message * has been processed. We could pause ourselves here, but it doesn't * seem to be worth it. */ if (Accepted) { if (ControlHeader >= 0) ARTcontrol(&Data, HDR(ControlHeader)); p = HDR(_supersedes); if (*p && ARTidok(p)) ARTcancel(&Data, p, FALSE); } /* If we need the overview data, write it. */ if (NeedOverview) ARTmakeoverview(&Data); /* And finally, send to everyone who should get it */ for (sp = Sites, i = nSites; --i >= 0; sp++) if (sp->Sendit) SITEsend(sp, &Data); return NNTP_TOOKIT; } inn-1.7.2/innd/proc.c0100644000175100001440000000660706443103542012677 0ustar mdusers/* $Revision: 1.14 $ ** ** Process control routines. */ #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" STATIC PROCESS *PROCtable; STATIC int PROCtablesize; STATIC PROCESS PROCnull = { PSfree }; /* ** Collect dead processes. */ STATIC void PROCreap() { int status; register PROCESS *pp; register int i; register PID_T pid; for ( ; ; ) { pid = waitnb(&status); if (pid == 0) break; if (pid < 0) { if (errno != ECHILD) syslog(L_ERROR, "%s cant wait %m", LogName); break; } for (pp = PROCtable, i = PROCtablesize; --i >= 0; pp++) if (pp->Pid == pid) { PROCneedscan = TRUE; pp->Status = status; pp->State = PSdead; pp->Collected = Now.time; break; } } } /* ** Signal handler that collects the processes, then resets the signal. */ STATIC SIGHANDLER PROCcatchsignal(s) int s; { PROCreap(); (void)signal(s, PROCcatchsignal); } /* ** Synchronous version that notifies a site when its process went away. */ void PROCscan() { register PROCESS *pp; register int i; for (pp = PROCtable, i = PROCtablesize; --i >= 0; pp++) if (pp->State == PSdead) { if (pp->Site >= 0) SITEprocdied(&Sites[pp->Site], pp - PROCtable, pp); pp->State = PSfree; } PROCneedscan = FALSE; } #if 0 /* ** Close down all processes. */ void PROCclose(Quickly) BOOL Quickly; { register int sig; register PROCESS *pp; register int i; /* What signal are we sending? */ sig = Quickly ? SIGKILL : SIGTERM; /* Send the signal to all living processes. */ for (pp = PROCtable, i = PROCtablesize; --i >= 0; pp++) { if (pp->State != PSrunning) continue; if (kill(pp->Pid, sig) < 0 && errno != ESRCH) syslog(L_ERROR, "%s cant kill %s %ld %m", LogName, Quickly ? "KILL" : "TERM", (long) pp->Pid); } /* Collect any who might have died. */ PROCreap(); for (pp = PROCtable, i = PROCtablesize; --i >= 0; pp++) if (pp->State == PSdead) *pp = PROCnull; } #endif /* 0 */ /* ** Stop watching a process -- we don't care about it any more. */ void PROCunwatch(process) int process; { if (process < 0 || process >= PROCtablesize) { syslog(L_ERROR, "%s internal PROCunwatch %d", LogName, process); return; } PROCtable[process].Site = -1; } /* ** Add a pid to the list of processes we watch. */ int PROCwatch(pid, site) PID_T pid; int site; { register PROCESS *pp; register int i; /* Find a free slot for this process. */ for (pp = PROCtable, i = PROCtablesize; --i >= 0; pp++) if (pp->State == PSfree) break; if (i < 0) { /* Ran out of room -- grow the table. */ RENEW(PROCtable, PROCESS, PROCtablesize + 20); for (pp = &PROCtable[PROCtablesize], i=20; --i >= 0; pp++) *pp = PROCnull; pp = &PROCtable[PROCtablesize]; PROCtablesize += 20; } pp->State = PSrunning; pp->Pid = pid; pp->Started = Now.time; pp->Site = site; return pp - PROCtable; } /* ** Setup. */ void PROCsetup(i) register int i; { register PROCESS *pp; if (PROCtable) DISPOSE(PROCtable); PROCtablesize = i; PROCtable = NEW(PROCESS, PROCtablesize); for (pp = PROCtable, i = PROCtablesize; --i >= 0; pp++) *pp = PROCnull; #if defined(SIGCHLD) (void)signal(SIGCHLD, PROCcatchsignal); #endif /* defined(SIGCHLD) */ (void)signal(SIGPIPE, PROCcatchsignal); } inn-1.7.2/innd/site.c0100644000175100001440000006742206443103542012702 0ustar mdusers/* $Revision: 1.40 $ ** ** Routines to implement site-feeding. Mainly working with channels to ** do buffering and determine what to send. */ #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" STATIC int SITEcount; STATIC int SITEhead = NOSITE; STATIC int SITEtail = NOSITE; STATIC char SITEshell[] = _PATH_SH; /* ** Called when input is ready to read. Shouldn't happen. */ /* ARGSUSED0 */ STATIC FUNCTYPE SITEreader(cp) CHANNEL *cp; { syslog(L_ERROR, "%s internal SITEreader", LogName); } /* ** Called when write is done. No-op. */ /* ARGSUSED0 */ STATIC FUNCTYPE SITEwritedone(cp) CHANNEL *cp; { } /* ** Make a site start spooling. */ BOOL SITEspool(sp, cp) register SITE *sp; CHANNEL *cp; { int i; char buff[SPOOLNAMEBUFF]; char *name; name = sp->SpoolName; i = open(name, O_APPEND | O_CREAT | O_WRONLY, BATCHFILE_MODE); if (i < 0 && errno == EISDIR) { FileGlue(buff, sp->SpoolName, '/', "togo"); name = buff; i = open(buff, O_APPEND | O_CREAT | O_WRONLY, BATCHFILE_MODE); } if (i < 0) { i = errno; syslog(L_ERROR, "%s cant open %s %m", sp->Name, name); IOError("site batch file", i); sp->Channel = NULL; return FALSE; } if (AmRoot) xchown(name); if (cp) { if (cp->fd >= 0) syslog(L_ERROR, "DEBUG ERROR SITEspool trashed:%d %s:%d", cp->fd, sp->Name, i); /* CPU-eating bug, killed by kre. */ WCHANremove(cp); RCHANremove(cp); SCHANremove(cp); (void)close(cp->fd); cp->fd = i; return TRUE; } sp->Channel = CHANcreate(i, CTfile, CSwriting, SITEreader, SITEwritedone); if (sp->Channel == NULL) { syslog(L_ERROR, "%s cant channel %m", sp->Name); (void)close(i); return FALSE; } WCHANset(sp->Channel, "", 0); sp->Spooling = TRUE; return TRUE; } /* ** Delete a site from the file writing list. Can be called even if ** site is not on the list. */ static void SITEunlink(sp) SITE *sp; { if (sp->Next != NOSITE || sp->Prev != NOSITE || (SITEhead != NOSITE && sp == &Sites[SITEhead])) SITEcount--; if (sp->Next != NOSITE) Sites[sp->Next].Prev = sp->Prev; else if (SITEtail != NOSITE && sp == &Sites[SITEtail]) SITEtail = sp->Prev; if (sp->Prev != NOSITE) Sites[sp->Prev].Next = sp->Next; else if (SITEhead != NOSITE && sp == &Sites[SITEhead]) SITEhead = sp->Next; sp->Next = sp->Prev = NOSITE; } /* ** Find the oldest "file feed" site and buffer it. */ STATIC void SITEbufferoldest() { register SITE *sp; register BUFFER *bp; register BUFFER *out; /* Get the oldest user of a file. */ if (SITEtail == NOSITE) { syslog(L_ERROR, "%s internal no oldest site found", LogName); SITEcount = 0; return; } sp = &Sites[SITEtail]; SITEunlink(sp); if (sp->Buffered) { syslog(L_ERROR, "%s internal oldest (%s) was buffered", LogName, sp->Name); return; } if (sp->Type != FTfile) { syslog(L_ERROR, "%s internal oldest (%s) not FTfile", LogName, sp->Name); return; } /* Write out what we can. */ (void)WCHANflush(sp->Channel); /* Get a buffer for the site. */ sp->Buffered = TRUE; bp = &sp->Buffer; bp->Used = 0; bp->Left = 0; if (bp->Size == 0) { bp->Size = sp->Flushpoint; bp->Data = NEW(char, bp->Size); } else { bp->Size = sp->Flushpoint; RENEW(bp->Data, char, bp->Size); } /* If there's any unwritten data, copy it. */ out = &sp->Channel->Out; if (out->Left) { BUFFset(bp, &out->Data[out->Used], out->Left); out->Left = 0; } /* Now close the original channel. */ CHANclose(sp->Channel, sp->Name); sp->Channel = NULL; } /* * * Bilge Site's Channel out buffer. */ STATIC BOOL SITECHANbilge(sp) register SITE *sp; { int fd, i; char buff[SPOOLNAMEBUFF]; char *name; name = sp->SpoolName; fd = open(name, O_APPEND | O_CREAT | O_WRONLY, BATCHFILE_MODE); if (fd < 0 && errno == EISDIR) { FileGlue(buff, sp->SpoolName, '/', "togo"); name = buff; fd = open(buff, O_APPEND | O_CREAT | O_WRONLY, BATCHFILE_MODE); } if (fd < 0) { int oerrno = errno ; syslog(L_ERROR, "%s cant open %s %m", sp->Name, name); IOError("site batch file",oerrno); sp->Channel = NULL; return FALSE; } while(sp->Channel->Out.Left > 0) { i = write(fd, (POINTER) &sp->Channel->Out.Data[sp->Channel->Out.Used], (SIZE_T) sp->Channel->Out.Left); if(i <= 0) { syslog(L_ERROR,"%s cant spool count %d",CHANname(sp->Channel), sp->Channel->Out.Left); close(fd); return FALSE; } sp->Channel->Out.Left -= i; sp->Channel->Out.Used += i; } close(fd); DISPOSE(sp->Channel->Out.Data); sp->Channel->Out.Data = NEW(char, SMBUF); sp->Channel->Out.Size = SMBUF; sp->Channel->Out.Left = 0; sp->Channel->Out.Used = 0; return TRUE; } /* ** Check if we need to write out the site's buffer. If we're buffered ** or the feed is backed up, this gets a bit complicated. */ STATIC void SITEflushcheck(sp, bp) register SITE *sp; register BUFFER *bp; { register int i; register CHANNEL *cp; /* If we're buffered, and we hit the flushpoint, do an LRU. */ if (sp->Buffered) { if (bp->Left < sp->Flushpoint) return; while (SITEcount >= MaxOutgoing) SITEbufferoldest(); if (!SITEsetup(sp) || sp->Buffered) { syslog(L_ERROR, "%s cant unbuffer %m", sp->Name); return; } WCHANsetfrombuffer(sp->Channel, bp); WCHANadd(sp->Channel); /* Reset buffer; data has been moved. */ BUFFset(bp, "", 0); } if (PROCneedscan) PROCscan(); /* Handle buffering. */ cp = sp->Channel; i = cp->Out.Left; if (i < sp->StopWriting) WCHANremove(cp); if ((sp->StartWriting == 0 || i > sp->StartWriting) && !CHANsleeping(cp)) { if (sp->Type == FTchannel) { /* channel feed, try the write */ int j; if (bp->Left == 0) return; j = write(cp->fd, (POINTER)&bp->Data[bp->Used], (SIZE_T)bp->Left); if (j > 0) { bp->Left -= j; bp->Used += j; i = cp->Out.Left; } if (bp->Left <= 0) { /* reset Used, Left on bp, keep channel buffer size from exploding. */ bp->Used = bp->Left = 0; WCHANremove(cp); } else WCHANadd(cp); } else WCHANadd(cp); } cp->LastActive = Now.time; /* If we're a channel that's getting big, see if we need to spool. */ if (sp->Type == FTfile || sp->StartSpooling == 0 || i < sp->StartSpooling) return; syslog(L_ERROR, "%s spooling %d bytes", sp->Name, i); if(!SITECHANbilge(sp)) { syslog(L_ERROR, "%s overflow %d bytes", sp->Name, i); return; } } /* ** Send a control line to an exploder. */ void SITEwrite(sp, text) register SITE *sp; STRING text; { static char PREFIX[] = { EXP_CONTROL, '\0' }; register BUFFER *bp; if (sp->Buffered) bp = &sp->Buffer; else { if (sp->Channel == NULL) return; sp->Channel->LastActive = Now.time; bp = &sp->Channel->Out; } BUFFappend(bp, PREFIX, STRLEN(PREFIX)); BUFFappend(bp, text, (int)strlen(text)); BUFFappend(bp, "\n", 1); if (sp->Channel != NULL) WCHANadd(sp->Channel); } /* ** Send the desired data about an article down a channel. */ STATIC void SITEwritefromflags(sp, Data) register SITE *sp; ARTDATA *Data; { static char ITEMSEP[] = " "; static char NL[] = "\n"; char pbuff[12]; register char *p; register BOOL Dirty; register BUFFER *bp; register SITE *spx; register int i; if (sp->Buffered) bp = &sp->Buffer; else { /* This should not happen, but if we tried to spool and failed, * e.g., because of a bad F param for this site, we can get * into this state. We already logged a message so give up. */ if (sp->Channel == NULL) return; bp = &sp->Channel->Out; } for (Dirty = FALSE, p = sp->FileFlags; *p; p++) { switch (*p) { default: syslog(L_ERROR, "%s internal SITEwritefromflags %c", sp->Name, *p); continue; case FEED_BYTESIZE: if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); BUFFappend(bp, Data->Size, Data->SizeLength); break; case FEED_FULLNAME: if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); BUFFappend(bp, SPOOL, SPOOLlen); BUFFappend(bp, "/", 1); BUFFappend(bp, Data->Name, Data->NameLength); break; case FEED_HDR_DISTRIB: if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); BUFFappend(bp, Data->Distribution, Data->DistributionLength); break; case FEED_HDR_NEWSGROUP: if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); BUFFappend(bp, Data->Newsgroups, Data->NewsgroupsLength); break; case FEED_HEADERS: if (Dirty) BUFFappend(bp, NL, STRLEN(NL)); BUFFappend(bp, Data->Headers->Data, Data->Headers->Left); break; case FEED_OVERVIEW: if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); BUFFappend(bp, Data->Overview->Data, Data->Overview->Left); break; case FEED_REPLIC: if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); BUFFappend(bp, Data->Replic, Data->ReplicLength); break; case FEED_TIMERECEIVED: if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); BUFFappend(bp, Data->TimeReceived, Data->TimeReceivedLength); break; case FEED_TIMEPOSTED: if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); sprintf(pbuff, "%ld", Data->Posted); BUFFappend(bp, pbuff, strlen(pbuff)); break; case FEED_MESSAGEID: if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); BUFFappend(bp, Data->MessageID, Data->MessageIDLength); break; case FEED_FNLNAMES: if (sp->FNLnames.Data) { /* Funnel; write names of our sites that got it. */ if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); BUFFappend(bp, sp->FNLnames.Data, sp->FNLnames.Used); } else { /* Not funnel; write names of all sites that got it. */ for (spx = Sites, i = nSites; --i >= 0; spx++) if (spx->Sendit) { if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); BUFFappend(bp, spx->Name, spx->NameLength); Dirty = TRUE; } } break; case FEED_NAME: if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); BUFFappend(bp, Data->Name, Data->NameLength); break; case FEED_NEWSGROUP: if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); if (sp->ng) BUFFappend(bp, sp->ng->Name, sp->ng->NameLength); else BUFFappend(bp, "?", 1); break; case FEED_SITE: if (Dirty) BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP)); BUFFappend(bp, Data->Feedsite, Data->FeedsiteLength); break; } Dirty = TRUE; } if (Dirty) { BUFFappend(bp, "\n", 1); SITEflushcheck(sp, bp); } } /* ** Send one article to a site. */ void SITEsend(sp, Data) register SITE *sp; ARTDATA *Data; { register int i; register char *p; char *temp; char buff[BUFSIZ]; STRING argv[MAX_BUILTIN_ARGV]; int fd; switch (sp->Type) { default: syslog(L_ERROR, "%s internal SITEsend type %d", sp->Name, sp->Type); break; case FTlogonly: break; case FTfunnel: syslog(L_ERROR, "%s funnel_send", sp->Name); break; case FTfile: case FTchannel: case FTexploder: SITEwritefromflags(sp, Data); break; case FTprogram: /* Set up the argument vector. */ if (sp->FNLwantsnames) { i = strlen(sp->Param) + sp->FNLnames.Used; if (i + strlen(Data->Name) >= sizeof buff) { syslog(L_ERROR, "%s toolong need %d for %s", sp->Name, i + strlen(Data->Name), Data->Name); break; } temp = NEW(char, i + 1); p = strchr(sp->Param, '*'); *p = '\0'; (void)strcpy(temp, sp->Param); (void)strcat(temp, sp->FNLnames.Data); (void)strcat(temp, &p[1]); *p = '*'; (void)sprintf(buff, temp, Data->Name); DISPOSE(temp); } else (void)sprintf(buff, sp->Param, Data->Name); if (NeedShell(buff, argv, ENDOF(argv))) { argv[0] = SITEshell; argv[1] = "-c"; argv[2] = buff; argv[3] = NULL; } /* Feed the article on standard input. */ fd = open(Data->Name, O_RDONLY); if (fd < 0) { /* Unlikely, but we could check if the article is cross-posted * and try it under other names... */ syslog(L_ERROR, "%s cant open %s %m", sp->Name, Data->Name); fd = 0; } /* Start the process. */ i = Spawn(fd, (int)fileno(Errlog), (int)fileno(Errlog), argv); if (i >= 0) (void)PROCwatch(i, -1); if (fd != 0) (void)close(fd); break; } } /* ** The channel was sleeping because we had to spool our output to ** a file. Flush and restart. */ STATIC FUNCTYPE SITEspoolwake(cp) CHANNEL *cp; { SITE *sp; int *ip; ip = CAST(int*, cp->Argument); sp = &Sites[*ip]; DISPOSE(cp->Argument); cp->Argument = NULL; if (sp->Channel != cp) { syslog(L_ERROR, "%s internal SITEspoolwake %s got %d, not %d", LogName, sp->Name, cp->fd, sp->Channel->fd); return; } syslog(L_NOTICE, "%s spoolwake", sp->Name); SITEflush(sp, TRUE); } /* ** Start up a process for a channel, or a spool to a file if we can't. ** Create a channel for the site to talk to. */ STATIC BOOL SITEstartprocess(sp) SITE *sp; { register PID_T i; STRING argv[MAX_BUILTIN_ARGV]; char *process; int *ip; int pan[2]; /* Create a pipe. */ if (pipe(pan) < 0) { syslog(L_ERROR, "%s cant pipe %m", sp->Name); return FALSE; } CloseOnExec(pan[PIPE_WRITE], TRUE); /* Set up the argument vector. */ process = COPY(sp->Param); if (NeedShell(process, argv, ENDOF(argv))) { argv[0] = SITEshell; argv[1] = "-c"; argv[2] = process; argv[3] = NULL; } /* Fork a child. */ i = Spawn(pan[PIPE_READ], (int)fileno(Errlog), (int)fileno(Errlog), argv); if (i > 0) { sp->pid = i; sp->Spooling = FALSE; sp->Process = PROCwatch(i, sp - Sites); (void)close(pan[PIPE_READ]); sp->Channel = CHANcreate(pan[PIPE_WRITE], sp->Type == FTchannel ? CTprocess : CTexploder, CSwriting, SITEreader, SITEwritedone); DISPOSE(process); return TRUE; } /* Error. Switch to spooling. */ syslog(L_ERROR, "%s cant spawn spooling %m", sp->Name); (void)close(pan[PIPE_WRITE]); (void)close(pan[PIPE_READ]); DISPOSE(process); if (!SITEspool(sp, (CHANNEL *)NULL)) return FALSE; /* We'll try to restart the channel later. */ syslog(L_ERROR, "%s cant spawn spooling %m", sp->Name); ip = NEW(int, 1); *ip = sp - Sites; SCHANadd(sp->Channel, (time_t)(Now.time + CHANNEL_RETRY_TIME), (POINTER)NULL, SITEspoolwake, (POINTER)ip); return TRUE; } /* ** Set up a site for internal buffering. */ STATIC void SITEbuffer(sp) register SITE *sp; { register BUFFER *bp; SITEunlink(sp); sp->Buffered = TRUE; sp->Channel = NULL; bp = &sp->Buffer; if (bp->Size == 0) { bp->Size = sp->Flushpoint; bp->Data = NEW(char, bp->Size); BUFFset(bp, "", 0); } else if (bp->Size < sp->Flushpoint) { bp->Size = sp->Flushpoint; RENEW(bp->Data, char, bp->Size); } BUFFset(bp, "", 0); syslog(L_NOTICE, "%s buffered", sp->Name); } /* ** Link a site at the head of the "currently writing to a file" list */ static void SITEmovetohead(sp) SITE *sp; { if (SITEhead == NOSITE && (sp->Next != NOSITE || sp->Prev != NOSITE || sp == &Sites[SITEhead] || sp == &Sites[SITEtail])) SITEunlink(sp); if ((sp->Next = SITEhead) != NOSITE) Sites[SITEhead].Prev = sp - Sites; sp->Prev = NOSITE; SITEhead = sp - Sites; if (SITEtail == NOSITE) SITEtail = sp - Sites; SITEcount++; } /* ** Set up a site's feed. This means opening a file or channel if needed. */ BOOL SITEsetup(sp) register SITE *sp; { int fd; int oerrno; switch (sp->Type) { default: syslog(L_ERROR, "%s internal SITEsetup %d", sp->Name, sp->Type); return FALSE; case FTfunnel: case FTlogonly: case FTprogram: /* Nothing to do here. */ break; case FTfile: if (SITEcount >= MaxOutgoing) SITEbuffer(sp); else { sp->Buffered = FALSE; fd = open(sp->Param, O_APPEND | O_CREAT | O_WRONLY, BATCHFILE_MODE); if (fd < 0) { if (errno == EMFILE) { syslog(L_ERROR, "%s cant open %s %m", sp->Name, sp->Param); SITEbuffer(sp); break; } oerrno = errno; syslog(L_NOTICE, "%s cant open %s %m", sp->Name, sp->Param); IOError("site file", oerrno); return FALSE; } SITEmovetohead(sp); if (AmRoot) xchown(sp->Param); sp->Channel = CHANcreate(fd, CTfile, CSwriting, SITEreader, SITEwritedone); syslog(L_NOTICE, "%s opened %s", sp->Name, CHANname(sp->Channel)); WCHANset(sp->Channel, "", 0); } break; case FTchannel: case FTexploder: if (!SITEstartprocess(sp)) return FALSE; syslog(L_NOTICE, "%s spawned %s", sp->Name, CHANname(sp->Channel)); WCHANset(sp->Channel, "", 0); WCHANadd(sp->Channel); break; } return TRUE; } /* ** A site's channel process died; restart it. */ void SITEprocdied(sp, process, pp) SITE *sp; int process; PROCESS *pp; { syslog(pp->Status ? L_ERROR : L_NOTICE, "%s exit %d elapsed %ld pid %ld", sp->Name ? sp->Name : "?", pp->Status, pp->Collected - pp->Started, (long)pp->Pid); if (sp->Process != process || sp->Name == NULL) /* We already started a new process for this channel * or this site has been dropped. */ return; if (sp->Channel != NULL) CHANclose(sp->Channel, CHANname(sp->Channel)); sp->Working = SITEsetup(sp); if (!sp->Working) { syslog(L_ERROR, "%s cant restart %m", sp->Name); return; } syslog(L_NOTICE, "%s restarted", sp->Name); } /* ** A channel is about to be closed; see if any site cares. */ void SITEchanclose(cp) register CHANNEL *cp; { register int i; register SITE *sp; int *ip; for (i = nSites, sp = Sites; --i >= 0; sp++) if (sp->Channel == cp) { /* Found the site that has this channel. Start that * site spooling, copy any data that might be pending, * and arrange to retry later. */ if (!SITEspool(sp, (CHANNEL *)NULL)) { syslog(L_ERROR, "%s loss %d bytes", sp->Name, cp->Out.Left); return; } WCHANsetfrombuffer(sp->Channel, &cp->Out); WCHANadd(sp->Channel); ip = NEW(int, 1); *ip = sp - Sites; SCHANadd(sp->Channel, (time_t)(Now.time + CHANNEL_RETRY_TIME), (POINTER)NULL, SITEspoolwake, (POINTER)ip); break; } } /* ** Flush any pending data waiting to be sent. */ void SITEflush(sp, Restart) register SITE *sp; BOOL Restart; { register CHANNEL *cp; register BUFFER *out; int count; if (sp->Name == NULL) return; if (Restart) SITEforward(sp, "flush"); switch (sp->Type) { default: syslog(L_ERROR, "%s internal SITEflush %d", sp->Name, sp->Type); return; case FTlogonly: case FTprogram: case FTfunnel: /* Nothing to do here. */ return; case FTchannel: case FTexploder: /* If spooling, close the file right now -- documented behavior. */ if (sp->Spooling && (cp = sp->Channel) != NULL) { (void)WCHANflush(cp); CHANclose(cp, CHANname(cp)); sp->Channel = NULL; } break; case FTfile: /* We must ensure we have a file open for this site, so if * we're buffered we HACK and pretend we have no sites * for a moment. */ if (sp->Buffered) { count = SITEcount; SITEcount = 0; if (!SITEsetup(sp) || sp->Buffered) syslog(L_ERROR, "%s cant unbuffer to flush", sp->Name); else BUFFswap(&sp->Buffer, &sp->Channel->Out); SITEcount += count; } break; } /* We're only dealing with files and channels now. */ if ((cp = sp->Channel) != NULL) (void)WCHANflush(cp); /* Restart the site, copy any pending data. */ if (Restart) { if (!SITEsetup(sp)) syslog(L_ERROR, "%s cant restart %m", sp->Name); else if (cp != NULL) { if (sp->Buffered) { /* SITEsetup had to buffer us; save any residue. */ out = &cp->Out; if (out->Left) BUFFset(&sp->Buffer, &out->Data[out->Used], out->Left); } else WCHANsetfrombuffer(sp->Channel, &cp->Out); } } else if (cp != NULL && cp->Out.Left) { if (sp->Type == FTfile || sp->Spooling) { /* Can't flush a file? Hopeless. */ syslog(L_ERROR, "%s dataloss %d", sp->Name, cp->Out.Left); return; } /* Must be a working channel; spool and retry. */ syslog(L_ERROR, "%s spooling %d bytes", sp->Name, cp->Out.Left); if (SITEspool(sp, cp)) SITEflush(sp, FALSE); return; } /* Close the old channel if it was open. */ if (cp != NULL) { /* Make sure we have no dangling pointers to it. */ if (!Restart) sp->Channel = NULL; CHANclose(cp, sp->Name); if (sp->Type == FTfile) SITEunlink(sp); } } /* ** Flush all sites. */ void SITEflushall(Restart) BOOL Restart; { register int i; register SITE *sp; for (i = nSites, sp = Sites; --i >= 0; sp++) if (sp->Name) SITEflush(sp, Restart); } /* ** Run down the site's pattern list and see if it wants the specified ** newsgroup. */ BOOL SITEwantsgroup(sp, name) register SITE *sp; register char *name; { register BOOL match; register BOOL subvalue; register char *pat; register char **argv; match = SUB_DEFAULT; if (ME.Patterns) { for (argv = ME.Patterns; (pat = *argv++) != NULL; ) { subvalue = *pat != SUB_NEGATE && *pat != SUB_POISON; if (!subvalue) pat++; if ((match != subvalue) && wildmat(name, pat)) match = subvalue; } } for (argv = sp->Patterns; (pat = *argv++) != NULL; ) { subvalue = *pat != SUB_NEGATE && *pat != SUB_POISON; if (!subvalue) pat++; if ((match != subvalue) && wildmat(name, pat)) match = subvalue; } return match; } /* ** Run down the site's pattern list and see if specified newsgroup is ** considered poison. */ BOOL SITEpoisongroup(sp, name) register SITE *sp; register char *name; { register BOOL match; register BOOL poisonvalue; register char *pat; register char **argv; match = SUB_DEFAULT; if (ME.Patterns) { for (argv = ME.Patterns; (pat = *argv++) != NULL; ) { poisonvalue = *pat == SUB_POISON; if (*pat == SUB_NEGATE || *pat == SUB_POISON) pat++; if (wildmat(name, pat)) match = poisonvalue; } } for (argv = sp->Patterns; (pat = *argv++) != NULL; ) { poisonvalue = *pat == SUB_POISON; if (*pat == SUB_NEGATE || *pat == SUB_POISON) pat++; if (wildmat(name, pat)) match = poisonvalue; } return match; } /* ** Find a site. */ SITE * SITEfind(p) char *p; { register int i; register SITE *sp; for (i = nSites, sp = Sites; --i >= 0; sp++) if (sp->Name && caseEQ(p, sp->Name)) return sp; return NULL; } /* ** Find the next site that matches this site. */ SITE * SITEfindnext(p, sp) char *p; register SITE *sp; { register SITE *end; for (sp++, end = &Sites[nSites]; sp < end; sp++) if (sp->Name && caseEQ(p, sp->Name)) return sp; return NULL; } /* ** Close a site down. */ void SITEfree(sp) register SITE *sp; { register SITE *s; register int new; register int i; if (sp->Channel) { CHANclose(sp->Channel, CHANname(sp->Channel)); sp->Channel = NULL; } SITEunlink(sp); sp->Name = NULL; if (sp->Process > 0) { /* Kill the backpointer so PROCdied won't call us. */ PROCunwatch(sp->Process); sp->Process = -1; } if (sp->Entry) { DISPOSE(sp->Entry); sp->Entry = NULL; } if (sp->Param) { DISPOSE(sp->Param); sp->Param = NULL; } if (sp->SpoolName) { DISPOSE(sp->SpoolName); sp->SpoolName = NULL; } if (sp->Patterns) { DISPOSE(sp->Patterns); sp->Patterns = NULL; } if (sp->Exclusions) { DISPOSE(sp->Exclusions); sp->Exclusions = NULL; } if (sp->Distributions) { DISPOSE(sp->Distributions); sp->Distributions = NULL; } if (sp->Buffer.Data) { DISPOSE(sp->Buffer.Data); sp->Buffer.Data = NULL; sp->Buffer.Size = 0; } if (sp->FNLnames.Data) { DISPOSE(sp->FNLnames.Data); sp->FNLnames.Data = NULL; sp->FNLnames.Size = 0; } /* If this site was a master, find a new one. */ if (sp->IsMaster) { for (new = NOSITE, s = Sites, i = nSites; --i >= 0; s++) if (&Sites[s->Master] == sp) if (new == NOSITE) { s->Master = NOSITE; s->IsMaster = TRUE; new = s - Sites; } else s->Master = new; sp->IsMaster = FALSE; } } /* ** If a site is an exploder or funnels into one, forward a command ** to it. */ void SITEforward(sp, text) register SITE *sp; char *text; { register SITE *fsp; register char *p; char buff[SMBUF]; fsp = sp; if (fsp->Funnel != NOSITE) fsp = &Sites[fsp->Funnel]; if (sp->Name == NULL || fsp->Name == NULL) return; if (fsp->Type == FTexploder) { (void)strcpy(buff, text); if (fsp != sp && fsp->FNLwantsnames) { p = buff + strlen(buff); *p++ = ' '; (void)strcpy(p, sp->Name); } SITEwrite(fsp, buff); } } /* ** Drop a site. */ void SITEdrop(sp) SITE *sp; { SITEforward(sp, "drop"); SITEflush(sp, FALSE); SITEfree(sp); } /* ** Append info about the current state of the site to the buffer */ void SITEinfo(bp, sp, Verbose) register BUFFER *bp; register SITE *sp; BOOL Verbose; { static char FREESITE[] = "<>\n\n"; register char *p; register CHANNEL *cp; char *sep; char buff[BUFSIZ]; if (sp->Name == NULL) { BUFFappend(bp, FREESITE, STRLEN(FREESITE)); return; } p = buff; (void)sprintf(buff, "%s%s:\t", sp->Name, sp->IsMaster ? "(*)" : ""); p += strlen(p); if (sp->Type == FTfunnel) { sp = &Sites[sp->Funnel]; (void)sprintf(p, "funnel -> %s: ", sp->Name); p += strlen(p); } switch (sp->Type) { default: (void)sprintf(p, "unknown feed type %d", sp->Type); p += strlen(p); break; case FTerror: case FTfile: p += strlen(strcpy(p, "file")); if (sp->Buffered) { (void)sprintf(p, " buffered(%ld)", sp->Buffer.Left); p += strlen(p); } else if ((cp = sp->Channel) == NULL) p += strlen(strcpy(p, " no channel?")); else { (void)sprintf(p, " open fd=%d, in mem %ld", cp->fd, cp->Out.Left); p += strlen(p); } break; case FTchannel: p += strlen(strcpy(p, "channel")); goto Common; case FTexploder: p += strlen(strcpy(p, "exploder")); Common: if (sp->Process >= 0) { (void)sprintf(p, " pid=%ld", (long) sp->pid); p += strlen(p); } if (sp->Spooling) p += strlen(strcpy(p, " spooling")); if ((cp = sp->Channel) == NULL) p += strlen(strcpy(p, " no channel?")); else { (void)sprintf(p, " fd=%d, in mem %ld", cp->fd, cp->Out.Left); p += strlen(p); } break; case FTfunnel: p += strlen(strcpy(p, "recursive funnel")); break; case FTlogonly: p += strlen(strcpy(p, "log only")); break; case FTprogram: p += strlen(strcpy(p, "program")); if (sp->FNLwantsnames) p += strlen(strcpy(p, " with names")); break; } *p++ = '\n'; if (Verbose) { sep = "\t"; if (sp->Buffered && sp->Flushpoint) { (void)sprintf(p, "%sFlush @ %ld", sep, sp->Flushpoint); p += strlen(p); sep = "; "; } if (sp->StartWriting || sp->StopWriting) { (void)sprintf(p, "%sWrite [%ld..%ld]", sep, sp->StopWriting, sp->StartWriting); p += strlen(p); sep = "; "; } if (sp->StartSpooling) { (void)sprintf(p, "%sSpool @ %ld", sep, sp->StartSpooling); p += strlen(p); sep = "; "; } if (sep[0] != '\t') *p++ = '\n'; if (sp->Spooling && sp->SpoolName) { (void)sprintf(p, "\tSpooling to \"%s\"\n", sp->SpoolName); p += strlen(p); } if ((cp = sp->Channel) != NULL) { (void)sprintf(p, "\tChannel created %.12s", ctime(&cp->Started) + 4); p += strlen(p); (void)sprintf(p, ", last active %.12s\n", ctime(&cp->LastActive) + 4); p += strlen(p); if (cp->Waketime > Now.time) { (void)sprintf("\tSleeping until %.12s\n", ctime(&cp->Waketime) + 4); p += strlen(p); } } } BUFFappend(bp, buff, p - buff); } inn-1.7.2/innd/perl.c0100644000175100001440000000637706443103542012702 0ustar mdusers/* -*- c -*- * * Author: Christophe Wolfhugel * (although he wouldn't recognise it anymore so don't blame him) * File: perl.c * RCSId: $Id: perl.c,v 1.5 1996/12/17 00:16:26 brister Exp $ * Description: perl support for innd. * */ #if ! defined (lint) static const char *rcsid = "$Id: perl.c,v 1.5 1996/12/17 00:16:26 brister Exp $" ; static void use_rcsid (const char *rid) { /* Never called */ use_rcsid (rcsid) ; use_rcsid (rid) ; } #endif #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" #include "art.h" #if defined(DO_PERL) #include #include extern BOOL PerlFilterActive; extern ARTHEADER ARTheaders[], *ARTheadersENDOF; extern CV *perl_filter_cv ; extern char *pathForPerl ; char * HandleArticle() { dSP; ARTHEADER *hp; HV *hdr; int rc; char *p; static char buf[256]; if (!PerlFilterActive || perl_filter_cv == NULL) return NULL; /* Create the Perl Hash */ hdr = perl_get_hv("hdr", TRUE); for (hp = ARTheaders; hp < ARTheadersENDOF; hp++) { if (hp->Found && hp->Value && strcmp (hp->Name,"Path") != 0) hv_store(hdr, (char *) hp->Name, strlen(hp->Name), newSVpv(hp->Value, 0), 0); } if (pathForPerl != NULL) { char *p = strchr (pathForPerl,'\n') ; *p = '\0' ; hv_store (hdr, (char *) "Path", 4, newSVpv(pathForPerl,0), 0) ; *p = '\n' ; } ENTER ; SAVETMPS ; rc = perl_call_argv ("filter_art", G_EVAL|G_SCALAR,NULL); SPAGAIN; hv_undef(hdr); buf [0] = '\0' ; if (SvTRUE(GvSV(errgv))) /* check $@ */ { syslog (L_ERROR,"Perl function filter_art died: %s", SvPV(GvSV(errgv), na)) ; POPs ; PerlFilter (FALSE) ; } else if (rc == 1) { p = POPp; if (p != NULL && *p != '\0') { strncpy(buf, p, sizeof(buf) - 1); buf[sizeof(buf) - 1] = '\0'; } } PUTBACK; FREETMPS; LEAVE; if (buf[0] != '\0') return buf ; return NULL; } void PerlMode(Mode, NewMode, reason) OPERATINGMODE Mode, NewMode; char *reason; { dSP ; HV *hdr; ENTER ; SAVETMPS ; hdr = perl_get_hv("mode", TRUE); if (Mode == OMrunning) hv_store(hdr, "Mode", 4, newSVpv("running", 0), 0); if (Mode == OMpaused) hv_store(hdr, "Mode", 4, newSVpv("paused", 0), 0); if (Mode == OMthrottled) hv_store(hdr, "Mode", 4, newSVpv("throttled", 0), 0); if (NewMode == OMrunning) hv_store(hdr, "NewMode", 7, newSVpv("running", 0), 0); if (NewMode == OMpaused) hv_store(hdr, "NewMode", 7, newSVpv("paused", 0), 0); if (NewMode == OMthrottled) hv_store(hdr, "NewMode", 7, newSVpv("throttled", 0), 0); hv_store(hdr, "reason", 6, newSVpv(reason, 0), 0); if (perl_get_cv("filter_mode", FALSE) != NULL) { perl_call_argv("filter_mode", G_EVAL|G_DISCARD|G_NOARGS, NULL); if (SvTRUE(GvSV(errgv))) { /* check $@ */ syslog (L_ERROR,"Perl function filter_mode died: %s", SvPV(GvSV(errgv), na)) ; POPs ; PerlFilter (FALSE) ; } } FREETMPS ; LEAVE ; } #endif /* defined(DO_PERL) */ inn-1.7.2/innd/nc.c0100644000175100001440000011530706443103542012332 0ustar mdusers/* $Revision: 1.51 $ ** ** Routines for the NNTP channel. Other channels get the descriptors which ** we turn into NNTP channels, and over which we speak NNTP. */ #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" #include "dbz.h" #define BAD_COMMAND_COUNT 10 #define WIP_CHECK (1 * 60) #define SAVE_AMT 10 #define ART_EOF(c, s) \ ((c) >= 5 && (s)[-5] == '\r' && (s)[-4] == '\n' && (s)[-3] == '.' \ && (s)[-2] == '\r' && (s)[-1] == '\n') /* ** An entry in the dispatch table. The name, and implementing function, ** of every command we support. */ typedef struct _NCDISPATCH { STRING Name; FUNCPTR Function; int Size; } NCDISPATCH; /* ** Information about the work in progress on all our open channels. */ typedef struct _WIP { char *MessageID; long Size; time_t Timestamp; BUFFER Replic; BOOL Wanted; } WIP; #if 0 static FUNCTYPE NCarticle(); #endif /* 0 */ static FUNCTYPE NCauthinfo(); static FUNCTYPE NChead(); static FUNCTYPE NChelp(); static FUNCTYPE NCihave(); static FUNCTYPE NClist(); static FUNCTYPE NCmode(); static FUNCTYPE NCquit(); static FUNCTYPE NCstat(); static FUNCTYPE NCxpath(); static FUNCTYPE NCxreplic(); static FUNCTYPE NC_unimp(); /* new modules for streaming */ static FUNCTYPE NCxbatch(); static FUNCTYPE NCcheck(); static FUNCTYPE NCtakethis(); static FUNCTYPE NCwritedone(); STATIC int NCcount; /* Number of open connections */ STATIC int NCwipsize; /* Size of NCwip array */ STATIC char *NCfreelist[5]; /* Free string list */ STATIC WIP *NCwip; /* Work-in-progress */ STATIC WIP NCnullwip; STATIC NCDISPATCH NCcommands[] = { #if 0 { "article", NCarticle }, #else { "article", NC_unimp }, #endif /* 0 */ { "authinfo", NCauthinfo }, { "help", NChelp }, { "ihave", NCihave }, { "check", NCcheck }, { "takethis", NCtakethis }, { "list", NClist }, { "mode", NCmode }, { "quit", NCquit }, { "head", NChead }, { "stat", NCstat }, { "body", NC_unimp }, { "group", NC_unimp }, { "last", NC_unimp }, { "newgroups", NC_unimp }, { "newnews", NC_unimp }, { "next", NC_unimp }, { "post", NC_unimp }, { "slave", NC_unimp }, { "xbatch", NCxbatch }, { "xhdr", NC_unimp }, { "xpath", NCxpath }, { "xreplic", NCxreplic } }; STATIC char *NCquietlist[] = { INND_QUIET_BADLIST }; STATIC char NCterm[] = "\r\n"; STATIC char NCdotterm[] = ".\r\n"; STATIC char NCdot[] = "." ; STATIC char NCbadcommand[] = NNTP_BAD_COMMAND; STATIC STRING NCgreeting; /* ** Clear the work-in-progress entry and wake up anyone who might ** have been waiting for us. */ STATIC void NCclearwip(wp) register WIP *wp; { char *p; if ((p = wp->MessageID) != NULL) *p = '\0'; wp->Size = 0; if (wp->Wanted) { wp->Wanted = FALSE; SCHANwakeup((POINTER)wp); } } /* ** Write an NNTP reply message. ** ** Tries to do the actual write immediately if it will not block ** and if there is not already other buffered output. Then, if the ** write is successful, calls NCwritedone (which does whatever is ** necessary to accommodate state changes). Else, NCwritedone will ** be called from the main select loop later. ** ** If the reply that we are writing now is associated with a ** state change, then cp->State must be set to its new value ** *before* NCwritereply is called. */ STATIC void NCwritereply(cp, text) CHANNEL *cp; char *text; { register BUFFER *bp; register int i; /* XXX could do RCHANremove(cp) here, as the old NCwritetext() used to * do, but that would be wrong if the channel is sreaming (because it * would zap the channell's input buffer). There's no harm in * never calling RCHANremove here. */ bp = &cp->Out; i = bp->Left; WCHANappend(cp, text, (int)strlen(text)); /* text in buffer */ WCHANappend(cp, NCterm, STRLEN(NCterm)); /* add CR NL to text */ if (i == 0) { /* if only data then try to write directly */ i = write(cp->fd, &bp->Data[bp->Used], bp->Left); if (Tracing || cp->Tracing) syslog(L_TRACE, "%s NCwritereply %d=write(%d, \"%.15s\", %d)", CHANname(cp), i, cp->fd, &bp->Data[bp->Used], bp->Left); if (i > 0) bp->Used += i; if (bp->Used == bp->Left) { /* all the data was written */ bp->Used = bp->Left = 0; NCwritedone(cp); } else i = 0; } else i = 0; if (i <= 0) { /* write failed, queue it for later */ WCHANadd(cp); } if (Tracing || cp->Tracing) syslog(L_TRACE, "%s > %s", CHANname(cp), text); } /* ** Tell the NNTP channel to go away. */ STATIC void NCwriteshutdown(cp, text) CHANNEL *cp; char *text; { cp->State = CSwritegoodbye; RCHANremove(cp); /* we're not going to read anything more */ #if 0 /* XXX why would we want to zap whatever was already * in the output buffer? */ WCHANset(cp, NNTP_GOODBYE, STRLEN(NNTP_GOODBYE)); #else WCHANappend(cp, NNTP_GOODBYE, STRLEN(NNTP_GOODBYE)); #endif WCHANappend(cp, " ", 1); WCHANappend(cp, text, (int)strlen(text)); WCHANappend(cp, NCterm, STRLEN(NCterm)); WCHANadd(cp); } /* ** If a Message-ID is bad, write a reject message and return TRUE. */ STATIC BOOL NCbadid(cp, p) register CHANNEL *cp; register char *p; { if (ARTidok(p)) return FALSE; NCwritereply(cp, NNTP_HAVEIT_BADID); syslog(L_NOTICE, "%s bad_messageid %s", CHANname(cp), MaxLength(p, p)); return TRUE; } /* ** We have an entire article collected; try to post it. If we're ** not running, drop the article or just pause and reschedule. */ STATIC void NCpostit(cp) register CHANNEL *cp; { STRING response; WIP *wp; /* Note that some use break, some use return here. */ switch (Mode) { default: syslog(L_ERROR, "%s internal NCpostit mode %d", CHANname(cp), Mode); return; case OMpaused: SCHANadd(cp, (time_t)(Now.time + PAUSE_RETRY_TIME), (POINTER)&Mode, NCpostit, (POINTER)NULL); return; case OMrunning: wp = &NCwip[cp->fd]; response = ARTpost(cp, AmSlave ? &wp->Replic : NULL, wp->MessageID); if (atoi(response) == NNTP_TOOKIT_VAL) { cp->Received++; if (cp->Sendid.Size > 3) { /* We be streaming */ char buff[4]; (void)sprintf(buff, "%d", NNTP_OK_RECID_VAL); cp->Sendid.Data[0] = buff[0]; cp->Sendid.Data[1] = buff[1]; cp->Sendid.Data[2] = buff[2]; response = cp->Sendid.Data; } } else { cp->Rejected++; if (cp->Sendid.Size) response = cp->Sendid.Data; } cp->Reported++; if (cp->Reported >= NNTP_ACTIVITY_SYNC) { syslog(L_NOTICE, "%s checkpoint seconds %ld accepted %ld refused %ld rejected %ld", CHANname(cp), (long)(Now.time - cp->Started), cp->Received, cp->Refused, cp->Rejected); cp->Reported = 0; } cp->State = CSgetcmd; NCwritereply(cp, response); break; case OMthrottled: NCwriteshutdown(cp, ModeReason); cp->Rejected++; break; } /* Clear the work-in-progress entry. */ NCclearwip(&NCwip[cp->fd]); } /* ** Write-done function. Close down or set state for what we expect to ** read next. */ STATIC FUNCTYPE NCwritedone(cp) register CHANNEL *cp; { switch (cp->State) { default: syslog(L_ERROR, "%s internal NCwritedone state %d", CHANname(cp), cp->State); break; case CSwritegoodbye: if (NCcount > 0) NCcount--; CHANclose(cp, CHANname(cp)); break; case CSgetcmd: case CSgetauth: case CSgetarticle: case CSgetrep: case CSgetxbatch: RCHANadd(cp); break; } } #if 0 /* ** The "article" command. */ STATIC FUNCTYPE NCarticle(cp) register CHANNEL *cp; { register char *p; register char *q; char *art; /* Snip off the Message-ID. */ for (p = cp->In.Data + STRLEN("article"); ISWHITE(*p); p++) continue; if (NCbadid(cp, p)) return; /* Get the article filenames, and the article header+body. */ if ((art = ARTreadarticle(HISfilesfor(p))) == NULL) { NCwritereply(cp, NNTP_DONTHAVEIT); return; } /* Write it. */ NCwritereply(cp, NNTP_ARTICLE_FOLLOWS); for (p = art; ((q = strchr(p, '\n')) != NULL); p = q + 1) { if (*p == '.') WCHANappend(cp, ".", 1); WCHANappend(cp, p, q - p); WCHANappend(cp, NCterm, STRLEN(NCterm)); } /* Write the terminator. */ WCHANappend(cp, NCdotterm, STRLEN(NCdotterm)); } #endif /* 0 */ /* ** The "head" command. */ STATIC FUNCTYPE NChead(cp) CHANNEL *cp; { register char *p; register char *q; char *head; /* Snip off the Message-ID. */ for (p = cp->In.Data + STRLEN("head"); ISWHITE(*p); p++) continue; if (NCbadid(cp, p)) return; /* Get the article filenames, and the header. */ if ((head = ARTreadheader(HISfilesfor(p))) == NULL) { NCwritereply(cp, NNTP_DONTHAVEIT); return; } /* Write it. */ WCHANappend(cp, NNTP_HEAD_FOLLOWS, STRLEN(NNTP_HEAD_FOLLOWS)); WCHANappend(cp, NCterm, STRLEN(NCterm)); for (p = head; ((q = strchr(p, '\n')) != NULL); p = q + 1) { if (*p == '.') WCHANappend(cp, ".", 1); WCHANappend(cp, p, q - p); WCHANappend(cp, NCterm, STRLEN(NCterm)); } /* Write the terminator. */ NCwritereply(cp, NCdot); } /* ** The "stat" command. */ STATIC FUNCTYPE NCstat(cp) CHANNEL *cp; { register char *p; /* mibsoft 97-Aug-12 If DBZMAXKEY is changed to be much different than SMBUF, then better bump up SMBUF! */ char buff[SMBUF+16]; /* Snip off the Message-ID. */ for (p = cp->In.Data + STRLEN("stat"); ISWHITE(*p); p++) continue; if (NCbadid(cp, p)) return; /* Get the article filenames; read the header (to make sure not * the article is still here). */ if (ARTreadheader(HISfilesfor(p)) == NULL) { NCwritereply(cp, NNTP_DONTHAVEIT); return; } /* Write the message. */ /* We know there is enough room as long as DBZMAXKEY < SMBUF+16-7 */ (void)sprintf(buff, "%d 0 %s", NNTP_NOTHING_FOLLOWS_VAL, p); NCwritereply(cp, buff); } /* ** The "authinfo" command. Actually, we come in here whenever the ** channel is in CSgetauth state and we just got a command. */ STATIC FUNCTYPE NCauthinfo(cp) register CHANNEL *cp; { static char AUTHINFO[] = "authinfo "; static char PASS[] = "pass "; static char USER[] = "user "; register char *p; p = cp->In.Data; /* Allow the poor sucker to quit. */ if (caseEQ(p, "quit")) { NCquit(cp); return; } /* Otherwise, make sure we're only getting "authinfo" commands. */ if (!caseEQn(p, AUTHINFO, STRLEN(AUTHINFO))) { NCwritereply(cp, NNTP_AUTH_NEEDED); return; } for (p += STRLEN(AUTHINFO); ISWHITE(*p); p++) continue; /* Ignore "authinfo user" commands, since we only care about the * password. */ if (caseEQn(p, USER, STRLEN(USER))) { NCwritereply(cp, NNTP_AUTH_NEXT); return; } /* Now make sure we're getting only "authinfo pass" commands. */ if (!caseEQn(p, PASS, STRLEN(PASS))) { NCwritereply(cp, NNTP_AUTH_NEEDED); return; } for (p += STRLEN(PASS); ISWHITE(*p); p++) continue; /* Got the password -- is it okay? */ if (!RCauthorized(cp, p)) { cp->State = CSwritegoodbye; NCwritereply(cp, NNTP_AUTH_BAD); } else { cp->State = CSgetcmd; NCwritereply(cp, NNTP_AUTH_OK); } } /* ** Is someone already sending us this article? */ STATIC BOOL NCinprogress(cp, id, who) CHANNEL *cp; register char *id; WIP **who; { register WIP *wp; register char *p; register int i; for (i = NCwipsize, wp = NCwip; --i >= 0; wp++) if ((p = wp->MessageID) != NULL && *p == *id && EQ(p, id) && Now.time - wp->Timestamp < WIP_CHECK) { *who = wp; return TRUE; } wp = &NCwip[cp->fd]; if (wp->MessageID == NULL) { for (i = SIZEOF(NCfreelist); --i >= 0; ) if (NCfreelist[i] != NULL) { wp->MessageID = NCfreelist[i]; NCfreelist[i] = NULL; break; } if (i < 0) wp->MessageID = NEW(char, DBZMAXKEY + 3); } (void)strcpy(wp->MessageID, id); return FALSE; } /* ** The "help" command. */ STATIC FUNCTYPE NChelp(cp) register CHANNEL *cp; { static char LINE1[] = "For more information, contact \""; static char LINE2[] = "\" at this machine."; register NCDISPATCH *dp; WCHANappend(cp, NNTP_HELP_FOLLOWS,STRLEN(NNTP_HELP_FOLLOWS)); WCHANappend(cp, NCterm,STRLEN(NCterm)); for (dp = NCcommands; dp < ENDOF(NCcommands); dp++) if (dp->Function != NC_unimp) { if (!StreamingOff || cp->Streaming || (dp->Function != NCcheck && dp->Function != NCtakethis)) { WCHANappend(cp, "\t", 1); WCHANappend(cp, dp->Name, dp->Size); WCHANappend(cp, NCterm, STRLEN(NCterm)); } } WCHANappend(cp, LINE1, STRLEN(LINE1)); WCHANappend(cp, NEWSMASTER, STRLEN(NEWSMASTER)); WCHANappend(cp, LINE2, STRLEN(LINE2)); WCHANappend(cp, NCterm, STRLEN(NCterm)); NCwritereply(cp, NCdot) ; } #if !defined(NNTP_RESENDIT_LATER) /* ** We woke up because we got offered an article that was already in ** progress somewhere else. If the other channel finished, then we ** don't want the article, otherwise let's accept it. */ STATIC FUNCTYPE NCwaitfor(cp) register CHANNEL *cp; { WIP *who; if (HIShavearticle(cp->Argument)) { cp->Refused++; NCwritereply(cp, NNTP_HAVEIT); DISPOSE(cp->Argument); cp->Argument = NULL; } else if (NCinprogress(cp, cp->Argument, &who)) { who->Wanted = TRUE; SCHANadd(cp, (time_t)(Now.time + WIP_CHECK / 2 + 1), (POINTER)who, NCwaitfor, (POINTER)cp->Argument); } else { cp->State = CSgetarticle; NCwritereply(cp, NNTP_SENDIT); DISPOSE(cp->Argument); cp->Argument = NULL; } } #endif /* !defined(NNTP_RESENDIT_LATER) */ /* ** The "ihave" command. Check the Message-ID, and see if we want the ** article or not. Set the state appropriately. */ STATIC FUNCTYPE NCihave(cp) CHANNEL *cp; { register char *p; WIP *who; if (AmSlave) { NCwritereply(cp, NCbadcommand); return; } /* Snip off the Message-ID. */ for (p = cp->In.Data + STRLEN("ihave"); ISWHITE(*p); p++) continue; if (NCbadid(cp, p)) return; if (HIShavearticle(p)) { cp->Refused++; NCwritereply(cp, NNTP_HAVEIT); } else if (NCinprogress(cp, p, &who)) { #if defined(NNTP_RESENDIT_LATER) NCwritereply(cp, NNTP_RESENDIT_LATER); #else /* Somebody else is sending it to us; wait until they're done. */ who->Wanted = TRUE; SCHANadd(cp, (time_t)(Now.time + WIP_CHECK + 1), (POINTER)who, NCwaitfor, (POINTER)COPY(p)); /* Clear input buffer. */ cp->In.Used = 0; #endif /* defined(NNTP_RESENDIT_LATER) */ } else { cp->State = CSgetarticle; NCwritereply(cp, NNTP_SENDIT); } } /* The "xbatch" command. We (ab)use WIP->Size to memorize the batch size. ** Set the state appropriately. */ STATIC FUNCTYPE NCxbatch(cp) CHANNEL *cp; { register char *p; WIP *wp; if (AmSlave) { NCwritereply(cp, NCbadcommand); return; } /* Snip off the batch size */ for (p = cp->In.Data + STRLEN("xbatch"); ISWHITE(*p); p++) continue; wp = &NCwip[cp->fd]; /* safety checks, unnecessary once we are running stable */ if (!wp) syslog(L_FATAL, "NCxbatch(): oops, wp == NULL"); if (wp->Size) { syslog(L_FATAL, "NCxbatch(): oops, wp->Size already set to %ld", wp->Size); } wp->Size = atoi(p); if (Tracing || cp->Tracing) syslog(L_TRACE, "%s will read batch of size %ld", CHANname(cp), wp->Size); if (wp->Size <= 0) { syslog(L_NOTICE, "%s got bad xbatch size %ld", CHANname(cp), wp->Size); NCwritereply(cp, NNTP_XBATCH_BADSIZE); return; } #if 1 /* we prefer not to touch the buffer, NCreader() does enough magic * with it */ #else /* We already know how much data will arrive, so we can allocate * sufficient buffer space for the batch in advance. We allocate * LOW_WATER + 1 more than needed, so that CHANreadtext() will never * reallocate it. */ if (cp->In.Size < wp->Size + LOW_WATER + 1) { DISPOSE(cp->In.Data); cp->In.Left = cp->In.Size = wp->Size + LOW_WATER + 1; cp->In.Used = 0; cp->In.Data = NEW(char, cp->In.Size); } #endif cp->State = CSgetxbatch; NCwritereply(cp, NNTP_CONT_XBATCH); } /* ** The "list" command. Send the active file. */ STATIC FUNCTYPE NClist(cp) register CHANNEL *cp; { register char *p; register char *q; char *trash; char *end; for (p = cp->In.Data + STRLEN("list"); ISWHITE(*p); p++) continue; if (caseEQ(p, "newsgroups")) { trash = p = ReadInFile(_PATH_NEWSGROUPS, (struct stat *)NULL); end = p + strlen(p); } else if (caseEQ(p, "active.times")) { trash = p = ReadInFile(_PATH_ACTIVETIMES, (struct stat *)NULL); end = p + strlen(p); } else if (*p == '\0' || (caseEQ(p, "active"))) { p = ICDreadactive(&end); trash = NULL; } else { NCwritereply(cp, NCbadcommand); return; } /* Loop over all lines, sending the text and \r\n. */ WCHANappend(cp, NNTP_LIST_FOLLOWS,STRLEN(NNTP_LIST_FOLLOWS)); WCHANappend(cp, NCterm, STRLEN(NCterm)) ; for (; p < end && (q = strchr(p, '\n')) != NULL; p = q + 1) { WCHANappend(cp, p, q - p); WCHANappend(cp, NCterm, STRLEN(NCterm)); } NCwritereply(cp, NCdot); if (trash) DISPOSE(trash); } /* ** The "mode" command. Hand off the channel. */ STATIC FUNCTYPE NCmode(cp) register CHANNEL *cp; { register char *p; HANDOFF h; /* Skip the first word, get the argument. */ for (p = cp->In.Data + STRLEN("mode"); ISWHITE(*p); p++) continue; if (caseEQ(p, "reader")) h = HOnnrpd; else if (caseEQ(p, "query")) h = HOnnrqd; else if (caseEQ(p, "stream") && (!StreamingOff || (StreamingOff && cp->Streaming))) { char buff[16]; (void)sprintf(buff, "%d StreamOK.", NNTP_OK_STREAM_VAL); NCwritereply(cp, buff); syslog(L_NOTICE, "%s NCmode \"mode stream\" received", CHANname(cp)); return; } else { NCwritereply(cp, NCbadcommand); return; } RChandoff(cp->fd, h); if (NCcount > 0) NCcount--; CHANclose(cp, CHANname(cp)); } /* ** The "quit" command. Acknowledge, and set the state to closing down. */ STATIC FUNCTYPE NCquit(cp) CHANNEL *cp; { register WIP *wp; register int i; wp = &NCwip[cp->fd]; for (i = SIZEOF(NCfreelist); --i >= 0; ) if (NCfreelist[i] == NULL) { NCfreelist[i] = wp->MessageID; wp->MessageID = NULL; break; } #if 0 if (i < 0) { DISPOSE(wp->MessageID); wp->MessageID = NULL; } #endif /* 0 */ cp->State = CSwritegoodbye; NCwritereply(cp, NNTP_GOODBYE_ACK); } /* ** The "xpath" command. Return the paths for an article is. */ STATIC FUNCTYPE NCxpath(cp) CHANNEL *cp; { static BUFFER Reply; register char *p; register int i; /* Nip off the Message-ID. */ for (p = cp->In.Data + STRLEN("xpath"); ISWHITE(*p); p++) continue; if (NCbadid(cp, p)) return; if ((p = HISfilesfor(p)) == NULL) { NCwritereply(cp, NNTP_DONTHAVEIT); return; } i = 3 + 1 + strlen(p); if (Reply.Data == NULL) { Reply.Size = i; Reply.Data = NEW(char, i + 1); } else if (Reply.Size < i) { Reply.Size = i; RENEW(Reply.Data, char, i + 1); } (void)sprintf(Reply.Data, "%d %s", NNTP_NOTHING_FOLLOWS_VAL, p); NCwritereply(cp, Reply.Data); } /* ** The "xreplic" command. Take an article and the places to file it. */ STATIC FUNCTYPE NCxreplic(cp) CHANNEL *cp; { register char *p; register BUFFER *bp; register int i; if (!RCismaster(cp->Address)) { NCwritereply(cp, NCbadcommand); return; } /* Stash the filename arguments. */ for (p = cp->In.Data + STRLEN("xreplic"); ISWHITE(*p); p++) continue; i = cp->In.Used - (p - cp->In.Data) + 1; bp = &NCwip[cp->fd].Replic; if (bp->Data == NULL) { bp->Size = i; bp->Data = NEW(char, i); } BUFFset(bp, p, i); bp->Used = bp->Left; /* Tell master to send it to us. */ cp->State = CSgetrep; NCwritereply(cp, NNTP_SENDIT); } /* ** The catch-all for inimplemented commands. */ STATIC FUNCTYPE NC_unimp(cp) CHANNEL *cp; { register char *p; char buff[SMBUF]; /* Nip off the first word. */ for (p = cp->In.Data; *p && !ISWHITE(*p); p++) continue; *p = '\0'; (void)sprintf(buff, "%d \"%s\" not implemented; try \"help\".", NNTP_BAD_COMMAND_VAL, MaxLength(cp->In.Data, cp->In.Data)); NCwritereply(cp, buff); } /* ** Remove the \r\n and leading dot escape that the NNTP protocol adds. */ STATIC void NCclean(bp) register BUFFER *bp; { register char *end; register char *p; register char *dest; for (p = bp->Data, dest = p, end = p + bp->Used; p < end; ) { if (p[0] == '\r' && p[1] == '\n') { p += 2; *dest++ = '\n'; if (p[0] == '.' && p[1] == '.') { p += 2; *dest++ = '.'; } } else *dest++ = *p++; } *dest = '\0'; bp->Used = dest - bp->Data; } /* ** Check whatever data is available on the channel. If we got the ** full amount (i.e., the command or the whole article) process it. */ STATIC FUNCTYPE NCproc(cp) register CHANNEL *cp; { register char *p; register NCDISPATCH *dp; register BUFFER *bp; register WIP *wp; STRING q; char buff[SMBUF]; char *av[2]; int i; if (Tracing || cp->Tracing) syslog(L_TRACE, "%s NCproc Used=%d", CHANname(cp), cp->In.Used); bp = &cp->In; if (bp->Used == 0) return; p = &bp->Data[bp->Used]; wp = &NCwip[cp->fd]; for ( ; ; ) { cp->Rest = 0; cp->SaveUsed = bp->Used; if (Tracing || cp->Tracing) if (bp->Used > 15) syslog(L_TRACE, "%s NCproc state=%d next \"%.15s\"", CHANname(cp), cp->State, bp->Data); switch (cp->State) { default: syslog(L_ERROR, "%s internal NCproc state %d", CHANname(cp), cp->State); break; case CSgetcmd: case CSgetauth: /* Did we get the whole command, terminated with "\r\n"? */ for (i = 0; (i < bp->Used) && (bp->Data[i] != '\n'); i++) ; if (i < bp->Used) cp->Rest = bp->Used = ++i; else { cp->Rest = 0; break; /* come back later for rest of line */ } if (cp->Rest < 2) break; p = &bp->Data[cp->Rest]; if (p[-2] != '\r' || p[-1] != '\n') { /* probably in an article */ int j; syslog(L_NOTICE, "%s bad_command %s", CHANname(cp), MaxLength(bp->Data, bp->Data)); if (++(cp->BadCommands) >= BAD_COMMAND_COUNT) { cp->State = CSwritegoodbye; NCwritereply(cp, NCbadcommand); cp->Rest = cp->SaveUsed; break; } else NCwritereply(cp, NCbadcommand); for (j = i + 1; j < cp->SaveUsed; j++) if (bp->Data[j] == '\n') { if (bp->Data[j - 1] == '\r') break; else cp->Rest = bp->Used = j + 1; } break; } p[-2] = '\0'; bp->Used -= 2; /* Ignore blank lines. */ if (bp->Data[0] == '\0') break; if (Tracing || cp->Tracing) syslog(L_TRACE, "%s < %s", CHANname(cp), bp->Data); /* We got something -- stop sleeping (in case we were). */ SCHANremove(cp); if (cp->Argument != NULL) { DISPOSE(cp->Argument); cp->Argument = NULL; } if (cp->State == CSgetauth) { if (caseEQn(bp->Data, "mode", 4)) NCmode(cp); else NCauthinfo(cp); break; } /* Loop through the command table. */ for (p = bp->Data, dp = NCcommands; dp < ENDOF(NCcommands); dp++) if (caseEQn(p, dp->Name, dp->Size)) { /* ignore the streaming commands if necessary. */ if (!StreamingOff || cp->Streaming || (dp->Function != NCcheck && dp->Function != NCtakethis)) { (*dp->Function)(cp); cp->BadCommands = 0; break; } } if (dp == ENDOF(NCcommands)) { if (++(cp->BadCommands) >= BAD_COMMAND_COUNT) { cp->State = CSwritegoodbye; NCwritereply(cp, NCbadcommand); cp->Rest = cp->SaveUsed; } else NCwritereply(cp, NCbadcommand); /* Channel could have been freed by above NCwritereply if we're writing-goodbye */ if (cp->Type == CTfree) { return; } for (i = 0; (p = NCquietlist[i]) != NULL; i++) if (caseEQ(p, bp->Data)) break; if (p == NULL) syslog(L_NOTICE, "%s bad_command %s", CHANname(cp), MaxLength(bp->Data, bp->Data)); } break; case CSgetarticle: case CSgetrep: /* Check for the null article. */ if ((bp->Used >= 3) && (bp->Data[0] == '.') && (bp->Data[1] == '\r') && (bp->Data[2] == '\n')) { cp->Rest = 3; /* null article (canceled?) */ cp->Rejected++; #if 0 syslog(L_NOTICE, "%s empty article", CHANname(cp)) ; #endif cp->State = CSgetcmd; if (cp->Sendid.Size > 3) { /* We be streaming */ char buff[4]; (void)sprintf(buff, "%d", NNTP_ERR_FAILID_VAL); cp->Sendid.Data[0] = buff[0]; cp->Sendid.Data[1] = buff[1]; cp->Sendid.Data[2] = buff[2]; NCwritereply(cp, cp->Sendid.Data); } else NCwritereply(cp, NNTP_REJECTIT_EMPTY); bp->Used = 0; /* Clear the work-in-progress entry. */ NCclearwip(wp); break; } /* Reading an article; look for "\r\n.\r\n" terminator. */ if (cp->Lastch > 5) i = cp->Lastch; /* only look at new data */ else i = 5; for ( ; i <= bp->Used; i++) { if ((bp->Data[i - 5] == '\r') && (bp->Data[i - 4] == '\n') && (bp->Data[i - 3] == '.') && (bp->Data[i - 2] == '\r') && (bp->Data[i - 1] == '\n')) { cp->Rest = bp->Used = i; p = &bp->Data[i]; break; } } cp->Lastch = i; if (i > bp->Used) { /* did not find terminator */ /* Check for big articles. */ if (LargestArticle > SAVE_AMT && bp->Used > LargestArticle) { /* Make some room, saving only the last few bytes. */ for (p = bp->Data, i = 0; i < SAVE_AMT; p++, i++) p[0] = p[bp->Used - SAVE_AMT]; wp->Size += bp->Used - SAVE_AMT; bp->Used = cp->Lastch = SAVE_AMT; cp->State = CSeatarticle; } cp->Rest = 0; break; } if (Mode == OMpaused) { /* defer processing while paused */ cp->Rest = 0; bp->Used = cp->SaveUsed; SCHANadd(cp, (time_t)(Now.time + PAUSE_RETRY_TIME), (POINTER)&Mode, NCproc, (POINTER)NULL); return; } /* Strip article terminator and post the article. */ p[-3] = '\0'; bp->Used -= 2; SCHANremove(cp); if (cp->Argument != NULL) { DISPOSE(cp->Argument); cp->Argument = NULL; } NCclean(bp); NCpostit(cp); cp->State = CSgetcmd; break; case CSeatarticle: /* Eat the article and then complain that it was too large */ /* Reading an article; look for "\r\n.\r\n" terminator. */ if (cp->Lastch > 5) i = cp->Lastch; /* only look at new data */ else i = 5; for ( ; i <= bp->Used; i++) { if ((bp->Data[i - 5] == '\r') && (bp->Data[i - 4] == '\n') && (bp->Data[i - 3] == '.') && (bp->Data[i - 2] == '\r') && (bp->Data[i - 1] == '\n')) { cp->Rest = bp->Used = i; p = &bp->Data[i]; break; } } if (i <= bp->Used) { /* did find terminator */ /* Reached the end of the article. */ SCHANremove(cp); if (cp->Argument != NULL) { DISPOSE(cp->Argument); cp->Argument = NULL; } p = wp->MessageID; i = wp->Size + bp->Used; syslog(L_ERROR, "%s internal rejecting huge article %s (%d > %d)", CHANname(cp), p ? p : "(null)", i, LargestArticle); (void)sprintf(buff, "%d Article exceeds local limit of %ld bytes", NNTP_REJECTIT_VAL, LargestArticle); cp->State = CSgetcmd; if (cp->Sendid.Size) NCwritereply(cp, cp->Sendid.Data); else NCwritereply(cp, buff); cp->Rejected++; /* Write a local cancel entry so nobody else gives it to us. */ if (p) { av[0] = p; av[1] = NULL; if ((q = CCcancel(av)) != NULL) syslog(L_ERROR, "%s cant cancel %s %s", LogName, av[0], q); } /* Clear the work-in-progress entry. */ NCclearwip(wp); /* * only free and allocate the buffer back to * START_BUFF_SIZE if there's nothing in the buffer we * need to save (i.e., following commands. * if there is, then we're probably in streaming mode, * so probably not much point in trying to keep the * buffers minimal anyway... */ if (bp->Used == cp->SaveUsed) { /* Reset input buffer to the default size; don't let realloc * be lazy. */ DISPOSE(bp->Data); bp->Size = START_BUFF_SIZE; bp->Used = 0; bp->Data = NEW(char, bp->Size); cp->SaveUsed = cp->Rest = cp->Lastch = 0; } } else if (bp->Used > 8 * 1024) { /* Make some room; save the last few bytes of the article */ for (p = bp->Data, i = 0; i < SAVE_AMT; p++, i++) p[0] = p[bp->Used - SAVE_AMT + 0]; wp->Size += bp->Used - SAVE_AMT; bp->Used = cp->Lastch = SAVE_AMT; cp->Rest = 0; } break; case CSgetxbatch: /* if the batch is complete, write it out into the in.coming * directory with an unique timestamp, and start rnews on it. */ if (Tracing || cp->Tracing) syslog(L_TRACE, "%s CSgetxbatch: now %ld of %ld bytes", CHANname(cp), bp->Used, wp->Size); if (bp->Used < wp->Size) { cp->Rest = 0; break; /* give us more data */ } cp->Rest = wp->Size; /* now do something with the batch */ { char buff[SMBUF], buff2[SMBUF]; int fd, oerrno, failed; long now; now = time(NULL); failed = 0; /* time+channel file descriptor should make an unique file name */ sprintf(buff, "%s/%ld%d.tmp", _PATH_XBATCHES, now, cp->fd); fd = open(buff, O_WRONLY|O_CREAT|O_EXCL, ARTFILE_MODE); if (fd < 0) { oerrno = errno; failed = 1; syslog(L_ERROR, "%s cannot open outfile %s for xbatch: %m", CHANname(cp), buff); sprintf(buff, "%s cant create file: %s", NNTP_RESENDIT_XBATCHERR, strerror(oerrno)); NCwritereply(cp, buff); } else { if (write(fd, cp->In.Data, wp->Size) != wp->Size) { oerrno = errno; syslog(L_ERROR, "%s cant write batch to file %s: %m", CHANname(cp), buff); sprintf(buff, "%s cant write batch to file: %s", NNTP_RESENDIT_XBATCHERR, strerror(oerrno)); NCwritereply(cp, buff); failed = 1; } } if (fd >= 0 && close(fd) != 0) { oerrno = errno; syslog(L_ERROR, "%s error closing batch file %s: %m", CHANname(cp), failed ? "" : buff); sprintf(buff, "%s error closing batch file: %s", NNTP_RESENDIT_XBATCHERR, strerror(oerrno)); NCwritereply(cp, buff); failed = 1; } sprintf(buff2, "%s/%ld%d.x", _PATH_XBATCHES, now, cp->fd); if (rename(buff, buff2)) { oerrno = errno; syslog(L_ERROR, "%s cant rename %s to %s: %m", CHANname(cp), failed ? "" : buff, buff2); sprintf(buff, "%s cant rename batch to %s: %s", NNTP_RESENDIT_XBATCHERR, buff2, strerror(oerrno)); NCwritereply(cp, buff); failed = 1; } cp->Reported++; if (!failed) { NCwritereply(cp, NNTP_OK_XBATCHED); cp->Received++; } else cp->Rejected++; } syslog(L_NOTICE, "%s accepted batch size %ld", CHANname(cp), wp->Size); /* Clear the work-in-progress entry. */ NCclearwip(wp); #if 1 /* leave the input buffer as it is, there is a fair chance * that we will get another xbatch on this channel. * The buffer will finally be disposed at connection shutdown. */ #else /* Reset input buffer to the default size; don't let realloc * be lazy. */ DISPOSE(bp->Data); bp->Size = START_BUFF_SIZE; bp->Used = 0; bp->Data = NEW(char, bp->Size); #endif break; } if (Tracing || cp->Tracing) syslog(L_TRACE, "%s NCproc Rest=%d Used=%d SaveUsed=%d", CHANname(cp), cp->Rest, bp->Used, cp->SaveUsed); if (cp->Rest > 0) { if (cp->Rest < cp->SaveUsed) { /* more commands in buffer */ bp->Used = cp->SaveUsed = cp->SaveUsed - cp->Rest; /* It would be nice to avoid this copy but that ** would require changes to the bp structure and ** the way it is used. */ (void)memcpy((POINTER)bp->Data, (POINTER)&bp->Data[cp->Rest], (SIZE_T)bp->Used); cp->Rest = cp->Lastch = 0; } else { bp->Used = cp->Lastch = 0; break; } } else break; } } /* ** Read whatever data is available on the channel. If we got the ** full amount (i.e., the command or the whole article) process it. */ STATIC FUNCTYPE NCreader(cp) register CHANNEL *cp; { register WIP *wp; int i; if (Tracing || cp->Tracing) syslog(L_TRACE, "%s NCreader Used=%d", CHANname(cp), cp->In.Used); /* Read any data that's there; ignore errors (retry next time it's our * turn) and if we got nothing, then it's EOF so mark it closed. */ if ((i = CHANreadtext(cp)) <= 0) { #ifdef POLL_BUG /* return of -2 indicates EAGAIN, for SUNOS5.4 poll() bug workaround */ if (i == -2) { return; } #endif if (i == 0 || cp->BadReads++ >= BAD_IO_COUNT) { if (NCcount > 0) NCcount--; CHANclose(cp, CHANname(cp)); } return; } /* Update timestamp. */ wp = &NCwip[cp->fd]; wp->Timestamp = Now.time; NCproc(cp); /* check and process data */ } /* ** Set up the NNTP channel state. */ void NCsetup(i) register int i; { register WIP *wp; register NCDISPATCH *dp; char *p; char buff[SMBUF]; /* Set the greeting message. */ if ((p = GetConfigValue(_CONF_PATHHOST)) == NULL) /* Worked in main, now it fails? Curious. */ p = Path.Data; (void)sprintf(buff, "%d %s InterNetNews server %s ready", NNTP_POSTOK_VAL, p, Version); NCgreeting = COPY(buff); /* Set up the work-in-progress structure. */ for (wp = NCwip = NEW(WIP, i), NCwipsize = i; --i >= 0; wp++) *wp = NCnullwip; /* Get the length of every command. */ for (dp = NCcommands; dp < ENDOF(NCcommands); dp++) dp->Size = strlen(dp->Name); } /* ** Tear down our state. */ void NCclose() { register WIP *wp; register int i; register CHANNEL *cp; int j; /* Close all incoming channels. */ for (j = 0; (cp = CHANiter(&j, CTnntp)) != NULL; ) { if (NCcount > 0) NCcount--; CHANclose(cp, CHANname(cp)); } /* Free the WIP list. */ for (wp = NCwip, i = NCwipsize; --i >= 0; wp++) { if (wp->MessageID) DISPOSE(wp->MessageID); if (wp->Replic.Data) DISPOSE(wp->Replic.Data); } DISPOSE(NCwip); for (i = SIZEOF(NCfreelist); --i >= 0; ) if (NCfreelist[i] != NULL) DISPOSE(NCfreelist[i]); } /* ** Create an NNTP channel and print the greeting message. */ CHANNEL * NCcreate(fd, MustAuthorize, IsLocal) int fd; BOOL MustAuthorize; BOOL IsLocal; { register CHANNEL *cp; int i; /* Create the channel. */ cp = CHANcreate(fd, CTnntp, MustAuthorize ? CSgetauth : CSgetcmd, NCreader, NCwritedone); /* check for wip overflow */ if(fd > NCwipsize) { NCwriteshutdown(cp, "too many file descriptors"); return cp; } NCclearwip(&NCwip[cp->fd]); #if defined(SOL_SOCKET) && defined(SO_SNDBUF) && defined(SO_RCVBUF) #if defined (DO_SET_SOCKOPT) i = 24 * 1024; if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&i, sizeof i) < 0) syslog(L_ERROR, "%s cant setsockopt(SNDBUF) %m", CHANname(cp)); if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&i, sizeof i) < 0) syslog(L_ERROR, "%s cant setsockopt(RCVBUF) %m", CHANname(cp)); #endif #endif /* defined(SOL_SOCKET) && defined(SO_SNDBUF) && defined(SO_RCVBUF) */ #if defined(SOL_SOCKET) && defined(SO_KEEPALIVE) #if defined (DO_SET_SOCKOPT) /* Set KEEPALIVE to catch broken socket connections. */ i = 1; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&i, sizeof i) < 0) syslog(L_ERROR, "%s cant setsockopt(KEEPALIVE) %m", CHANname(cp)); #endif #endif /* defined(SOL_SOCKET) && defined(SO_KEEPALIVE) */ /* Now check our operating mode. */ NCcount++; if (Mode == OMthrottled) { NCwriteshutdown(cp, ModeReason); return cp; } if (RejectReason) { NCwriteshutdown(cp, RejectReason); return cp; } /* See if we have too many channels. */ if (!IsLocal && MaxIncoming && NCcount >= MaxIncoming && !RCnolimit(cp)) { /* Recount, just in case we got out of sync. */ for (NCcount = 0, i = 0; CHANiter(&i, CTnntp) != NULL; ) NCcount++; if (NCcount >= MaxIncoming) { NCwriteshutdown(cp, "Too many connections"); return cp; } } cp->BadReads = 0; cp->BadCommands = 0; NCwritereply(cp, NCgreeting); return cp; } /* These modules support the streaming option to tranfer articles ** faster. */ /* ** The "check" command. Check the Message-ID, and see if we want the ** article or not. Stay in command state. */ STATIC FUNCTYPE NCcheck(cp) CHANNEL *cp; { register char *p; int msglen; WIP *who; if (AmSlave) { NCwritereply(cp, NCbadcommand); return; } /* Snip off the Message-ID. */ for (p = cp->In.Data; !ISWHITE(*p); p++) continue; for ( ; ISWHITE(*p); p++) continue; msglen = strlen(p) + 5; /* 3 digits + space + id + null */ if (cp->Sendid.Size < msglen) { if (cp->Sendid.Size > 0) DISPOSE(cp->Sendid.Data); if (msglen > MAXHEADERSIZE) cp->Sendid.Size = msglen; else cp->Sendid.Size = MAXHEADERSIZE; cp->Sendid.Data = NEW(char, cp->Sendid.Size); } if (!ARTidok(p)) { (void)sprintf(cp->Sendid.Data, "%d %s", NNTP_ERR_GOTID_VAL, p); NCwritereply(cp, cp->Sendid.Data); syslog(L_NOTICE, "%s bad_messageid %s", CHANname(cp), MaxLength(p, p)); return; } if (HIShavearticle(p)) { cp->Refused++; (void)sprintf(cp->Sendid.Data, "%d %s", NNTP_ERR_GOTID_VAL, p); NCwritereply(cp, cp->Sendid.Data); } else if (NCinprogress(cp, p, &who)) { (void)sprintf(cp->Sendid.Data, "%d %s", NNTP_RESENDID_VAL, p); NCwritereply(cp, cp->Sendid.Data); } else { (void)sprintf(cp->Sendid.Data, "%d %s", NNTP_OK_SENDID_VAL, p); NCwritereply(cp, cp->Sendid.Data); } /* stay in command mode */ } /* ** The "takethis" command. Article follows. ** Remember for later ack. */ STATIC FUNCTYPE NCtakethis(cp) CHANNEL *cp; { register char *p; int msglen; register WIP *wp; register int i; /* Snip off the Message-ID. */ for (p = cp->In.Data + STRLEN("takethis"); ISWHITE(*p); p++) continue; for ( ; ISWHITE(*p); p++) continue; if (!ARTidok(p)) { syslog(L_NOTICE, "%s bad_messageid %s", CHANname(cp), MaxLength(p, p)); } msglen = strlen(p) + 5; /* 3 digits + space + id + null */ if (cp->Sendid.Size < msglen) { if (cp->Sendid.Size > 0) DISPOSE(cp->Sendid.Data); if (msglen > MAXHEADERSIZE) cp->Sendid.Size = msglen; else cp->Sendid.Size = MAXHEADERSIZE; cp->Sendid.Data = NEW(char, cp->Sendid.Size); } /* save ID for later NACK or ACK */ (void)sprintf(cp->Sendid.Data, "%d %s", NNTP_ERR_FAILID_VAL, p); cp->State = CSgetarticle; /* set wp->MessageID for benefit of later code in NCreader * (especially while in CSeatarticle state) */ wp = &NCwip[cp->fd]; if (wp->MessageID == NULL) { for (i = SIZEOF(NCfreelist); --i >= 0; ) if (NCfreelist[i] != NULL) { wp->MessageID = NCfreelist[i]; NCfreelist[i] = NULL; break; } if (i < 0) wp->MessageID = NEW(char, DBZMAXKEY + 3); } (void)strcpy(wp->MessageID, p); } inn-1.7.2/innd/rc.c0100644000175100001440000005036706443103542012342 0ustar mdusers/* $Revision: 1.42 $ ** ** Routines for the remote connect channel. Create an Internet stream socket ** that processes connect to. If the incoming site is not one of our feeds, ** then we pass the connection off to the standard nntp daemon. */ #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" #include #if !defined(NETSWAP) #if !defined(htons) extern unsigned short htons(); #endif /* !defined(htons) */ #if !defined(htonl) #if 0 extern unsigned long htonl(); /* nobody should really need this anymore */ #endif #endif /* !defined(htonl) */ #endif /* !defined(NETSWAP) */ #define COPYADDR(dest, src) \ (void)memcpy((POINTER)dest, (POINTER)src, (SIZE_T)sizeof (INADDR)) /* ** A remote host has an address and a password. */ typedef struct _REMOTEHOST { char *Name; INADDR Address; char *Password; BOOL Streaming ; char **Patterns; } REMOTEHOST; typedef struct _REMOTETABLE { INADDR Address; time_t Expires; } REMOTETABLE; STATIC INADDR *RCmaster; STATIC int RCnmaster; STATIC char *RCslaveflag; STATIC char RCnnrpd[] = _PATH_NNRPD; STATIC char RCnnrqd[] = _PATH_NNQRD; STATIC char RCnntpd[] = _PATH_NNTPD; STATIC CHANNEL *RCchan; STATIC REMOTEHOST *RCpeerlist; STATIC int RCnpeerlist; STATIC REMOTEHOST *RCnolimitlist; STATIC int RCnnolimitlist; /* ** Stuff needed for limiting incoming connects. */ STATIC char RCterm[] = "\r\n"; STATIC REMOTETABLE remotetable[REMOTETABLESIZE]; STATIC int remotecount; STATIC int remotefirst; /* ** See if the site properly entered the password. */ BOOL RCauthorized(cp, pass) register CHANNEL *cp; char *pass; { register REMOTEHOST *rp; register int i; for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++) /* SUPPRESS 112 *//* Retrieving long where char is stored */ if (cp->Address.s_addr == rp->Address.s_addr) { if (rp->Password[0] == '\0' || EQ(pass, rp->Password)) return TRUE; syslog(L_ERROR, "%s bad_auth", inet_ntoa(cp->Address)); return FALSE; } if (!AnyIncoming) /* Not found in our table; this can't happen. */ syslog(L_ERROR, "%s not_found", inet_ntoa(cp->Address)); /* Anonymous hosts should not authenticate. */ return FALSE; } /* ** See if a host is in the "nolimit" file. */ BOOL RCnolimit(cp) register CHANNEL *cp; { register REMOTEHOST *rp; register int i; for (rp = RCnolimitlist, i = RCnnolimitlist; --i >= 0; rp++) /* SUPPRESS 112 *//* Retrieving long where char is stored */ if (cp->Address.s_addr == rp->Address.s_addr) return TRUE; return FALSE; } /* ** Is this an address of the master? */ BOOL RCismaster(addr) INADDR addr; { register INADDR *ip; register int i; if (AmSlave) for (i = RCnmaster, ip = RCmaster; --i >= 0; ip++) /* SUPPRESS 112 *//* Retrieving long where char is stored */ if (addr.s_addr == ip->s_addr) return TRUE; return FALSE; } /* ** Called when input is ready to read. Shouldn't happen. */ /* ARGSUSED0 */ STATIC FUNCTYPE RCrejectreader(cp) CHANNEL *cp; { syslog(L_ERROR, "%s internal RCrejectreader", LogName); } /* ** Write-done function for rejects. */ STATIC FUNCTYPE RCrejectwritedone(cp) register CHANNEL *cp; { switch (cp->State) { default: syslog(L_ERROR, "%s internal RCrejectwritedone state %d", CHANname(cp), cp->State); break; case CSwritegoodbye: CHANclose(cp, CHANname(cp)); break; } } /* ** Hand off a descriptor to NNRPD. */ void RChandoff(fd, h) int fd; HANDOFF h; { STRING argv[6]; char buff[SMBUF]; int i; #if defined(SOL_SOCKET) && defined(SO_KEEPALIVE) /* Set KEEPALIVE to catch broken socket connections. */ i = 1; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&i, sizeof i) < 0) syslog(L_ERROR, "fd %d cant setsockopt(KEEPALIVE) %m", fd); #endif /* defined(SOL_SOCKET) && defined(SO_KEEPALIVE) */ if (SetNonBlocking(fd, FALSE) < 0) syslog(L_ERROR, "%s cant nonblock %d in RChandoff %m", LogName, fd); switch (h) { default: syslog(L_ERROR, "%s internal RChandoff %d type %d", LogName, fd, h); /* FALLTHROUGH */ case HOnnrpd: argv[0] = RCnnrpd; break; case HOnnrqd: argv[0] = RCnnrqd; break; case HOnntpd: argv[0] = RCnntpd; break; } argv[1] = "-s "; i = 2; if (NNRPReason) { (void)sprintf(buff, "-r%s", NNRPReason); argv[i++] = buff; } if (NNRPTracing) argv[i++] = "-t"; if (RCslaveflag) argv[i++] = RCslaveflag; argv[i] = NULL; /* Call NNRP; don't send back a QUIT message if Spawn fails since * that's a major error we want to find out about quickly. */ (void)Spawn(fd, fd, fd, argv); } /* ** Read function. Accept the connection and either create an NNTP channel ** or spawn an nnrpd to handle it. */ STATIC FUNCTYPE RCreader(cp) CHANNEL *cp; { int fd; struct sockaddr_in remote; int size; register int i; register REMOTEHOST *rp; CHANNEL *new; char *name; long reject_val; char *reject_message; int count; int found; time_t now; CHANNEL tempchan; if (cp != RCchan) { syslog(L_ERROR, "%s internal RCreader wrong channel 0x%x not 0x%x", LogName, cp, RCchan); return; } /* Get the connection. */ size = sizeof remote; if ((fd = accept(cp->fd, (struct sockaddr *)&remote, &size)) < 0) { syslog(L_ERROR, "%s cant accept RCreader %m", LogName); return; } /* ** Clear any IP_OPTIONS, including source routing, on the socket */ if (RCfix_options(fd, &remote) != 0) { /* shouldn't happen, but we're bit paranoid at this point */ if (close(fd) < 0) syslog(L_ERROR, "%s cant close %d %m", LogName, fd); return; } /* ** If RemoteTimer is not zero, then check the limits on incoming ** connections on a total and per host basis. ** ** The incoming connection table is fixed at 128 entries to make ** calculating the index easy (i + 1) & 7, and to be pretty sure ** that you won't run out of space. The table is used as a ring ** with new entries being added to the end (wrapping around) and ** expired entries being deleted from the front (again wrapping ** around). It is doubtful that you will ever use even half of ** the table. ** ** There are three parameters controlling the use of the table not ** counting the starting index and count. ** ** L = per host incoming connects per X seconds allowed ** T = total incoming connects per X seconds allowed ** X = number of seconds to remember a successful connect ** ** First, one pass is made over the live entries deleting any that ** are over X seconds old. If the entry hasn't expired, compare ** the incoming connection's host address with the entry's host ** address. If equal, increment the ``found'' counter. ** ** Second, if the number of entries now in the table is equal to ** the ``T'' parameter, reject the connection with the ``504'' ** error code. ** ** 504 Server overloaded, try later ** ** Third, if the number of entries now in the table which match ** the incoming connection's host address is equal to the ``L'' ** parameter, reject the connection with the ``505'' error code. ** ** 505 Connection rejected, you're making too many connects per minute ** ** Finally, if neither rejection happened, add the entry to the ** table, and continue on as a normal connect. */ tempchan.Address.s_addr = remote.sin_addr.s_addr; reject_message = NULL; if (RemoteTimer != 0) { now = time(NULL); i = remotefirst; count = remotecount; found = 0; while (count--) { if (remotetable[i].Expires < now) { remotecount--; remotefirst = (remotefirst + 1) & (REMOTETABLESIZE - 1); i = (i + 1) & (REMOTETABLESIZE - 1); continue; } if (remotetable[i].Address.s_addr == remote.sin_addr.s_addr) found++; i = (i + 1) & (REMOTETABLESIZE - 1); } if (remotecount == RemoteTotal) { reject_val = NNTP_SERVER_TOOBUSY_VAL; reject_message = NNTP_SERVER_TOOBUSY; } else if (found >= RemoteLimit && !RCnolimit(&tempchan)) { reject_val = NNTP_TOO_MANY_CONNECTS_VAL; reject_message = NNTP_TOO_MANY_CONNECTS; } else { i = (remotefirst + remotecount) & (REMOTETABLESIZE - 1); remotetable[i].Address = remote.sin_addr; remotetable[i].Expires = now + RemoteTimer; remotecount++; } } /* ** Create a reject channel to reject the connection. This is done ** to avoid a call to fork. */ if (reject_message) { new = CHANcreate(fd, CTreject, CSwritegoodbye, RCrejectreader, RCrejectwritedone); new->Address.s_addr = remote.sin_addr.s_addr; new->Rejected = reject_val; RCHANremove(new); WCHANset(new, reject_message, (int)strlen(reject_message)); WCHANappend(new, RCterm, STRLEN(RCterm)); WCHANadd(new); return; } /* See if it's one of our servers. */ for (name = NULL, rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++) /* SUPPRESS 112 *//* Retrieving long where char is stored */ if (rp->Address.s_addr == remote.sin_addr.s_addr) { name = rp->Name; break; } /* If not a server, and not allowing anyone, hand him off. */ if (i >= 0) { new = NCcreate(fd, rp->Password[0] != '\0', FALSE); new->Streaming = rp->Streaming ; } else if (AnyIncoming) { new = NCcreate(fd, FALSE, FALSE); } else { RChandoff(fd, HOnntpd); if (close(fd) < 0) syslog(L_ERROR, "%s cant close %d %m", LogName, fd); return; } /* SUPPRESS 112 *//* Retrieving long where char is stored */ new->Address.s_addr = remote.sin_addr.s_addr; syslog(L_NOTICE, "%s connected %d streaming %s", name ? name : inet_ntoa(new->Address), new->fd, (!StreamingOff || new->Streaming) ? "allowed" : "not allowed"); } /* ** Write-done function. Shouldn't happen. */ STATIC FUNCTYPE RCwritedone() { syslog(L_ERROR, "%s internal RCwritedone", LogName); } /* ** Read in the file listing the hosts we take news from, and fill in the ** global list of their Internet addresses. On modern systems a host can ** have multiple addresses, so we take care to add all of them to the list. ** We can distinguish between the two because h_addr is a #define for the ** first element of the address list in modern systems, while it's a field ** name in old ones. */ STATIC void RCreadfile(list, count, filename) REMOTEHOST **list; int *count; char *filename; { static char NOPASS[] = ""; char buff[SMBUF]; register FILE *F; register char *p; struct hostent *hp; register int i; register REMOTEHOST *rp; register int j; int k ; char *pass; char *pats; int errors; /* Free anything that might have been there. */ if (*list) { for (rp = *list, i = *count; --i >= 0; rp++) { DISPOSE(rp->Name); DISPOSE(rp->Password); if (rp->Patterns) { DISPOSE(rp->Patterns[0]); DISPOSE(rp->Patterns); } } DISPOSE(*list); *list = NULL; *count = 0; } /* Open the server file, count the lines. */ if ((F = fopen(filename, "r")) == NULL) { syslog(L_FATAL, "%s cant read %s %m", LogName, filename); exit(1); } for (i = 1; fgets(buff, sizeof buff, F) != NULL; ) if (buff[0] != COMMENT_CHAR && buff[0] != '\n') i++; *count = i; rp = *list = NEW(REMOTEHOST, *count); #if !defined(DO_HAVE_UNIX_DOMAIN) rp->Address.s_addr = inet_addr(LOOPBACK_HOST); rp->Name = COPY("localhost"); rp->Password = COPY(NOPASS); rp->Patterns = NULL; rp++; #endif /* !defined(DO_HAVE_UNIX_DOMAIN) */ /* Now read the file to add all the hosts. */ (void)fseek(F, (OFFSET_T)0, SEEK_SET); for (errors = 0; fgets(buff, sizeof buff, F) != NULL; ) { /* Ignore blank and comment lines. */ if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; if ((p = strchr(buff, COMMENT_CHAR)) != NULL) *p = '\0'; if (buff[0] == '\0') continue; if ((pass = strchr(buff, ':')) != NULL) { *pass++ = '\0'; if ((pats = strchr(pass, ':')) != NULL) *pats++ = '\0'; else pats = NULL; } else { pass = NOPASS; pats = NULL; } /* Check if the host name ends with '/s' which means that streaming is specifically permitted (as opposed to defaulted). The default for the global StreamingOff is FALSE, meaning any host can use streaming commands. If any entry is hosts.nntp has a suffix of '/s' then StreamingOff is set to TRUE, and then only those hosts.nntp entries with '/s' can use streaming commands. */ rp->Streaming = FALSE; if ((k = strlen(buff)) > 2) { if (buff[k - 1] == 's' && buff[k - 2] == '/') { buff[k - 2] = '\0'; rp->Streaming = TRUE; StreamingOff = TRUE ; } } /* Was host specified as as dotted quad? */ if ((rp->Address.s_addr = inet_addr(buff)) != (unsigned int) -1) { syslog(LOG_NOTICE, "think it's a dotquad: %s",buff); rp->Name = COPY(buff); rp->Password = COPY(pass); rp->Patterns = (pats && *pats) ? CommaSplit(COPY(pats)) : NULL; rp++; continue; } /* Host specified as a text name? */ if ((hp = gethostbyname(buff)) == NULL) { syslog(L_ERROR, "%s cant gethostbyname %s %m", LogName, buff); errors++; continue; } #if defined(h_addr) /* Count the addresses and see if we have to grow the list. */ for (i = 0; hp->h_addr_list[i]; i++) continue; if (i == 0) { syslog(L_ERROR, "%s no_address %s %m", LogName, buff); errors++; continue; } if (i == 1) { /* Just one, no need to grow. */ COPYADDR(&rp->Address, hp->h_addr_list[0]); rp->Name = COPY(hp->h_name); rp->Password = COPY(pass); rp->Patterns = (pats && *pats) ? CommaSplit(COPY(pats)) : NULL; rp++; continue; } /* Note the relative position, grow the array, and restore it. */ j = rp - *list; *count += i - 1; RENEW(*list, REMOTEHOST, *count); rp = *list + j; /* Add all the hosts. */ for (i = 0; hp->h_addr_list[i]; i++) { COPYADDR(&rp->Address, hp->h_addr_list[i]); rp->Name = COPY(hp->h_name); rp->Password = COPY(pass); rp->Patterns = (pats && *pats) ? CommaSplit(COPY(pats)) : NULL; rp->Streaming = (*list + j)->Streaming ; rp++; } #else /* Old-style, single address, just add it. */ COPYADDR(&rp->Address, hp->h_addr); rp->Name = COPY(hp->h_name); rp->Password = COPY(pass); rp->Patterns = (pats && *pats) ? CommaSplit(COPY(pats)) : NULL; rp++; #endif /* defined(h_addr) */ } *count = rp - *list; if (fclose(F) == EOF) syslog(L_ERROR, "%s cant fclose %s %m", LogName, filename); if (errors) syslog(L_ERROR, "%s bad_hosts %d in %s", LogName, errors, filename); } void RCreadlist() { static char INNDHOSTS[] = _PATH_INNDHOSTS; char name[sizeof _PATH_INNDHOSTS + sizeof ".nolimit"]; struct stat Sb; StreamingOff = FALSE ; RCreadfile(&RCpeerlist, &RCnpeerlist, INNDHOSTS); FileGlue(name, INNDHOSTS, '.', "nolimit"); if (stat(name, &Sb) >= 0) RCreadfile(&RCnolimitlist, &RCnnolimitlist, name); } /* ** Find the name of a remote host we've connected to. */ char * RChostname(cp) register CHANNEL *cp; { static char buff[SMBUF]; register REMOTEHOST *rp; register int i; for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++) /* SUPPRESS 112 *//* Retrieving long where char is stored */ if (cp->Address.s_addr == rp->Address.s_addr) return rp->Name; (void)strcpy(buff, inet_ntoa(cp->Address)); return buff; } /* ** Is the remote site allowed to post to this group? */ BOOL RCcanpost(cp, group) register CHANNEL *cp; register char *group; { register REMOTEHOST *rp; register BOOL match; register BOOL subvalue; register char **argv; register char *pat; register int i; for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++) { /* SUPPRESS 112 *//* Retrieving long where char is stored */ if (cp->Address.s_addr != rp->Address.s_addr) continue; if (rp->Patterns == NULL) break; for (match = TRUE, argv = rp->Patterns; (pat = *argv++) != NULL; ) { subvalue = *pat != SUB_NEGATE; if (!subvalue) pat++; if ((match != subvalue) && wildmat(group, pat)) match = subvalue; } return match; } return TRUE; } /* ** Create the channel. */ void RCsetup(i, master) register int i; char *master; { struct sockaddr_in server; struct hostent *hp; INADDR a; char buff[SMBUF]; #if defined(SO_REUSEADDR) int on; #endif /* defined(SO_REUSEADDR) */ if (i < 0) { /* Create a socket and name it. */ if ((i = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(L_FATAL, "%s cant socket RCreader %m", LogName); exit(1); } #if defined(SO_REUSEADDR) on = 1; if (setsockopt(i, SOL_SOCKET, SO_REUSEADDR, (caddr_t)&on, sizeof on) < 0) syslog(L_ERROR, "%s cant setsockopt RCreader %m", LogName); #endif /* defined(SO_REUSEADDR) */ (void)memset((POINTER)&server, 0, sizeof server); server.sin_port = htons(NNTP_PORT); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(i, (struct sockaddr *)&server, sizeof server) < 0) { syslog(L_FATAL, "%s cant bind RCreader %m", LogName); exit(1); } } /* Set it up to wait for connections. */ if (listen(i, MAXLISTEN) < 0) { syslog(L_FATAL, "%s cant listen RCreader %m", LogName); exit(1); } RCchan = CHANcreate(i, CTremconn, CSwaiting, RCreader, RCwritedone); syslog(L_NOTICE, "%s rcsetup %s", LogName, CHANname(RCchan)); RCHANadd(RCchan); /* Get the list of hosts we handle. */ RCreadlist(); /* If we have a master, get all his addresses. */ AmSlave = master != NULL; if (AmSlave) { /* Dotted quad? */ if ((a.s_addr = inet_addr(master)) != (unsigned int) -1) { RCnmaster = 1; RCmaster = NEW(INADDR, 1); COPYADDR(&RCmaster[0], &a); } else { /* Must be a text name. */ if ((hp = gethostbyname(master)) == NULL) { syslog(L_FATAL, "%s cant gethostbyname %s %m", LogName, master); exit(1); } #if defined(h_addr) /* Count the addresses. */ for (i = 0; hp->h_addr_list[i]; i++) continue; if (i == 0) { syslog(L_FATAL, "%s no_address %s %m", LogName, master); exit(1); } RCnmaster = i; RCmaster = NEW(INADDR, RCnmaster); for (i = 0; hp->h_addr_list[i]; i++) COPYADDR(&RCmaster[i], hp->h_addr_list[i]); #else RCnmaster = 1; RCmaster = NEW(INADDR, 1) COPYADDR(&RCmaster[0], &a); #endif /* defined(h_addr) */ } /* Set flag for nnrp. */ (void)sprintf(buff, "-S%s", master); RCslaveflag = COPY(buff); } } /* ** Cleanly shut down the channel. */ void RCclose() { register REMOTEHOST *rp; register int i; CHANclose(RCchan, CHANname(RCchan)); RCchan = NULL; if (RCpeerlist) { for (rp = RCpeerlist, i = RCnpeerlist; --i >= 0; rp++) { DISPOSE(rp->Name); DISPOSE(rp->Password); if (rp->Patterns) DISPOSE(rp->Patterns); } DISPOSE(RCpeerlist); RCpeerlist = NULL; RCnpeerlist = 0; } if (RCmaster) { DISPOSE(RCmaster); RCmaster = NULL; RCnmaster = 0; } } /* * Routine to disable IP-level socket options. This code was taken from 4.4BSD * rlogind source, but all mistakes in it are my fault. * * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. * * 21-Jan-1997 smd * Code copied again, and modified for INN, all new mistakes are mine. * */ /* fix_options - get rid of IP-level socket options */ #ifndef IP_OPTIONS #define IP_OPTIONS 1 #endif int RCfix_options(fd, remote) int fd; struct sockaddr_in *remote; { #if IP_OPTIONS unsigned char optbuf[BUFSIZ / 3], *cp; char lbuf[BUFSIZ], *lp; int optsize = sizeof(optbuf), ipproto; struct protoent *ip; if ((ip = getprotobyname("ip")) != 0) ipproto = ip->p_proto; else ipproto = IPPROTO_IP; if (getsockopt(fd, ipproto, IP_OPTIONS, (char *) optbuf, &optsize) == 0 && optsize != 0) { lp = lbuf; for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) sprintf(lp, " %2.2x", *cp); syslog(LOG_NOTICE, "connect from %s with IP options (ignored):%s", inet_ntoa(remote->sin_addr), lbuf); if (setsockopt(fd, ipproto, IP_OPTIONS, (char *) 0, optsize) != 0) { syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m"); return -1; } } #endif return 0; } inn-1.7.2/innd/tcl.c0100644000175100001440000001075606443103542012516 0ustar mdusers/* $Revision: 1.3 $ ** ** Support for TCL things ** ** By Bob Heiney, Network Systems Laboratory, Digital Equipment Corporation */ #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" #if defined(DO_TCL) Tcl_Interp *TCLInterpreter; BOOL TCLFilterActive; BUFFER *TCLCurrArticle; ARTDATA *TCLCurrData; STATIC char TCLSTARTUP[] = _PATH_TCL_STARTUP; STATIC char TCLFILTER[] = _PATH_TCL_FILTER; void TCLfilter(value) BOOL value; { TCLFilterActive=value; syslog(L_NOTICE, "%s tcl filtering %s", LogName, TCLFilterActive ? "enabled" : "disabled"); } void TCLreadfilter() { int code; /* do before reload callback */ code = Tcl_Eval(TCLInterpreter, "filter_before_reload"); if (code != TCL_OK) { if (strcmp(TCLInterpreter->result, "invalid command name: \"filter_before_reload\"")!=0) syslog(L_ERROR, "%s Tcl filter_before_reload failed: %s", LogName, TCLInterpreter->result); } /* read the filter file */ code = Tcl_EvalFile(TCLInterpreter, TCLFILTER); if (code != TCL_OK) { syslog(L_ERROR, "%s cant evaluate Tcl filter file: %s", LogName, TCLInterpreter->result); TCLfilter(FALSE); } /* do the after callback, discarding any errors */ code = Tcl_Eval(TCLInterpreter, "filter_after_reload"); if (code != TCL_OK) { if (strcmp(TCLInterpreter->result, "invalid command name: \"filter_after_reload\"")!=0) syslog(L_ERROR, "%s Tcl filter_after_reload failed: %s", LogName, TCLInterpreter->result); } } /* makeCheckSum * * Compute a checksum. This function does a one's-complement addition * of a series of 32-bit words. "buflen" is in bytes, not words. This is * hard because the number of bits with which our machine can do arithmetic * is the same as the size of the checksum being created, but our hardware * is 2's-complement and C has no way to check for integer overflow. * * Note that the checksum is returned in network byte order and not host * byte order; this makes it suitable for putting into packets and for * comparing with what is found in packets. */ static U_INT32_T makechecksum(sumbuf, buflen) u_char *sumbuf; int buflen; { register u_char *buf = (u_char *)sumbuf; register INT32_T len = buflen; register INT32_T sum; U_INT32_T bwordl,bwordr,bword,suml,sumr; int rmdr; u_char tbuf[4]; u_char *ptbuf; suml = 0; sumr = 0; len = len/4; rmdr = buflen - 4*len; while (len-- > 0) { bwordr = (buf[3] & 0xFF) + ((buf[2] & 0xFF) << 8); bwordl = (buf[1] & 0xFF) + ((buf[0] & 0xFF) << 8); bword = ( bwordl << 16) | bwordr; bword = ntohl(bword); bwordl = (bword >> 16) & 0xFFFF; bwordr = bword & 0xFFFF; sumr += bwordr; if (sumr & ~0xFFFF) { sumr &= 0xFFFF; suml++; } suml += bwordl; if (suml & ~0xFFFF) { suml &= 0xFFFF; sumr++; } buf += 4; } /* if buffer size was not an even multiple of 4 bytes, we have work to do */ if (rmdr > 0) { tbuf[3] = 0; tbuf[2] = 0; tbuf[1] = 0; /* tbuf[0] will always be copied into, and tbuf[3] will * always be zero (else this would not be a remainder) */ ptbuf = tbuf; while (rmdr--) *ptbuf++ = *buf++; bwordr = (tbuf[3] & 0xFF) + ((tbuf[2] & 0xFF) << 8); bwordl = (tbuf[1] & 0xFF) + ((tbuf[0] & 0xFF) << 8); bword = ( bwordl << 16) | bwordr; bword = ntohl(bword); bwordl = (bword >> 16) & 0xFFFF; bwordr = bword & 0xFFFF; sumr += bwordr; if (sumr & ~0xFFFF) { sumr &= 0xFFFF; suml++; } suml += bwordl; if (suml & ~0xFFFF) { suml &= 0xFFFF; sumr++; } } sum = htonl( (suml << 16) | sumr); return (~sum); } int TCLCksumArt(clientData, interp, argc, argv) ClientData clientData; Tcl_Interp *interp; int argc; char *argv[]; { char buf[100]; sprintf(buf, "%08x", makechecksum(TCLCurrData->Body, &TCLCurrArticle->Data[TCLCurrArticle->Used] - TCLCurrData->Body)); Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_OK; } void TCLsetup() { int code; TCLInterpreter = Tcl_CreateInterp(); code = Tcl_EvalFile(TCLInterpreter, TCLSTARTUP); if (code != TCL_OK) { syslog(L_FATAL, "%s cant read Tcl startup file: %s", LogName, TCLInterpreter->result); exit(1); } Tcl_CreateCommand(TCLInterpreter, "checksum_article", TCLCksumArt, NULL, NULL); TCLfilter(TRUE); TCLreadfilter(); } void TCLclose() { } #endif /* defined(DO_TCL) */ inn-1.7.2/innd/Makefile0100644000175100001440000001675006443103542013230 0ustar mdusers## $Revision: 1.33 $ SHELL = /bin/sh MAKE = make DESTDIR = D = $(DESTDIR) ## =()

@>()= P = ## =()@>()= CC = gcc ## =()@>()= PERLLIB = ## =()@>()= PERLINC = ## =()@>()= TCLINC = ## =()@ $(PERLINC) $(TCLINC)>()= DEFS = -I../include $(PERLINC) $(TCLINC) ## =()@>()= CFLAGS = $(DEFS) -g ## =()@>()= LDFLAGS = ## =()@ $(PERLINC) $(TCLINC)>()= LINTFLAGS = -b -h -z $(DEFS) $(PERLINC) $(TCLINC) ## =()@>()= LINTFILTER = | sed -n -f ../sedf.sun ## =()@>()= CTAGS = ctags -t -w ## =()@>()= PROF = -pg ## =()@>()= INND = /usr/news/bin/innd ## =()@>()= INNDSTART = /usr/news/bin/inndstart ## =()@ -G @@>()= OWNER = -O news -G news ## =()@>()= NEWSGROUP = news ## =()@>()= LIBS = -lutil LIBNEWS = ../libinn.a LINTLIB = ../llib-linn.ln ## =()@>()= TCL_LIB = SOURCES = \ art.c cc.c chan.c his.c icd.c innd.c lc.c nc.c newsfeeds.c ng.c \ proc.c rc.c site.c tcl.c perl.c OBJECTS = \ art.o cc.o chan.o his.o icd.o innd.o lc.o nc.o newsfeeds.o ng.o \ proc.o rc.o site.o tcl.o perl.o ALL = innd inndstart all: $(ALL) install: $D$(INND) $D$(INNDSTART) clobber clean: rm -f *.o $(ALL) rm -f inndp profiled rm -f all install lint tags ctags: $(SOURCES) $(CTAGS) $(SOURCES) ../lib/*.c innd.h ../include/*.h innd: $(P) $(OBJECTS) $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ $(OBJECTS) $(LIBNEWS) $(TCL_LIB) $(PERLLIB) $(LIBS) inndstart: $(P) inndstart.o $(LIBNEWS) $(CC) $(LDFLAGS) -o $@ inndstart.o $(LIBNEWS) $(LIBS) lint: $(ALL) @rm -f lint -lint $(LINTFLAGS) $(SOURCES) $(LINTLIB) $(LINTFILTER) >lint -lint $(LINTFLAGS) inndstart.c $(LINTLIB) $(LINTFILTER) >>lint ../include/dbz.h: (cd ../lib ; $(MAKE) ../include/dbz.h) $(LIBNEWS) $(LINTLIB): (cd ../lib ; $(MAKE) install) ## Profiling. The rules are a bit brute-force, but good enough. profiled: inndp date >$@ inndp: $(SOURCES) rm -f $(OBJECTS) $(MAKE) innd CFLAGS="$(CFLAGS) $(PROF)" LIBNEWS=../libinn_p.a mv innd inndp rm -f $(OBJECTS) ## ccenter: $(SOURCES) #load $(CFLAGS) $(SOURCES) $(LIBNEWS) ## Low-level install actions. $D$(INND): innd $(SHELL) ../installit.sh $(OWNER) -m 0550 -b .OLD $? $@ $D$(INNDSTART): inndstart $(SHELL) ../installit.sh -O root -G $(NEWSGROUP) -m 4550 -b .OLD $? $@ @ME=`(whoami || /usr/ucb/whoami) 2> /dev/null` ;\ if [ "X$$ME" = Xroot ]; then \ echo $@ has been installed setuid root. ;\ else\ echo "" ; echo "===============================" ;\ echo "NOTE NOTE NOTE NOTE NOTE" ;\ ls -l $@ ;\ echo $@ needs to be installed setuid root ;\ echo "" ; echo "" ;\ fi ## Dependencies. Default list, below, is probably good enough. depend: Makefile $(SOURCES) ../include/dbz.h makedepend $(DEFS) $(SOURCES) # DO NOT DELETE THIS LINE -- make depend depends on it. art.o: ../include/clibrary.h art.o: ../include/configdata.h art.o: ../include/configdata.h art.o: ../include/dbz.h art.o: ../include/libinn.h art.o: ../include/logging.h art.o: ../include/macros.h art.o: ../include/macros.h art.o: ../include/nntp.h art.o: ../include/paths.h art.o: ../include/paths.h art.o: art.h art.o: innd.h cc.o: ../include/clibrary.h cc.o: ../include/configdata.h cc.o: ../include/configdata.h cc.o: ../include/inndcomm.h cc.o: ../include/libinn.h cc.o: ../include/logging.h cc.o: ../include/macros.h cc.o: ../include/macros.h cc.o: ../include/nntp.h cc.o: ../include/paths.h cc.o: ../include/paths.h cc.o: innd.h chan.o: ../include/clibrary.h chan.o: ../include/configdata.h chan.o: ../include/configdata.h chan.o: ../include/libinn.h chan.o: ../include/libinn.h chan.o: ../include/logging.h chan.o: ../include/macros.h chan.o: ../include/nntp.h chan.o: ../include/nntp.h chan.o: ../include/paths.h chan.o: innd.h his.o: ../include/clibrary.h his.o: ../include/configdata.h his.o: ../include/configdata.h his.o: ../include/dbz.h his.o: ../include/libinn.h his.o: ../include/logging.h his.o: ../include/macros.h his.o: ../include/macros.h his.o: ../include/nntp.h his.o: ../include/paths.h his.o: ../include/paths.h his.o: innd.h icd.o: ../include/clibrary.h icd.o: ../include/configdata.h icd.o: ../include/configdata.h icd.o: ../include/libinn.h icd.o: ../include/logging.h icd.o: ../include/macros.h icd.o: ../include/macros.h icd.o: ../include/nntp.h icd.o: ../include/paths.h icd.o: ../include/paths.h icd.o: innd.h innd.o: ../include/clibrary.h innd.o: ../include/configdata.h innd.o: ../include/configdata.h innd.o: ../include/libinn.h innd.o: ../include/libinn.h innd.o: ../include/logging.h innd.o: ../include/macros.h innd.o: ../include/nntp.h innd.o: ../include/nntp.h innd.o: ../include/paths.h innd.o: innd.h lc.o: ../include/clibrary.h lc.o: ../include/configdata.h lc.o: ../include/configdata.h lc.o: ../include/libinn.h lc.o: ../include/logging.h lc.o: ../include/macros.h lc.o: ../include/macros.h lc.o: ../include/nntp.h lc.o: ../include/paths.h lc.o: ../include/paths.h lc.o: innd.h nc.o: ../include/clibrary.h nc.o: ../include/configdata.h nc.o: ../include/configdata.h nc.o: ../include/dbz.h nc.o: ../include/libinn.h nc.o: ../include/logging.h nc.o: ../include/macros.h nc.o: ../include/macros.h nc.o: ../include/nntp.h nc.o: ../include/paths.h nc.o: ../include/paths.h nc.o: innd.h newsfeeds.o: ../include/clibrary.h newsfeeds.o: ../include/configdata.h newsfeeds.o: ../include/configdata.h newsfeeds.o: ../include/libinn.h newsfeeds.o: ../include/libinn.h newsfeeds.o: ../include/logging.h newsfeeds.o: ../include/macros.h newsfeeds.o: ../include/nntp.h newsfeeds.o: ../include/nntp.h newsfeeds.o: ../include/paths.h newsfeeds.o: innd.h ng.o: ../include/clibrary.h ng.o: ../include/configdata.h ng.o: ../include/configdata.h ng.o: ../include/libinn.h ng.o: ../include/logging.h ng.o: ../include/macros.h ng.o: ../include/macros.h ng.o: ../include/mydir.h ng.o: ../include/nntp.h ng.o: ../include/paths.h ng.o: ../include/paths.h ng.o: innd.h perl.o: ../include/clibrary.h perl.o: ../include/configdata.h perl.o: ../include/configdata.h perl.o: ../include/libinn.h perl.o: ../include/libinn.h perl.o: ../include/logging.h perl.o: ../include/macros.h perl.o: ../include/nntp.h perl.o: ../include/nntp.h perl.o: ../include/paths.h perl.o: art.h perl.o: innd.h proc.o: ../include/clibrary.h proc.o: ../include/configdata.h proc.o: ../include/configdata.h proc.o: ../include/libinn.h proc.o: ../include/libinn.h proc.o: ../include/logging.h proc.o: ../include/macros.h proc.o: ../include/nntp.h proc.o: ../include/nntp.h proc.o: ../include/paths.h proc.o: innd.h rc.o: ../include/clibrary.h rc.o: ../include/configdata.h rc.o: ../include/configdata.h rc.o: ../include/libinn.h rc.o: ../include/logging.h rc.o: ../include/macros.h rc.o: ../include/macros.h rc.o: ../include/nntp.h rc.o: ../include/paths.h rc.o: ../include/paths.h rc.o: innd.h site.o: ../include/clibrary.h site.o: ../include/configdata.h site.o: ../include/configdata.h site.o: ../include/libinn.h site.o: ../include/libinn.h site.o: ../include/logging.h site.o: ../include/macros.h site.o: ../include/nntp.h site.o: ../include/nntp.h site.o: ../include/paths.h site.o: innd.h tcl.o: ../include/clibrary.h tcl.o: ../include/configdata.h tcl.o: ../include/configdata.h tcl.o: ../include/libinn.h tcl.o: ../include/logging.h tcl.o: ../include/macros.h tcl.o: ../include/macros.h tcl.o: ../include/nntp.h tcl.o: ../include/paths.h tcl.o: ../include/paths.h tcl.o: innd.h inn-1.7.2/innd/cc.c0100644000175100001440000011653606443103542012324 0ustar mdusers/* $Revision: 1.53 $ ** ** Routines for the control channel. Create a Unix-domain datagram socket ** that processes on the local server send messages to. The control ** channel is used only by ctlinnd to tell the server to perform ** special functions. We use datagrams so that we don't need to do an ** accept() and tie up another descriptor. Recvfrom seems to be broken on ** several systems, so the client passes in the socket name. ** ** This module completely rips away all pretense of software layering. */ #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" #include "inndcomm.h" #if defined(DO_HAVE_UNIX_DOMAIN) #include #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ /* ** An entry in the dispatch table. The name, and implementing function, ** of every command we support. */ typedef struct _CCDISPATCH { char Name; int argc; STRING (*Function)(); } CCDISPATCH; STATIC STRING CCaddhist(); STATIC STRING CCallow(); STATIC STRING CCbegin(); STATIC STRING CCchgroup(); STATIC STRING CCdrop(); STATIC STRING CCfeedinfo(); STATIC STRING CCflush(); STATIC STRING CCflushlogs(); STATIC STRING CCgo(); STATIC STRING CChangup(); STATIC STRING CCreserve(); STATIC STRING CClogmode(); STATIC STRING CCmode(); STATIC STRING CCname(); STATIC STRING CCnewgroup(); STATIC STRING CCparam(); STATIC STRING CCpause(); STATIC STRING CCreaders(); STATIC STRING CCrefile(); STATIC STRING CCreject(); STATIC STRING CCreload(); STATIC STRING CCrenumber(); STATIC STRING CCrmgroup(); STATIC STRING CCsend(); STATIC STRING CCshutdown(); STATIC STRING CCsignal(); STATIC STRING CCthrottle(); STATIC STRING CCtrace(); STATIC STRING CCxabort(); STATIC STRING CCxexec(); #if defined(DO_TCL) STATIC STRING CCfilter(); #endif /* defined(DO_TCL) */ #if defined(DO_PERL) STATIC STRING CCperl(); #endif /* defined(DO_PERL) */ STATIC char CCpath[] = _PATH_NEWSCONTROL; STATIC char **CCargv; STATIC char CCnosite[] = "1 No such site"; STATIC char CCwrongtype[] = "1 Wrong site type"; STATIC char CCnogroup[] = "1 No such group"; STATIC char CCnochannel[] = "1 No such channel"; STATIC char CCnoreason[] = "1 Empty reason"; STATIC char CCbigreason[] = "1 Reason too long"; STATIC char CCnotrunning[] = "1 Must be running"; STATIC BUFFER CCreply; STATIC CHANNEL *CCchan; STATIC int CCwriter; STATIC CCDISPATCH CCcommands[] = { { SC_ADDHIST, 5, CCaddhist }, { SC_ALLOW, 1, CCallow }, { SC_BEGIN, 1, CCbegin }, { SC_CANCEL, 1, CCcancel }, { SC_CHANGEGROUP, 2, CCchgroup }, { SC_CHECKFILE, 0, CCcheckfile }, { SC_DROP, 1, CCdrop }, { SC_FEEDINFO, 1, CCfeedinfo }, #if defined(DO_TCL) { SC_FILTER, 1, CCfilter }, #endif /* defined(DO_TCL) */ #if defined(DO_PERL) { SC_PERL, 1, CCperl }, #endif /* defined(DO_PERL) */ { SC_FLUSH, 1, CCflush }, { SC_FLUSHLOGS, 0, CCflushlogs }, { SC_GO, 1, CCgo }, { SC_HANGUP, 1, CChangup }, { SC_LOGMODE, 0, CClogmode }, { SC_MODE, 0, CCmode }, { SC_NAME, 1, CCname }, { SC_NEWGROUP, 3, CCnewgroup }, { SC_PARAM, 2, CCparam }, { SC_PAUSE, 1, CCpause }, { SC_READERS, 2, CCreaders }, { SC_REFILE, 2, CCrefile }, { SC_REJECT, 1, CCreject }, { SC_RENUMBER, 1, CCrenumber }, { SC_RELOAD, 2, CCreload }, { SC_RESERVE, 1, CCreserve }, { SC_RMGROUP, 1, CCrmgroup }, { SC_SEND, 2, CCsend }, { SC_SHUTDOWN, 1, CCshutdown }, { SC_SIGNAL, 2, CCsignal }, { SC_THROTTLE, 1, CCthrottle }, { SC_TRACE, 2, CCtrace }, { SC_XABORT, 1, CCxabort }, { SC_XEXEC, 1, CCxexec } }; STATIC SIGHANDLER CCresetup(); void CCcopyargv(av) char *av[]; { register char **v; register int i; /* Get the vector size. */ for (i = 0; av[i]; i++) continue; /* Get the vector, copy each element. */ for (v = CCargv = NEW(char*, i + 1); *av; av++) *v++ = COPY(*av); *v = NULL; } /* ** Return a string representing our operating mode. */ STATIC STRING CCcurrmode() { static char buff[32]; /* Server's mode. */ switch (Mode) { default: (void)sprintf(buff, "Unknown %d", Mode); return buff; case OMrunning: return "running"; case OMpaused: return "paused"; case OMthrottled: return "throttled"; } } /* ** Add <> around Message-ID if needed. */ STATIC STRING CCgetid(p, store) char *p; char **store; { static char NULLMESGID[] = "1 Empty Message-ID"; static BUFFER Save; int i; if (*p == '\0') return NULLMESGID; if (*p == '<') { if (p[1] == '\0' || p[1] == '>') return NULLMESGID; *store = p; return NULL; } /* Make sure the Message-ID buffer has room. */ i = 1 + strlen(p) + 1 + 1; if (Save.Data == NULL) { Save.Size = i; Save.Data = NEW(char, Save.Size); } else if (Save.Size < i) { Save.Size = i; RENEW(Save.Data, char, Save.Size); } *store = Save.Data; (void)sprintf(*store, "<%s>", p); return NULL; } /* ** Abort and dump core. */ STATIC STRING CCxabort(av) char *av[]; { syslog(L_FATAL, "%s abort %s", LogName, av[0]); abort(); syslog(L_FATAL, "%s cant abort %m", LogName); CleanupAndExit(1, av[0]); /* NOTREACHED */ } /* ** Do the work needed to add a history entry. */ STATIC STRING CCaddhist(av) char *av[]; { static char DIGITS[] = "0123456789"; ARTDATA Data; STRING p; BOOL ok; /* Check the fields. */ if ((p = CCgetid(av[0], &Data.MessageID)) != NULL) return p; if (HIShavearticle(Data.MessageID)) return "1 Duplicate"; if (strspn(av[1], DIGITS) != strlen(av[1])) return "1 Bad arrival date"; Data.Arrived = atol(av[1]); if (strspn(av[2], DIGITS) != strlen(av[2])) return "1 Bad expiration date"; Data.Expires = atol(av[2]); if (strspn(av[3], DIGITS) != strlen(av[3])) return "1 Bad posted date"; Data.Posted = atol(av[3]); if (Mode == OMrunning) ok = HISwrite(&Data, av[4]); else { /* Possible race condition, but documented in ctlinnd manpage. */ HISsetup(); ok = HISwrite(&Data, av[4]); HISclose(); } return ok ? NULL : "1 Write failed"; } /* ** Do the work to allow foreign connectiosn. */ STATIC STRING CCallow(av) char *av[]; { char *p; if (RejectReason == NULL) return "1 Already allowed"; p = av[0]; if (*p && !EQ(p, RejectReason)) return "1 Wrong reason"; DISPOSE(RejectReason); RejectReason = NULL; return NULL; } /* ** Do the work needed to start feeding a (new) site. */ STATIC STRING CCbegin(av) char *av[]; { SITE *sp; register int i; register int length; register STRING p; register char **strings; register NEWSGROUP *ngp; STRING error; char *subbed; char *poison; /* If site already exists, drop it. */ if (SITEfind(av[0]) != NULL && (p = CCdrop(av)) != NULL) return p; /* Find the named site. */ length = strlen(av[0]); for (strings = SITEreadfile(TRUE), i = 0; (p = strings[i]) != NULL; i++) if ((p[length] == NF_FIELD_SEP || p[length] == NF_SUBFIELD_SEP) && caseEQn(p, av[0], length)) { p = COPY(p); break; } if (p == NULL) return CCnosite; if (p[0] == 'M' && p[1] == 'E' && p[2] == NF_FIELD_SEP) sp = &ME; else { /* Get space for the new site entry, and space for it in all * the groups. */ for (i = nSites, sp = Sites; --i >= 0; sp++) if (sp->Name == NULL) break; if (i < 0) { nSites++; RENEW(Sites, SITE, nSites); sp = &Sites[nSites - 1]; sp->Next = sp->Prev = NOSITE; for (i = nGroups, ngp = Groups; --i >= 0; ngp++) { RENEW(ngp->Sites, int, nSites); RENEW(ngp->Poison, int, nSites); } } } /* Parse. */ subbed = NEW(char, nGroups); poison = NEW(char, nGroups); error = SITEparseone(p, sp, subbed, poison); DISPOSE(subbed); DISPOSE(poison); if (error != NULL) { DISPOSE(p); syslog(L_ERROR, "%s bad_newsfeeds %s", av[0], error); return "1 Parse error"; } if (sp != &ME && (!SITEsetup(sp) || !SITEfunnelpatch())) return "1 Startup error"; SITEforward(sp, "begin"); return NULL; } /* ** Common code to change a group's flags. */ STATIC STRING CCdochange(ngp, Rest) register NEWSGROUP *ngp; char *Rest; { int length; char *p; if (ngp->Rest[0] == Rest[0]) { length = strlen(Rest); if (ngp->Rest[length] == '\n' && EQn(ngp->Rest, Rest, length)) return "0 Group status unchanged"; } if (Mode != OMrunning) return CCnotrunning; p = COPY(ngp->Name); if (!ICDchangegroup(ngp, Rest)) { syslog(L_NOTICE, "%s cant change_group %s to %s", LogName, p, Rest); DISPOSE(p); return "1 Change failed (probably can't write active?)"; } syslog(L_NOTICE, "%s change_group %s to %s", LogName, p, Rest); DISPOSE(p); return NULL; } /* ** Change the mode of a newsgroup. */ STATIC STRING CCchgroup(av) char *av[]; { NEWSGROUP *ngp; char *Rest; if ((ngp = NGfind(av[0])) == NULL) return CCnogroup; Rest = av[1]; if (Rest[0] != NF_FLAG_ALIAS) { Rest[1] = '\0'; if (CTYPE(isupper, Rest[0])) Rest[0] = tolower(Rest[0]); } return CCdochange(ngp, Rest); } /* ** Cancel a message. */ STRING CCcancel(av) char *av[]; { ARTDATA Data; STRING p; Data.Posted = Data.Arrived = Now.time; Data.Expires = 0; Data.Feedsite = "?"; if ((p = CCgetid(av[0], &Data.MessageID)) != NULL) return p; if (Mode == OMrunning) ARTcancel(&Data, Data.MessageID, TRUE); else { /* Possible race condition, but documented in ctlinnd manpage. */ HISsetup(); ARTcancel(&Data, Data.MessageID, TRUE); HISclose(); } #if defined(DO_LOG_CANCEL_COMMANDS) syslog(L_NOTICE, "%s cancelled %s", LogName, Data.MessageID); #endif /* defined(DO_LOG_CANCEL_COMMANDS) */ return NULL; } /* ** Syntax-check the newsfeeds file. */ /* ARGSUSED */ STRING CCcheckfile(av) char *av[]; { register char **strings; register char *p; register int i; register int errors; STRING error; SITE fake; /* Parse all site entries. */ strings = SITEreadfile(FALSE); fake.Buffer.Size = 0; fake.Buffer.Data = NULL; for (errors = 0, i = 0; (p = strings[i]) != NULL; i++) { if ((error = SITEparseone(p, &fake, (char *)NULL, (char *)NULL)) != NULL) { syslog(L_ERROR, "%s bad_newsfeeds %s", MaxLength(p, p), error); errors++; } SITEfree(&fake); } DISPOSE(strings); if (errors == 0) return NULL; if (CCreply.Data == NULL) { /* If we got the "-s" flag, then CCsetup hasn't been called yet. */ CCreply.Size = SMBUF; CCreply.Data = NEW(char, CCreply.Size); } else if (CCreply.Size < SMBUF) { CCreply.Size = SMBUF; RENEW(CCreply.Data, char, CCreply.Size); } (void)sprintf(CCreply.Data, "1 Found %d errors -- see syslog", errors); return CCreply.Data; } /* ** Drop a site. */ STATIC STRING CCdrop(av) char *av[]; { SITE *sp; register NEWSGROUP *ngp; register int *ip; register int idx; register int i; register int j; if ((sp = SITEfind(av[0])) == NULL) return CCnosite; SITEdrop(sp); /* Loop over all groups, and if the site is in a group, clobber it. */ for (idx = sp - Sites, i = nGroups, ngp = Groups; --i >= 0; ngp++) { for (j = ngp->nSites, ip = ngp->Sites; --j >= 0; ip++) if (*ip == idx) *ip = NOSITE; for (j = ngp->nPoison, ip = ngp->Poison; --j >= 0; ip++) if (*ip == idx) *ip = NOSITE; } return NULL; } /* ** Return info on the feeds for one, or all, sites */ STATIC STRING CCfeedinfo(av) char *av[]; { register SITE *sp; register char *p; register int i; BUFFset(&CCreply, "0 ", 2); p = av[0]; if (*p != '\0') { if ((sp = SITEfind(p)) == NULL) return "1 No such site"; SITEinfo(&CCreply, sp, TRUE); while ((sp = SITEfindnext(p, sp)) != NULL) SITEinfo(&CCreply, sp, TRUE); } else for (i = nSites, sp = Sites; --i >= 0; sp++) if (sp->Name) SITEinfo(&CCreply, sp, FALSE); BUFFappend(&CCreply, "", 1); return CCreply.Data; } #if defined(DO_TCL) STATIC STRING CCfilter(av) char *av[]; { char *p; switch (av[0][0]) { default: return "1 Bad flag"; case 'y': if (TCLFilterActive) return "1 tcl filter already enabled"; TCLfilter(TRUE); break; case 'n': if (!TCLFilterActive) return "1 tcl filter already disabled"; TCLfilter(FALSE); break; } return NULL; } #endif /* defined(DO_TCL) */ #if defined(DO_PERL) #include #include #include extern CV *perl_filter_cv ; STATIC STRING CCperl(av) char *av[]; { char *p; extern int PerlFilterActive; switch (av[0][0]) { default: return "1 Bad flag"; case 'y': if (PerlFilterActive) return "1 Perl filter already enabled"; else if (perl_filter_cv == NULL) return "1 Perl filter not defined" ; PerlFilter(TRUE); break; case 'n': if (!PerlFilterActive) return "1 Perl filter already disabled"; PerlFilter(FALSE); break; } return NULL; } #endif /* defined(DO_PERL) */ /* ** Flush all sites or one site. */ STATIC STRING CCflush(av) char *av[]; { register SITE *sp; register int i; register char *p; p = av[0]; if (*p == '\0') { ICDwrite(); for (sp = Sites, i = nSites; --i >= 0; sp++) SITEflush(sp, TRUE); syslog(L_NOTICE, "%s flush_all", LogName); } else { if ((sp = SITEfind(p)) == NULL) return CCnosite; syslog(L_NOTICE, "%s flush", sp->Name); SITEflush(sp, TRUE); } return NULL; } /* ** Flush the log files. */ /* ARGSUSED0 */ STATIC STRING CCflushlogs(av) char *av[]; { if (Debug) return "1 In debug mode"; ICDwrite(); syslog(L_NOTICE, "%s flushlogs %s", LogName, CCcurrmode()); ReopenLog(Log); ReopenLog(Errlog); return NULL; } /* ** Leave paused or throttled mode. */ STATIC STRING CCgo(av) char *av[]; { static char YES[] = "y"; char *p; p = av[0]; if (Reservation && EQ(p, Reservation)) { DISPOSE(Reservation); Reservation = NULL; } if (RejectReason && EQ(p, RejectReason)) { DISPOSE(RejectReason); RejectReason = NULL; } if (Mode == OMrunning) return "1 Already running"; if (*p && !EQ(p, ModeReason)) return "1 Wrong reason"; #if defined(DO_PERL) PerlMode(Mode, OMrunning, p); #endif /* defined(DO_PERL) */ DISPOSE(ModeReason); ModeReason = NULL; Mode = OMrunning; if (NNRPReason && NNRPFollows) { av[0] = YES; av[1] = p; (void)CCreaders(av); } if (ErrorCount < 0) ErrorCount = IO_ERROR_COUNT; HISsetup(); syslog(L_NOTICE, "%s running", LogName); if (ICDneedsetup) ICDsetup(TRUE); SCHANwakeup((POINTER)&Mode); return NULL; } /* ** Hangup a channel. */ STATIC STRING CChangup(av) char *av[]; { register CHANNEL *cp; register int fd; register char *p; int i; /* Parse the argument, a channel number. */ for (p = av[0], fd = 0; *p; p++) { if (!CTYPE(isdigit, *p)) return "1 Bad channel number"; fd = fd * 10 + *p - '0'; } /* Loop over all channels for the desired one. */ for (i = 0; (cp = CHANiter(&i, CTany)) != NULL; ) if (cp->fd == fd) { p = CHANname(cp); switch (cp->Type) { default: (void)sprintf(CCreply.Data, "1 Can't close %s", p); return CCreply.Data; case CTexploder: case CTprocess: case CTfile: case CTnntp: case CTreject: syslog(L_NOTICE, "%s hangup", p); CHANclose(cp, p); return NULL; } } return "1 Not active"; } /* ** Return our operating mode. */ /* ARGSUSED */ STATIC STRING CCmode(av) char *av[]; { register char *p; register int i; int h; char buff[BUFSIZ]; #if defined(DO_PERL) extern int PerlFilterActive; #endif /* defined(DO_PERL) */ /* nb: We assume here that BUFSIZ is >= 512, and that none of * ModeReason RejectReason Reservation or NNRPReason is longer than * MAX_REASON_LEN bytes (or actually, the average of their lengths is * <= MAX_REASON_LEN). If this is not true, the sprintf's/strcpy's * below are likely to overflow buff with somewhat nasty * consequences... */ p = buff; p += strlen(strcpy(buff, "0 Server ")); /* Server's mode. */ switch (Mode) { default: (void)sprintf(p, "Unknown %d", Mode); p += strlen(p); break; case OMrunning: p += strlen(strcpy(p, "running")); break; case OMpaused: p += strlen(strcpy(p, "paused ")); p += strlen(strcpy(p, ModeReason)); break; case OMthrottled: p += strlen(strcpy(p, "throttled ")); p += strlen(strcpy(p, ModeReason)); break; } *p++ = '\n'; if (RejectReason) { p += strlen(strcpy(p, "Rejecting ")); p += strlen(strcpy(p, RejectReason)); } else p += strlen(strcpy(p, "Allowing remote connections")); /* Server parameters. */ for (i = 0, h = 0; CHANiter(&h, CTnntp) != NULL; ) i++; *p++ = '\n'; (void)sprintf(p, "Parameters c %ld i %d (%d) l %ld o %d t %ld H %d T %d X %d %s %s", (long)Cutoff / (24L * 60L * 60L), MaxIncoming, i, LargestArticle, MaxOutgoing, (long)TimeOut.tv_sec, RemoteLimit, RemoteTotal, (int) RemoteTimer, AmSlave ? "slave" : "normal", AnyIncoming ? "any" : "specified"); p += strlen(p); /* Reservation. */ *p++ = '\n'; if (Reservation) { (void)sprintf(p, "Reserved %s", Reservation); p += strlen(p); } else p += strlen(strcpy(p, "Not reserved")); /* Newsreaders. */ *p++ = '\n'; p += strlen(strcpy(p, "Readers ")); if (NNRPFollows) p += strlen(strcpy(p, "follow ")); else p += strlen(strcpy(p, "separate ")); if (NNRPReason == NULL) p += strlen(strcpy(p, "enabled")); else { (void)sprintf(p, "disabled %s", NNRPReason); p += strlen(p); } #if defined(DO_TCL) *p++ = '\n'; p += strlen(strcpy(p, "Tcl filtering ")); if (TCLFilterActive) p += strlen(strcpy(p, "enabled")); else p += strlen(strcpy(p, "disabled")); #endif /* defined(DO_TCL) */ #if defined(DO_PERL) *p++ = '\n'; p += strlen(strcpy(p, "Perl filtering ")); if (PerlFilterActive) p += strlen(strcpy(p, "enabled")); else p += strlen(strcpy(p, "disabled")); #endif /* defined(DO_PERL) */ i = strlen(buff); if (CCreply.Size <= i) { CCreply.Size = i; RENEW(CCreply.Data, char, CCreply.Size + 1); } (void)strcpy(CCreply.Data, buff); return CCreply.Data; } /* ** Log our operating mode (via syslog). */ /* ARGSUSED */ STATIC STRING CClogmode(av) char *av[]; { syslog(L_NOTICE, "%s servermode %s", LogName, CCcurrmode()); return NULL; } /* ** Name the channels. ("Name the bats -- simple names.") */ STATIC STRING CCname(av) char *av[]; { static char NL[] = "\n"; static char NIL[] = "\0"; register CHANNEL *cp; register char *p; register int count; int i; p = av[0]; if (*p != '\0') { if ((cp = CHANfromdescriptor(atoi(p))) == NULL) return COPY(CCnochannel); (void)sprintf(CCreply.Data, "0 %s", CHANname(cp)); return CCreply.Data; } BUFFset(&CCreply, "0 ", 2); for (count = 0, i = 0; (cp = CHANiter(&i, CTany)) != NULL; ) { if (cp->Type == CTfree) continue; if (++count > 1) BUFFappend(&CCreply, NL, 1); p = CHANname(cp); BUFFappend(&CCreply, p, strlen(p)); } BUFFappend(&CCreply, NIL, 1); return CCreply.Data; } /* ** Create a newsgroup. */ STATIC STRING CCnewgroup(av) char *av[]; { static char TIMES[] = _PATH_ACTIVETIMES; static char WHEN[] = "updating active.times"; register int fd; register char *p; NEWSGROUP *ngp; char *Name; char *Rest; STRING who; char *buff; int oerrno; Name = av[0]; if (Name[0] == '.' || strspn(Name, "0123456789") == strlen(Name)) return "1 Illegal newsgroup name"; for (p = Name; *p; p++) if (*p == '.') { if (p[1] == '.' || p[1] == '\0') return "1 Double or trailing period in newsgroup name"; } else if (ISWHITE(*p) || *p == ':' || *p == '!' || *p == '/') return "1 Illegal character in newsgroup name"; Rest = av[1]; if (Rest[0] != NF_FLAG_ALIAS) { Rest[1] = '\0'; if (CTYPE(isupper, Rest[0])) Rest[0] = tolower(Rest[0]); } if (strlen(Name) + strlen(Rest) > (SIZE_T)(SMBUF - 24)) return "1 Name too long"; if ((ngp = NGfind(Name)) != NULL) return CCdochange(ngp, Rest); /* Update the log of groups created. Don't use stdio because SunOS * 4.1 has broken libc which can't handle fd's greater than 127. */ if ((fd = open(TIMES, O_WRONLY | O_APPEND | O_CREAT, 0664)) < 0) { oerrno = errno; syslog(L_ERROR, "%s cant fopen %s %m", LogName, TIMES); IOError(WHEN, oerrno); } else { who = av[2]; if (*who == '\0') who = NEWSMASTER; /* %s + ' ' + %ld + ' ' + %s + '\n' + terminator */ buff = NEW(char, strlen(Name) + 1 + 20 + 1 + strlen(who) + 1 + 1); (void)sprintf(buff, "%s %ld %s\n", Name, Now.time, who); if (xwrite(fd, buff, strlen(buff)) < 0) { oerrno = errno; syslog(L_ERROR, "%s cant write %s %m", LogName, TIMES); IOError(WHEN, oerrno); } if (close(fd) < 0) { oerrno = errno; syslog(L_ERROR, "%s cant close %s %m", LogName, TIMES); IOError(WHEN, oerrno); } DISPOSE(buff); if (AmRoot) xchown(TIMES); } /* Update the in-core data. */ if (!ICDnewgroup(Name, Rest)) return "1 Failed"; syslog(L_NOTICE, "%s newgroup %s as %s", LogName, Name, Rest); if (*Rest != NF_FLAG_ALIAS) { /* Create the spool directory. */ for (p = Name; *p; p++) if (*p == '.') *p = '/'; if (!MakeSpoolDirectory(Name)) syslog(L_NOTICE, "%s cant mkdir %s %m", LogName, Name); } return NULL; } /* ** Parse and set a boolean flag. */ STATIC BOOL CCparsebool(name, bp, value) char name; BOOL *bp; char value; { switch (value) { default: return FALSE; case 'y': *bp = FALSE; break; case 'n': *bp = TRUE; break; } syslog(L_NOTICE, "%s changed -%c %c", LogName, name, value); return TRUE; } /* ** Change a running parameter. */ STATIC STRING CCparam(av) char *av[]; { static char BADVAL[] = "1 Bad value"; char *p; p = av[1]; switch (av[0][0]) { default: return "1 Unknown parameter"; case 'a': if (!CCparsebool('a', &AnyIncoming, *p)) return BADVAL; break; case 'c': Cutoff = atoi(p) * 24 * 60 * 60; syslog(L_NOTICE, "%s changed -c %d", LogName, Cutoff); break; case 'i': MaxIncoming = atoi(p); syslog(L_NOTICE, "%s changed -i %d", LogName, MaxIncoming); break; case 'l': LargestArticle = atol(p); syslog(L_NOTICE, "%s changed -l %ld", LogName, LargestArticle); break; case 'n': if (!CCparsebool('n', &NNRPFollows, *p)) return BADVAL; break; case 'o': MaxOutgoing = atoi(p); syslog(L_NOTICE, "%s changed -o %d", LogName, MaxOutgoing); break; case 't': TimeOut.tv_sec = atol(p); syslog(L_NOTICE, "%s changed -t %ld", LogName, (long)TimeOut.tv_sec); break; case 'H': RemoteLimit = atoi(p); syslog(L_NOTICE, "%s changed -H %d", LogName, RemoteLimit); break; case 'T': RemoteTotal = atoi(p); if (RemoteTotal > REMOTETABLESIZE) RemoteTotal = REMOTETABLESIZE; syslog(L_NOTICE, "%s changed -T %d", LogName, RemoteTotal); break; case 'X': RemoteTimer = (time_t) atoi(p); syslog(L_NOTICE, "%s changed -X %d", LogName, (int) RemoteTimer); break; } return NULL; } /* ** Common code to implement a pause or throttle. */ STRING CCblock(NewMode, reason) OPERATINGMODE NewMode; char *reason; { static char NO[] = "n"; STRING av[2]; if (*reason == '\0') return CCnoreason; if (strlen(reason) > MAX_REASON_LEN) /* MAX_REASON_LEN is as big as is safe */ return CCbigreason; if (Reservation) { if (!EQ(reason, Reservation)) { (void)sprintf(CCreply.Data, "1 Reserved \"%s\"", Reservation); return CCreply.Data; } DISPOSE(Reservation); Reservation = NULL; } #if defined(DO_PERL) PerlMode(Mode, NewMode, reason); #endif /* defined(DO_PERL) */ ICDwrite(); HISclose(); Mode = NewMode; if (ModeReason) DISPOSE(ModeReason); ModeReason = COPY(reason); if (NNRPReason == NULL && NNRPFollows) { av[0] = NO; av[1] = ModeReason; (void)CCreaders(av); } syslog(L_NOTICE, "%s %s %s", LogName, NewMode == OMpaused ? "paused" : "throttled", reason); return NULL; } /* ** Enter paused mode. */ STATIC STRING CCpause(av) char *av[]; { switch (Mode) { case OMrunning: return CCblock(OMpaused, av[0]); case OMpaused: return "1 Already paused"; case OMthrottled: return "1 Already throttled"; } return "1 Unknown mode"; } /* ** Allow or disallow newsreaders. */ STATIC STRING CCreaders(av) char *av[]; { char *p; switch (av[0][0]) { default: return "1 Bad flag"; case 'y': if (NNRPReason == NULL) return "1 Already allowing readers"; p = av[1]; if (*p && !EQ(p, NNRPReason)) return "1 Wrong reason"; DISPOSE(NNRPReason); NNRPReason = NULL; break; case 'n': if (NNRPReason) return "1 Already not allowing readers"; p = av[1]; if (*p == '\0') return CCnoreason; if (strlen(p) > MAX_REASON_LEN) /* MAX_REASON_LEN is as big as is safe */ return CCbigreason; NNRPReason = COPY(p); break; } return NULL; } /* ** Re-exec ourselves. */ STATIC STRING CCxexec(av) char *av[]; { static char INND[] = _PATH_INND; static char INNDSTART[] = _PATH_INNDSTART; char *p; if (CCargv == NULL) return "1 no argv!"; /* Get the pathname. */ p = av[0]; if (*p == '\0') CCargv[0] = AmRoot ? INND : INNDSTART; else if (EQ(p, "innd")) CCargv[0] = INND; else if (EQ(p, "inndstart")) CCargv[0] = INNDSTART; else return "1 Bad value"; JustCleanup(); syslog(L_NOTICE, "%s execv %s", LogName, CCargv[0]); (void)execv(CCargv[0], CCargv); syslog(L_FATAL, "%s cant execv %s %m", LogName, CCargv[0]); _exit(1); /* NOTREACHED */ } /* ** Refile an article. */ STATIC STRING CCrefile(av) char *av[]; { char *head; /* xxx multiple groups? */ if (NGfind(av[1]) == NULL) return CCnogroup; head = ARTreadheader(av[0]); if (head == NULL) return "1 No such article"; return "1 Not yet implemented"; } /* ** Reject remote readers. */ STATIC STRING CCreject(av) char *av[]; { if (RejectReason) return "1 Already rejecting"; if (strlen(av[0]) > MAX_REASON_LEN) /* MAX_REASON_LEN is as big as is safe */ return CCbigreason; RejectReason = COPY(av[0]); return NULL; } /* ** Re-read all in-core data. */ STATIC STRING CCreload(av) char *av[]; { static char BADSCHEMA[] = "1 Can't read schema"; #if defined(DO_PERL) static char BADPERLRELOAD[] = "1 Failed to define filter_art" ; #endif /* defined(DO_PERL) */ STRING p; p = av[0]; if (*p == '\0' || EQ(p, "all")) { SITEflushall(FALSE); HISclose(); RCreadlist(); HISsetup(); ICDwrite(); ICDsetup(TRUE); if (!ARTreadschema()) return BADSCHEMA; #if defined(DO_TCL) TCLreadfilter(); #endif /* defined(DO_TCL) */ #if defined(DO_PERL) PERLreadfilter (_PATH_PERL_FILTER_INND,"filter_art") ; #endif /* defined(DO_PERL) */ p = "all"; } else if (EQ(p, "active") || EQ(p, "newsfeeds")) { SITEflushall(FALSE); ICDwrite(); ICDsetup(TRUE); } else if (EQ(p, "history")) { HISclose(); HISsetup(); } else if (EQ(p, "hosts.nntp")) RCreadlist(); else if (EQ(p, "overview.fmt")) { if (!ARTreadschema()) return BADSCHEMA; } #if defined(DO_TCL) else if (EQ(p, "filter.tcl")) { TCLreadfilter(); } #endif /* defined(DO_TCL) */ #if defined(DO_PERL) else if (EQ(p, "filter.perl")) { if (!PERLreadfilter (_PATH_PERL_FILTER_INND,"filter_art")) return BADPERLRELOAD ; } #endif /* defined(DO_PERL) */ else return "1 Unknown reload type"; syslog(L_NOTICE, "%s reload %s %s", LogName, p, av[1]); return NULL; } /* ** Renumber the active file. */ STATIC STRING CCrenumber(av) char *av[]; { static char CANTRENUMBER[] = "1 Failed (see syslog)"; char *p; NEWSGROUP *ngp; if (Mode != OMrunning) return CCnotrunning; if (ICDneedsetup) return "1 Must first reload newsfeeds"; p = av[0]; if (*p) { if ((ngp = NGfind(p)) == NULL) return CCnogroup; if (!NGrenumber(ngp)) return CANTRENUMBER; } else if (!ICDrenumberactive()) return CANTRENUMBER; return NULL; } /* ** Reserve a lock. */ STATIC STRING CCreserve(av) char *av[]; { char *p; if (Mode != OMrunning) return CCnotrunning; p = av[0]; if (*p) { /* Trying to make a reservation. */ if (Reservation) return "1 Already reserved"; if (strlen(p) > MAX_REASON_LEN) /* MAX_REASON_LEN is as big as is safe */ return CCbigreason; Reservation = COPY(p); } else { /* Trying to remove a reservation. */ if (Reservation == NULL) return "1 Not reserved"; DISPOSE(Reservation); Reservation = NULL; } return NULL; } /* ** Remove a newsgroup. */ STATIC STRING CCrmgroup(av) char *av[]; { NEWSGROUP *ngp; if ((ngp = NGfind(av[0])) == NULL) return CCnogroup; /* Update the in-core data. */ if (!ICDrmgroup(ngp)) return "1 Failed"; syslog(L_NOTICE, "%s rmgroup %s", LogName, av[0]); return NULL; } /* ** Send a command line to an exploder. */ STATIC STRING CCsend(av) char *av[]; { SITE *sp; if ((sp = SITEfind(av[0])) == NULL) return CCnosite; if (sp->Type != FTexploder) return CCwrongtype; SITEwrite(sp, av[1]); return NULL; } /* ** Shut down the system. */ STATIC STRING CCshutdown(av) char *av[]; { syslog(L_NOTICE, "%s shutdown %s", LogName, av[0]); CleanupAndExit(0, av[0]); /* NOTREACHED */ } /* ** Send a signal to a site's feed. */ STATIC STRING CCsignal(av) char *av[]; { register SITE *sp; register char *p; int s; int oerrno; /* Parse the signal. */ p = av[0]; if (*p == '-') p++; if (caseEQ(p, "HUP")) s = SIGHUP; else if (caseEQ(p, "INT")) s = SIGINT; else if (caseEQ(p, "TERM")) s = SIGTERM; else if ((s = atoi(p)) <= 0) return "1 Invalid signal"; /* Parse the site. */ p = av[1]; if ((sp = SITEfind(p)) == NULL) return CCnosite; if (sp->Type != FTchannel && sp->Type != FTexploder) return CCwrongtype; if (sp->Process < 0) return "1 Site has no process"; /* Do it. */ if (kill(sp->pid, s) < 0) { oerrno = errno; syslog(L_ERROR, "%s cant kill %ld %d site %s, %m", LogName, (long) sp->pid, s, p); (void)sprintf(CCreply.Data, "1 Can't signal process %ld, %s", (long) sp->pid, strerror(oerrno)); return CCreply.Data; } return NULL; } /* ** Enter throttled mode. */ STATIC STRING CCthrottle(av) char *av[]; { char *p; p = av[0]; switch (Mode) { case OMpaused: if (*p && !EQ(p, ModeReason)) return "1 Already paused"; /* FALLTHROUGH */ case OMrunning: return CCblock(OMthrottled, p); case OMthrottled: return "1 Already throttled"; } return "1 unknown mode"; } /* ** Add or remove tracing. */ STATIC STRING CCtrace(av) char *av[]; { char *p; BOOL Flag; STRING word; CHANNEL *cp; /* Parse the flag. */ p = av[1]; switch (p[0]) { default: return "1 Bad trace flag"; case 'y': case 'Y': Flag = TRUE; word = "on"; break; case 'n': case 'N': Flag = FALSE; word = "off"; break; } /* Parse what's being traced. */ p = av[0]; switch (*p) { default: return "1 Bad trace item"; case 'i': case 'I': Tracing = Flag; syslog(L_NOTICE, "%s trace innd %s", LogName, word); break; case 'n': case 'N': NNRPTracing = Flag; syslog(L_NOTICE, "%s trace nnrpd %s", LogName, word); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if ((cp = CHANfromdescriptor(atoi(p))) == NULL) return CCnochannel; CHANtracing(cp, Flag); break; } return NULL; } /* ** Split up the text into fields and stuff them in argv. Return the ** number of elements or -1 on error. */ STATIC int CCargsplit(p, end, argv, size) register char *p; register char *end; register char **argv; register int size; { char **save; for (save = argv, *argv++ = p, size--; p < end; p++) if (*p == SC_SEP) { if (--size <= 0) return -1; *p = '\0'; *argv++ = p + 1; } *argv = NULL; return argv - save; } /* ** Read function. Read and process the message. */ STATIC FUNCTYPE CCreader(cp) CHANNEL *cp; { static char TOOLONG[] = "0 Reply too long for server to send"; register CCDISPATCH *dp; register STRING p; register char *q; ICC_MSGLENTYPE bufflen; ICC_PROTOCOLTYPE protocol ; #if defined(DO_HAVE_UNIX_DOMAIN) struct sockaddr_un client; #else int written; #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ int i; char buff[BIG_BUFFER + 2]; char copy[BIG_BUFFER + 2]; char *argv[SC_MAXFIELDS + 2]; int argc; int len; char *tbuff ; if (cp != CCchan) { syslog(L_ERROR, "%s internal CCreader wrong channel 0x%x not 0x%x", LogName, cp, CCchan); return; } #if defined (DO_HAVE_UNIX_DOMAIN) i = RECVorREAD(CCchan->fd, buff, BIG_BUFFER) ; if (i < 0) { syslog(L_ERROR, "%s cant recv CCreader %m", LogName); return; } else if (i == 0) { syslog(L_ERROR, "%s cant recv CCreader empty", LogName); return; } else if (i < HEADER_SIZE) { syslog(L_ERROR, "%s cant recv CCreader header-length %m", LogName); return; } memcpy (&protocol,buff,sizeof (protocol)) ; memcpy (&bufflen,buff + sizeof (protocol),sizeof (bufflen)) ; bufflen = ntohs (bufflen) ; if (i != bufflen) { syslog(L_ERROR, "%s cant recv CCreader short-read %m", LogName); return; } i -= HEADER_SIZE ; memmove (buff,buff + HEADER_SIZE,i) ; buff[i] = '\0'; if (protocol != ICC_PROTOCOL_1) { syslog(L_ERROR, "%s CCreader protocol mismatch", LogName) ; return ; } #else /* defined (DO_HAVE_UNIX_DOMAIN) */ i = RECVorREAD(CCchan->fd, buff, HEADER_SIZE) ; if (i < 0) { syslog(L_ERROR, "%s cant read CCreader header %m", LogName); return; } else if (i == 0) { syslog(L_ERROR, "%s cant read CCreader header empty", LogName); return; } else if (i != HEADER_SIZE) { syslog(L_ERROR, "%s cant read CCreader header-length %m", LogName); return; } memcpy (&protocol,buff,sizeof (protocol)) ; memcpy (&bufflen,buff + sizeof (protocol),sizeof (bufflen)) ; bufflen = ntohs (bufflen) - HEADER_SIZE ; i = RECVorREAD(CCchan->fd, buff, bufflen) ; if (i < 0) { syslog(L_ERROR, "%s cant read CCreader buffer %m", LogName); return; } else if (i == 0) { syslog(L_ERROR, "%s cant read CCreader buffer empty", LogName); return; } else if (i != bufflen) { syslog(L_ERROR, "%s cant read CCreader buffer-length %m", LogName); return; } buff[i] = '\0'; if (protocol != ICC_PROTOCOL_1) { syslog(L_ERROR, "%s CCreader protocol mismatch", LogName) ; return ; } #endif /* defined (DO_HAVE_UNIX_DOMAIN) */ /* Copy to a printable buffer, and log. */ (void)strcpy(copy, buff); for (p = NULL, q = copy; *q; q++) if (*q == SC_SEP) { *q = ':'; if (p == NULL) p = q + 1; } syslog(L_CC_CMD, "%s", p ? p : copy); /* Split up the fields, get the command letter. */ if ((argc = CCargsplit(buff, &buff[i], argv, SIZEOF(argv))) < 2 || argc == SIZEOF(argv)) { syslog(L_ERROR, "%s bad_fields CCreader", LogName); return; } p = argv[1]; i = *p; /* Dispatch to the command function. */ for (argc -= 2, dp = CCcommands; dp < ENDOF(CCcommands); dp++) if (i == dp->Name) { if (argc != dp->argc) p = "1 Wrong number of parameters"; else p = (*dp->Function)(&argv[2]); break; } if (dp == ENDOF(CCcommands)) { syslog(L_NOTICE, "%s bad_message %c", LogName, i); p = "1 Bad command"; } else if (p == NULL) p = "0 Ok"; /* Build the reply address and send the reply. */ len = strlen(p) + HEADER_SIZE ; tbuff = NEW(char,len + 1); protocol = ICC_PROTOCOL_1 ; memcpy (tbuff,&protocol,sizeof (protocol)) ; tbuff += sizeof (protocol) ; bufflen = htons (len) ; memcpy (tbuff,&bufflen,sizeof (bufflen)) ; tbuff += sizeof (bufflen) ; strcpy (tbuff,p) ; tbuff -= HEADER_SIZE ; #if defined(DO_HAVE_UNIX_DOMAIN) (void)memset((POINTER)&client, 0, sizeof client); client.sun_family = AF_UNIX; (void)strcpy(client.sun_path, argv[0]); if (sendto(CCwriter, tbuff, len, 0, (struct sockaddr *)&client, AF_UNIX_SOCKSIZE(client)) < 0) { i = errno; syslog(i == ENOENT ? L_NOTICE : L_ERROR, "%s cant sendto CCreader bytes %d %m", LogName, len); if (i == EMSGSIZE) (void)sendto(CCwriter, TOOLONG, STRLEN(TOOLONG), 0, (struct sockaddr *)&client, AF_UNIX_SOCKSIZE(client)); } #else if ((i = open(argv[0], O_WRONLY | O_NDELAY)) < 0) syslog(L_ERROR, "%s cant open %s %m", LogName, argv[0]); else { if ((written = write(i, tbuff, len)) != len) if (written < 0) syslog(L_ERROR, "%s cant write %s %m", LogName, argv[0]); else syslog(L_ERROR, "%s cant write %s", LogName, argv[0]); if (close(i) < 0) syslog(L_ERROR, "%s cant close %s %m", LogName, argv[0]); } #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ DISPOSE (tbuff) ; } /* ** Called when a write-in-progress is done on the channel. Shouldn't happen. */ STATIC FUNCTYPE CCwritedone() { syslog(L_ERROR, "%s internal CCwritedone", LogName); } /* ** Create the channel. */ void CCsetup() { int i; #if defined(DO_HAVE_UNIX_DOMAIN) struct sockaddr_un server; #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ /* Remove old detritus. */ if (unlink(CCpath) < 0 && errno != ENOENT) { syslog(L_FATAL, "%s cant unlink %s %m", LogName, CCpath); exit(1); } #if defined(DO_HAVE_UNIX_DOMAIN) /* Create a socket and name it. */ if ((i = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { syslog(L_FATAL, "%s cant socket %s %m", LogName, CCpath); exit(1); } (void)memset((POINTER)&server, 0, sizeof server); server.sun_family = AF_UNIX; (void)strcpy(server.sun_path, CCpath); if (bind(i, (struct sockaddr *)&server, AF_UNIX_SOCKSIZE(server)) < 0) { syslog(L_FATAL, "%s cant bind %s %m", LogName, CCpath); exit(1); } /* Create an unbound socket to reply on. */ if ((CCwriter = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { syslog(L_FATAL, "%s cant socket unbound %m", LogName); exit(1); } #else /* Create a named pipe and open it. */ if (mkfifo(CCpath, 0666) < 0) { syslog(L_FATAL, "%s cant mkfifo %s %m", LogName, CCpath); exit(1); } if ((i = open(CCpath, O_RDWR)) < 0) { syslog(L_FATAL, "%s cant open %s %m", LogName, CCpath); exit(1); } #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ CCchan = CHANcreate(i, CTcontrol, CSwaiting, CCreader, CCwritedone); syslog(L_NOTICE, "%s ccsetup %s", LogName, CHANname(CCchan)); RCHANadd(CCchan); if (CCreply.Size == 0) { CCreply.Size = SMBUF; CCreply.Data = NEW(char, CCreply.Size); } /* * Catch SIGUSR1 so that we can recreate the control channel when * needed (i.e. something has deleted our named socket. */ #if defined(SIGUSR1) (void)signal(SIGUSR1, CCresetup); #endif /* defined(SIGUSR1) */ } /* ** Cleanly shut down the channel. */ void CCclose() { CHANclose(CCchan, CHANname(CCchan)); CCchan = NULL; if (unlink(CCpath) < 0) syslog(L_ERROR, "%s cant unlink %s %m", LogName, CCpath); #if defined(DO_HAVE_UNIX_DOMAIN) if (close(CCwriter) < 0) syslog(L_ERROR, "%s cant close unbound %m", LogName); #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ } /* ** Restablish the control channel. */ STATIC SIGHANDLER CCresetup(s) int s; { (void)signal(s, CCresetup); CCclose(); CCsetup(); } inn-1.7.2/innd/newsfeeds.c0100644000175100001440000003574406443103542013723 0ustar mdusers/* $Revision: 1.38 $ ** ** Routines for the in-core data structures for the newsfeeds file. */ #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" STATIC SITE SITEnull; STATIC char SITEfeedspath[] = _PATH_NEWSFEEDS; /* ** Return a copy of an array of strings. */ STATIC char ** SITEcopystrings(av) char **av; { register char **new; register char **pp; char **save; for (pp = av; *pp; pp++) continue; for (new = save = NEW(char*, pp - av + 1), pp = av; *pp; pp++) *new++ = COPY(*pp); *new = NULL; return save; } /* ** Read the newsfeeds file, return a string array of entries. */ char ** SITEreadfile(ReadOnly) BOOL ReadOnly; { static char **old_strings; static time_t old_mtime; static ino_t old_ino; static OFFSET_T old_size; register char *p; register char *to; register char *site; register int i; struct stat Sb; char *data; if (old_strings != NULL) { /* If the file hasn't changed, return a copy of the old data. */ if (stat(SITEfeedspath, &Sb) >= 0 && Sb.st_ino == old_ino && Sb.st_size == old_size && Sb.st_mtime == old_mtime) return ReadOnly ? old_strings : SITEcopystrings(old_strings); /* Data's bad, toss it. */ for (i = 0; old_strings[i] != NULL; i++) DISPOSE(old_strings[i]); DISPOSE(old_strings); } /* Read in the file, note its statistics. */ if ((data = ReadInFile(SITEfeedspath, &Sb)) == NULL) { syslog(L_FATAL, "%s cant read %s %m", LogName, SITEfeedspath); exit(1); } old_mtime = Sb.st_mtime; old_ino = Sb.st_ino; old_size = Sb.st_size; /* Get a gross count of the number of sites. */ for (p = data, i = 0; (p = strchr(p, '\n')) != NULL; p++, i++) continue; /* Scan the file, parse all multi-line entries. */ for (old_strings = NEW(char*, i + 1), i = 0, to = p = data; *p; ) { for (site = to; *p; ) { if (*p == '\n') { p++; *to = '\0'; break; } if (*p == '\\' && p[1] == '\n') while (*++p && CTYPE(isspace, *p)) continue; else *to++ = *p++; } *to++ = '\0'; if (*site == COMMENT_CHAR || *site == '\0') continue ; if (strspn(site," \t") == strlen (site)) continue; old_strings[i++] = COPY(site); } old_strings[i] = NULL; DISPOSE(data); return ReadOnly ? old_strings : SITEcopystrings(old_strings); } /* ** Modify "subbed" according to the patterns in "patlist." */ STATIC void SITEsetlist(patlist, subbed, poison, poisonEntry) char **patlist; char *subbed; char *poison; BOOL *poisonEntry; { register char *pat; register char *p; register char *u; register char subvalue; register char poisonvalue; register NEWSGROUP *ngp; register int i; while ((pat = *patlist++) != NULL) { subvalue = *pat != SUB_NEGATE && *pat != SUB_POISON; poisonvalue = *pat == SUB_POISON; if (!subvalue) pat++; if (!*pat) continue; /* See if pattern is a simple newsgroup name. If so, set the * right subbed element for that one group (if found); if not, * pattern-match against all the groups. */ for (p = pat; *p; p++) if (*p == '?' || *p == '*' || *p == '[') break; if (*p == '\0') { /* Simple string; look it up, set it. */ if ((ngp = NGfind(pat)) != NULL) { subbed[ngp - Groups] = subvalue; poison[ngp - Groups] = poisonvalue; } } else for (p = subbed, u = poison, ngp = Groups, i = nGroups; --i >= 0; ngp++, p++, u++) if (wildmat(ngp->Name, pat)) { *p = subvalue; *u = poisonvalue; } } } /* ** Parse an individual site entry. Subbed is used to build the subscription ** list. Since this routine is called once for each site, the caller ** allocates subbed once, and frees it after the last site has been parsed. ** If subbed is NULL, we don't update the SITE array, since we're just ** doing syntax checking. */ STRING SITEparseone(Entry, sp, subbed, poison) char *Entry; SITE *sp; char *subbed; char *poison; { static char BATCH[] = _PATH_BATCHDIR; register int i; register int j; register NEWSGROUP *ngp; register char *p; register char *u; char *f2; char *f3; char *f4; char **save; char **argv; BOOL JustModerated; BOOL JustUnmoderated; int isp; SITE *nsp; BUFFER b; b = sp->Buffer; *sp = SITEnull; sp->Buffer = b; sp->Master = NOSITE; sp->Funnel = NOSITE; sp->PoisonEntry = FALSE; sp->Process = -1; sp->Next = sp->Prev = NOSITE; sp->Entry = Entry; sp->FileFlags[0] = FEED_NAME; sp->FileFlags[1] = '\0'; /* Nip off the first field, the site name. */ if ((f2 = strchr(Entry, NF_FIELD_SEP)) == NULL) return "missing field 2"; *f2++ = '\0'; sp->Name = Entry; if ((p = strchr(sp->Name, NF_SUBFIELD_SEP)) != NULL) { /* Exclusions within the site field. */ *p++ = '\0'; if (*p) sp->Exclusions = CommaSplit(p); } sp->NameLength = strlen(sp->Name); /* Parse the second field, the subscriptions. */ if ((f3 = strchr(f2, NF_FIELD_SEP)) == NULL) return "missing field 3"; *f3++ = '\0'; if ((p = strchr(f2, NF_SUBFIELD_SEP)) != NULL) { /* Distributions within the subscription field. */ *p++ = '\0'; if (*p) sp->Distributions = CommaSplit(p); } if (f2) sp->Patterns = CommaSplit(f2); if (subbed) { /* Read the subscription patterns and set the bits. */ (void)memset((POINTER)subbed, SUB_DEFAULT, (SIZE_T)nGroups); (void)memset((POINTER)poison, SUB_DEFAULT, (SIZE_T)nGroups); if (ME.Patterns) SITEsetlist(ME.Patterns, subbed, poison, &ME.PoisonEntry); SITEsetlist(sp->Patterns, subbed, poison, &sp->PoisonEntry); } /* Get the third field, the flags. */ if ((f4 = strchr(f3, NF_FIELD_SEP)) == NULL) return "missing field 4"; *f4++ = '\0'; JustModerated = FALSE; JustUnmoderated = FALSE; sp->Type = FTfile; for (save = argv = CommaSplit(f3); (p = *argv++) != NULL; ) switch (*p) { default: return "unknown field 3 flag"; case '\0': break; case '<': if (*++p && CTYPE(isdigit, *p)) sp->MaxSize = atol(p); break; case '>': if (*++p && CTYPE(isdigit, *p)) sp->MinSize = atol(p); break; case 'A': while (*++p) switch (*p) { default: return "unknown A param in field 3"; case 'd': sp->DistRequired = TRUE; break; case 'p': sp->IgnorePath = TRUE; break; } break; case 'B': if (*++p && CTYPE(isdigit, *p)) { sp->StartWriting = atoi(p); if ((p = strchr(p, NF_SUBFIELD_SEP)) != NULL && *++p && CTYPE(isdigit, *p)) sp->StopWriting = atoi(p); } break; case 'F': if (*++p == '\0') return "missing file name for F param in field 3"; else if (*p == '/') sp->SpoolName = COPY(p); else { sp->SpoolName = NEW(char, STRLEN(BATCH) + 1 + strlen(p) + 1); FileGlue(sp->SpoolName, BATCH, '/', p); } break; case 'G': if (*++p && CTYPE(isdigit, *p)) sp->Groupcount = atoi(p); else sp->Groupcount = 1; break; case 'H': if (*++p && CTYPE(isdigit, *p)) sp->Hops = atoi(p); else sp->Hops = 1; break; case 'I': if (*++p && CTYPE(isdigit, *p)) sp->Flushpoint = atol(p); break; case 'N': while (*++p) switch (*p) { default: return "unknown N param in field 3"; case 'm': JustModerated = TRUE; break; case 'u': JustUnmoderated = TRUE; break; } break; case 'S': if (*++p && CTYPE(isdigit, *p)) sp->StartSpooling = atol(p); break; case 'T': switch (*++p) { default: return "unknown T param in field 3"; case 'c': sp->Type = FTchannel; break; case 'l': sp->Type = FTlogonly; break; case 'f': sp->Type = FTfile; break; case 'm': sp->Type = FTfunnel; break; case 'p': sp->Type = FTprogram; break; case 'x': sp->Type = FTexploder; break; } break; case 'W': for (i = 0; *++p && i < FEED_MAXFLAGS; ) { switch (*p) { default: return "unknown W param in field 3"; case FEED_FNLNAMES: /* Funnel feed names */ sp->FNLwantsnames = TRUE; break; case FEED_HEADERS: /* Article headers */ NeedHeaders = TRUE; break; case FEED_OVERVIEW: NeedOverview = TRUE; /* Overview data */ break; case FEED_BYTESIZE: /* Size in bytes */ case FEED_FULLNAME: /* Full filename */ case FEED_HDR_DISTRIB: /* Distribution header */ case FEED_HDR_NEWSGROUP: /* Newsgroup header */ case FEED_MESSAGEID: /* Message-ID */ case FEED_NAME: /* Filename */ case FEED_NEWSGROUP: /* Newsgroup */ case FEED_REPLIC: /* Replication data */ case FEED_SITE: /* Site that gave it */ case FEED_TIMERECEIVED: /* When received */ case FEED_TIMEPOSTED: /* When posted */ break; } sp->FileFlags[i++] = *p; } if (*p) return "too many W param values"; sp->FileFlags[i] = '\0'; break; } DISPOSE(save); if (sp->Flushpoint && sp->Type != FTfile) return "I param with non-file feed"; if (sp->Flushpoint == 0 && sp->Type == FTfile) sp->Flushpoint = SITE_BUFFER_SIZE; if (subbed) { /* Modify the subscription list based on the flags. */ if (JustModerated) for (p = subbed, ngp = Groups, i = nGroups; --i >= 0; ngp++, p++) if (ngp->Rest[0] != NF_FLAG_MODERATED) *p = FALSE; if (JustUnmoderated) for (p = subbed, ngp = Groups, i = nGroups; --i >= 0; ngp++, p++) if (ngp->Rest[0] == NF_FLAG_MODERATED) *p = FALSE; } /* Get the fourth field, the param. */ if (*f4 == '\0' && sp != &ME) { if (sp->Type != FTfile && sp->Type != FTlogonly) return "empty field 4"; sp->Param = NEW(char, STRLEN(BATCH) + 1 + sp->NameLength + 1); FileGlue(sp->Param, BATCH, '/', sp->Name); } else if (sp->Type == FTfile && *f4 != '/') { sp->Param = NEW(char, STRLEN(BATCH) + 1 + strlen(f4) + 1); FileGlue(sp->Param, BATCH, '/', f4); } else sp->Param = COPY(f4); if (sp->SpoolName == NULL) { sp->SpoolName = NEW(char, STRLEN(BATCH) + 1 + strlen(sp->Name) + 1); FileGlue(sp->SpoolName, BATCH, '/', sp->Name); } /* Make sure there is only one %s, and only one *. */ if (sp->Type == FTprogram) { f3 = NULL; for (f2 = sp->Param; *f2; f2 = p + 1) { p = strchr(f2, '%'); if (p == NULL) break; if (p[1] == '%') { p++; continue; } if (f3 != NULL) return "bad (extra) sprintf format for field 4"; f3 = p; while (*++p && *p != '*' && !CTYPE(isalpha, *p)) continue; if (*p != 's') return "bad sprintf format for field 4"; } if (sp->FNLwantsnames && ((p = strchr(sp->Param, '*')) == NULL || strchr(++p, '*') != NULL)) return "multiple or no *'s in field 4"; } /* Now tell the groups this site gets that they should feed this site. */ if (sp != &ME && subbed) { isp = sp - Sites; for (p = subbed, u = poison, ngp = Groups, i = nGroups; --i >= 0; ngp++) { if (*p++) { for (j = 0; j < ngp->nSites; j++) if (ngp->Sites[j] == NOSITE) { ngp->Sites[j] = isp; break; } if (j == ngp->nSites) ngp->Sites[ngp->nSites++] = isp; } if (*u++) { for (j = 0; j < ngp->nPoison; j++) if (ngp->Poison[j] == NOSITE) { ngp->Poison[j] = isp; break; } if (j == ngp->nPoison) ngp->Poison[ngp->nPoison++] = isp; } } } /* If this is a duplicate name, find the master. */ nsp = SITEfind(sp->Name); if (nsp == sp) nsp = SITEfindnext(sp->Name, nsp); if (nsp != NULL) { if (nsp->Master != NOSITE) nsp = &Sites[nsp->Master]; if (nsp != sp) { sp->Master = nsp - Sites; nsp->IsMaster = TRUE; } } return NULL; } /* ** Patch up the funnel references. */ BOOL SITEfunnelpatch() { register int i; register int length; register SITE *sp; SITE *funnel; BOOL result; /* Get worst-case length of all sitenames. */ for (length = 0, i = nSites, sp = Sites; --i >= 0; sp++) if (sp->Name != NULL) length += 1 + strlen(sp->Name); /* Loop over all funnel feeds. */ for (result = TRUE, i = nSites, sp = Sites; --i >= 0; sp++) { if (sp->Name == NULL || sp->Type != FTfunnel) continue; /* Find the entry they feed in to, give that entry a buffer. */ if (sp->Param == NULL) { syslog(L_FATAL, "%s funnel NULL", sp->Name); SITEfree(sp); result = FALSE; continue; } if ((funnel = SITEfind(sp->Param)) == NULL) { syslog(L_FATAL, "%s funnel_bad", sp->Name); SITEfree(sp); result = FALSE; continue; } if (funnel->Type == FTfunnel) { syslog(L_FATAL, "%s funnels to funnel %s", sp->Name, funnel->Name); SITEfree(sp); result = FALSE; continue; } if (funnel->FNLnames.Data == NULL) { funnel->FNLnames.Size = length; funnel->FNLnames.Data = NEW(char, length); } else if (funnel->FNLnames.Size != length) { funnel->FNLnames.Size = length; RENEW(funnel->FNLnames.Data, char, length); } sp->Funnel = funnel - Sites; } return result; } /* ** Read the entries in the newsfeeds file, and parse them one at a time. */ void SITEparsefile(StartSite) BOOL StartSite; { register int i; register char *p; char **strings; SITE *sp; char *subbed; char *poison; STRING error; int errors; /* Free old sites info. */ if (Sites) { for (i = nSites, sp = Sites; --i >= 0; sp++) { SITEflush(sp, FALSE); SITEfree(sp); } DISPOSE(Sites); SITEfree(&ME); } /* Count the number of sites. */ for (strings = SITEreadfile(FALSE), nSites = 0; strings[nSites]; nSites++) continue; Sites = NEW(SITE, nSites); for (sp = Sites, i = 0; i < nSites; i++, sp++) { sp->Name = NULL; sp->Buffer.Data = NULL; sp->Buffer.Size = sp->Buffer.Used = sp->Buffer.Left = 0 ; } /* Set up scratch subscription list. */ subbed = NEW(char, nGroups); poison = NEW(char, nGroups); ME.Prev = 0; /* Used as a flag to ensure exactly one ME entry */ for (sp = Sites, errors = 0, i = 0; i < nSites; i++) { p = strings[i]; if (p[0] == 'M' && p[1] == 'E' && ((p[2] == NF_FIELD_SEP) || (p[2] == NF_SUBFIELD_SEP))) { if (ME.Prev == NOSITE) { syslog(L_FATAL, "bad_newsfeeds. Must have exactly one ME entry"); errors++; } else if ((error = SITEparseone(p, &ME, subbed, poison)) != NULL) { syslog(L_FATAL, "%s bad_newsfeeds %s", MaxLength(p, p), error); errors++; } continue; } if ((error = SITEparseone(p, sp, subbed, poison)) != NULL) { syslog(L_FATAL, "%s bad_newsfeeds %s", MaxLength(p, p), error); errors++; continue; } if (StartSite && !SITEsetup(sp)) { syslog(L_FATAL, "%s cant setup %m", sp->Name); errors++; continue; } sp->Working = TRUE; sp++; } if (ME.Prev != NOSITE) { syslog(L_FATAL, "bad_newsfeeds. Must have exactly one ME entry"); errors++; } if (errors) { syslog(L_FATAL, "%s syntax_error %s", LogName, SITEfeedspath); JustCleanup(); exit(1); } /* Free our scratch array, set up the funnel links. */ nSites = sp - Sites; DISPOSE(subbed); DISPOSE(poison); DISPOSE(strings); if (!SITEfunnelpatch()) { JustCleanup(); exit(1); } } inn-1.7.2/innd/ng.c0100644000175100001440000002311306443103542012327 0ustar mdusers/* $Revision: 1.25 $ ** ** Routine for the in-core data structures for the active and newsfeeds ** files. */ #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" #include "mydir.h" /* ** Hash function taken from Chris Torek's hash package posted to ** comp.lang.c on 18-Oct-90 in <27038@mimsy.umd.edu>. Thanks, Chris. */ #define NGH_HASH(Name, p, j) \ for (p = Name, j = 0; *p; ) j = (j << 5) + j + *p++ /* ** Size of hash table. Change NGH_BUCKET if not a power of two. */ #define NGH_SIZE 2048 #define NGH_BUCKET(j) &NGHtable[j & (NGH_SIZE - 1)] /* ** Newsgroup hash entry, which is really a hash bucket -- pointers ** to all the groups with this hash code. */ typedef struct _NGHASH { int Size; int Used; NEWSGROUP **Groups; } NGHASH; STATIC BUFFER NGdirs; STATIC BUFFER NGnames; STATIC NGHASH NGHtable[NGH_SIZE]; STATIC int NGHbuckets; STATIC int NGHcount; /* ** Sorting predicate for qsort call in NGparsefile. Put newsgroups in ** rough order of their activity. Will be better if we write a "counts" ** file sometime. */ STATIC int NGcompare(p1, p2) CPOINTER p1; CPOINTER p2; { NEWSGROUP **ng1; NEWSGROUP **ng2; ng1 = CAST(NEWSGROUP**, p1); ng2 = CAST(NEWSGROUP**, p2); return ng1[0]->Last - ng2[0]->Last; } /* ** Convert a newsgroup name into a directory name. */ STATIC void NGdirname(p) register char *p; { for ( ; *p; p++) if (*p == '.') *p = '/'; } /* ** Parse a single line from the active file, filling in ngp. Be careful ** not to write NUL's into the in-core copy, since we're either mmap(2)'d, ** or we want to just blat it out to disk later. */ STATIC BOOL NGparseentry(ngp, p, end) register NEWSGROUP *ngp; register char *p; register char *end; { register char *q; register unsigned int j; register NGHASH *htp; register NEWSGROUP **ngpp; register int i; if ((q = strchr(p, ' ')) == NULL) return FALSE; i = q - p; ngp->NameLength = i; ngp->Name = &NGnames.Data[NGnames.Used]; (void)strncpy(ngp->Name, p, (SIZE_T)i); ngp->Name[i] = '\0'; NGnames.Used += i + 1; ngp->Dir = &NGdirs.Data[NGdirs.Used]; (void)strncpy(ngp->Dir, p, (SIZE_T)i); ngp->Dir[i] = '\0'; NGdirs.Used += i + 1; NGdirname(ngp->Dir); ngp->LastString = ++q; if ((q = strchr(q, ' ')) == NULL || q > end) return FALSE; ngp->Lastwidth = q - ngp->LastString; if ((q = strchr(q, ' ')) == NULL || q > end) return FALSE; if ((q = strchr(q + 1, ' ')) == NULL || q > end) return FALSE; ngp->Rest = ++q; /* We count on atoi() to stop at the space after the digits! */ ngp->Last = atol(ngp->LastString); ngp->nSites = 0; ngp->Sites = NEW(int, NGHcount); ngp->nPoison = 0; ngp->Poison = NEW(int, NGHcount); ngp->Alias = NULL; /* Find the right bucket for the group, make sure there is room. */ /* SUPPRESS 6 *//* Over/underflow from plus expression */ NGH_HASH(ngp->Name, p, j); htp = NGH_BUCKET(j); for (p = ngp->Name, ngpp = htp->Groups, i = htp->Used; --i >= 0; ngpp++) if (*p == ngpp[0]->Name[0] && EQ(p, ngpp[0]->Name)) { syslog(L_ERROR, "%s duplicate_group %s", LogName, p); return FALSE; } if (htp->Used >= htp->Size) { htp->Size += NGHbuckets; RENEW(htp->Groups, NEWSGROUP*, htp->Size); } htp->Groups[htp->Used++] = ngp; return TRUE; } /* ** Parse the active file, building the initial Groups global. */ void NGparsefile() { register char *p; register char *q; register int i; register BOOL SawMe; register NEWSGROUP *ngp; register NGHASH *htp; char **strings; char *active; char *end; /* If re-reading, remove anything we might have had. */ if (Groups) { for (i = nGroups, ngp = Groups; --i >= 0; ngp++) { DISPOSE(ngp->Sites); DISPOSE(ngp->Poison); } DISPOSE(Groups); DISPOSE(GroupPointers); DISPOSE(NGdirs.Data); DISPOSE(NGnames.Data); } /* Get active file and space for group entries. */ active = ICDreadactive(&end); for (p = active, i = 0; p < end && (p = strchr(p, '\n')) != NULL; p++, i++) continue; if ((nGroups = i) == 0) { syslog(L_FATAL, "%s empty active file", LogName); exit(1); } Groups = NEW(NEWSGROUP, nGroups); GroupPointers = NEW(NEWSGROUP*, nGroups); /* Get space to hold copies of the names and the directory names. * This might take more space than individually allocating each * element, but it is definitely easier on the system. */ i = end - active; NGdirs.Size = i; NGdirs.Data = NEW(char, NGdirs.Size + 1); NGdirs.Used = 0; NGnames.Size = i; NGnames.Data = NEW(char, NGnames.Size + 1); NGnames.Used = 0; /* Set up the default hash buckets. */ NGHbuckets = nGroups / NGH_SIZE; if (NGHbuckets == 0) NGHbuckets = 1; if (NGHtable[0].Groups) for (i = NGH_SIZE, htp = NGHtable; --i >= 0; htp++) htp->Used = 0; else for (i = NGH_SIZE, htp = NGHtable; --i >= 0; htp++) { htp->Size = NGHbuckets; htp->Groups = NEW(NEWSGROUP*, htp->Size); htp->Used = 0; } /* Count the number of sites. */ SawMe = FALSE; for (strings = SITEreadfile(TRUE), i = 0; (p = strings[i]) != NULL; i++) if (*p == 'M' && *++p == 'E' && *++p == ':') SawMe = TRUE; if (i == 0 || (i == 1 && SawMe)) { syslog(L_ERROR, "%s bad_newsfeeds no feeding sites", LogName); NGHcount = 1; } else NGHcount = i; /* Loop over all lines in the active file, filling in the fields of * the Groups array. */ for (p = active, ngp = Groups, i = nGroups; --i >= 0; ngp++, p = q + 1) { ngp->Start = p - active; if ((q = strchr(p, '\n')) == NULL || !NGparseentry(ngp, p, q)) { syslog(L_FATAL, "%s bad_active %s...", LogName, MaxLength(p, q)); exit(1); } } /* Sort each bucket. */ for (i = NGH_SIZE, htp = NGHtable; --i >= 0; htp++) if (htp->Used > 1) qsort((POINTER)htp->Groups, (SIZE_T)htp->Used, sizeof htp->Groups[0], NGcompare); /* Chase down any alias flags. */ for (ngp = Groups, i = nGroups; --i >= 0; ngp++) if (ngp->Rest[0] == NF_FLAG_ALIAS) { ngp->Alias = ngp; if ((p = strchr(ngp->Alias->Rest, '\n')) != NULL) *p = '\0'; ngp->Alias = NGfind(&ngp->Alias->Rest[1]); if (p) *p = '\n'; if (ngp->Alias != NULL && ngp->Alias->Rest[0] == NF_FLAG_ALIAS) syslog(L_NOTICE, "%s alias_error %s too many levels", LogName, ngp->Name); } } /* ** Hash a newsgroup and see if we get it. */ NEWSGROUP * NGfind(Name) char *Name; { register char *p; register int i; register unsigned int j; register NEWSGROUP **ngp; char c; NGHASH *htp; /* SUPPRESS 6 *//* Over/underflow from plus expression */ NGH_HASH(Name, p, j); htp = NGH_BUCKET(j); for (c = *Name, ngp = htp->Groups, i = htp->Used; --i >= 0; ngp++) if (c == ngp[0]->Name[0] && EQ(Name, ngp[0]->Name)) return ngp[0]; return NULL; } /* ** Split a newsgroups header line into the groups we get. Return a ** point to static memory and clobber the argument along the way. */ char ** NGsplit(p) register char *p; { static char **groups; static int oldlength; register char **gp; register int i; /* Get an array of character pointers. */ i = strlen(p); if (groups == NULL) { groups = NEW(char*, i + 1); oldlength = i; } else if (oldlength < i) { RENEW(groups, char*, i + 1); oldlength = i; } /* Loop over text. */ for (gp = groups; *p; *p++ = '\0') { /* Skip leading separators. */ for (; NG_ISSEP(*p); p++) continue; if (*p == '\0') break; /* Mark the start of the newsgroup, move to the end of it. */ for (*gp++ = p; *p && !NG_ISSEP(*p); p++) continue; if (*p == '\0') break; } *gp = NULL; return groups; } /* ** Renumber a group. */ BOOL NGrenumber(ngp) NEWSGROUP *ngp; { static char NORENUMBER[] = "%s cant renumber %s %s too wide"; static char RENUMBER[] = "%s renumber %s %s from %ld to %ld"; register DIR *dp; register DIRENTRY *ep; register char *f2; register char *p; char *f3; char *f4; char *start; long l; long himark; long lomark; char *dummy; /* Get a valid offset into the active file. */ if (ICDneedsetup) { syslog(L_ERROR, "%s unsynched must reload before renumber", LogName); return FALSE; } start = ICDreadactive(&dummy) + ngp->Start; /* Check the file format. */ if ((f2 = strchr(start, ' ')) == NULL || (f3 = strchr(++f2, ' ')) == NULL || (f4 = strchr(++f3, ' ')) == NULL) { syslog(L_ERROR, "%s bad_format active %s", LogName, MaxLength(start, start)); return FALSE; } himark = atol(f2); lomark = himark + 1; /* Scan the directory. */ if ((dp = opendir(ngp->Dir)) != NULL) { while ((ep = readdir(dp)) != NULL) { p = ep->d_name; if (!CTYPE(isdigit, p[0]) || strspn(p, "0123456789") != strlen(p) || (l = atol(p)) == 0) continue; if (l < lomark) lomark = l; if (l > himark) himark = l; } (void)closedir(dp); } l = atol(f2); if (himark != l) { syslog(L_NOTICE, RENUMBER, LogName, ngp->Name, "hi", l, himark); if (!FormatLong(f2, himark, f3 - f2 - 1)) { syslog(L_ERROR, NORENUMBER, LogName, ngp->Name, "hi"); return FALSE; } ngp->Last = himark; ICDactivedirty++; } l = atol(f3); if (lomark != l) { if (lomark < l) syslog(L_NOTICE, RENUMBER, LogName, ngp->Name, "lo", l, lomark); if (!FormatLong(f3, lomark, f4 - f3)) { syslog(L_ERROR, NORENUMBER, LogName, ngp->Name, "lo"); return FALSE; } ICDactivedirty++; } return TRUE; } inn-1.7.2/innd/icd.c0100644000175100001440000002126706443103542012472 0ustar mdusers/* $Revision: 1.33 $ ** ** Routines to read and write the active file. */ #include #include #include "configdata.h" #include "clibrary.h" #include "innd.h" #if defined(ACT_MMAP) #include #endif /* defined(ACT_MMAP) */ #include typedef struct iovec IOVEC; STATIC char ICDactpath[] = _PATH_ACTIVE; STATIC char *ICDactpointer; STATIC int ICDactfd; STATIC int ICDactsize; /* ** Set and unset (or copy) IOVEC elements. We make copies to ** avoid problems with mmap. */ #if defined(ACT_MMAP) #define ICDiovset(iovp, base, len) \ do { \ (iovp)->iov_len = len; \ (iovp)->iov_base = NEW(char, (iovp)->iov_len); \ (void)memcpy((POINTER)(iovp)->iov_base, (POINTER)base, \ (SIZE_T)(iovp)->iov_len); \ } while (JUSTONCE) #define ICDiovrelease(iovp) DISPOSE((iovp)->iov_base) #if defined(MAP_FILE) #define MAP__ARG (MAP_FILE | MAP_SHARED) #else #define MAP__ARG (MAP_SHARED) #endif /* defined(MAP_FILE) */ #else #define ICDiovset(iovp, base, len) \ (iovp)->iov_base = base, (iovp)->iov_len = len #define ICDiovrelease(iovp) /* NULL */ #endif /* defined(ACT_MMAP) */ /* ** Close the active file, releasing its resources. */ STATIC void ICDcloseactive() { if (ICDactpointer) { #if defined(ACT_MMAP) if (munmap(ICDactpointer, ICDactsize) < 0) syslog(L_ERROR, "%s cant munmap %s %m", LogName, ICDactpath); #else DISPOSE(ICDactpointer); #endif /* defined(ACT_MMAP) */ ICDactpointer = NULL; if (close(ICDactfd) < 0) { syslog(L_FATAL, "%s cant close %s %m", LogName, ICDactpath); exit(1); } } } /* ** Set up the hash and in-core tables. */ void ICDsetup(StartSites) BOOL StartSites; { if (ICDneedsetup == TRUE) { ICDneedsetup = FALSE; } else { ICDcloseactive(); NGparsefile(); } if (NGfind("control") == NULL || NGfind("junk") == NULL) { syslog(L_FATAL, "%s internal no control and/or junk group", LogName); exit(1); } #if defined(DO_MERGE_TO_GROUPS) if (NGfind("to") == NULL) { syslog(L_FATAL, "%s internal no to group", LogName); exit(1); } #endif /* defined(DO_MERGE_TO_GROUPS) */ SITEparsefile(StartSites); } /* ** Write out all in-core data. */ void ICDwrite() { HISsync(); if (ICDactivedirty) { ICDwriteactive(); ICDactivedirty = 0; } /* Flush log and error log. */ if (fflush(Log) == EOF) syslog(L_ERROR, "%s cant fflush log %m", LogName); if (fflush(Errlog) == EOF) syslog(L_ERROR, "%s cant fflush errlog %m", LogName); } /* ** Close things down. */ void ICDclose() { ICDwrite(); ICDcloseactive(); } /* ** Scan the active file, and renumber the min/max counts. */ BOOL ICDrenumberactive() { register int i; register NEWSGROUP *ngp; for (i = nGroups, ngp = Groups; --i >= 0; ngp++) if (!NGrenumber(ngp)) return FALSE; if (i < 0) ICDwrite(); return TRUE; } /* ** Use writev() to replace the active file. */ STATIC BOOL ICDwritevactive(vp, vpcount) IOVEC *vp; int vpcount; { static char BACKUP[] = _PATH_OLDACTIVE; static char WHEN[] = "backup active"; register int fd; int oerrno; /* Write the current file to a backup. */ if (unlink(BACKUP) < 0 && errno != ENOENT) { oerrno = errno; syslog(L_ERROR, "%s cant unlink %s %m", LogName, BACKUP); IOError(WHEN, oerrno); } if ((fd = open(BACKUP, O_WRONLY | O_TRUNC | O_CREAT, 0664)) < 0) { oerrno = errno; syslog(L_ERROR, "%s cant open %s %m", LogName, BACKUP); IOError(WHEN, oerrno); } else if (xwrite(fd, ICDactpointer, ICDactsize) < 0) { oerrno = errno; syslog(L_ERROR, "%s cant write %s %m", LogName, BACKUP); IOError(WHEN, oerrno); (void)close(fd); } else if (close(fd) < 0) { oerrno = errno; syslog(L_ERROR, "%s cant close %s %m", LogName, BACKUP); IOError(WHEN, oerrno); } /* Open the active file. */ fd = open(ICDactpath, O_WRONLY | O_TRUNC | O_CREAT, ARTFILE_MODE); if (fd < 0) { oerrno = errno; syslog(L_ERROR, "%s cant open %s %m", LogName, ICDactpath); IOError(WHEN, oerrno); return FALSE; } /* Write it. */ if (xwritev(fd, vp, vpcount) < 0) { oerrno = errno; syslog(L_ERROR, "%s cant write %s %m", LogName, ICDactpath); IOError(WHEN, oerrno); (void)close(fd); return FALSE; } /* Close it. */ (void)close(fd); if (AmRoot) xchown(ICDactpath); /* Invalidate in-core pointers. */ ICDcloseactive(); /* Restore in-core pointers. */ if (Mode != OMrunning) { ICDneedsetup = TRUE; /* Force the active file into memory. */ NGparsefile(); } else ICDsetup(TRUE); return TRUE; } /* ** Change the flag on a newsgroup. Fairly easy. */ BOOL ICDchangegroup(ngp, Rest) NEWSGROUP *ngp; char *Rest; { static char NEWLINE[] = "\n"; register int i; IOVEC iov[3]; BOOL ret; /* Set up the scatter/gather vectors. */ ICDiovset(&iov[0], ICDactpointer, ngp->Rest - ICDactpointer); ICDiovset(&iov[1], Rest, strlen(Rest)); if (++ngp < &Groups[nGroups]) { /* Not the last group, keep the \n from the next line. */ i = ngp->Start; ICDiovset(&iov[2], &ICDactpointer[i - 1], ICDactsize - i + 1); } else { /* Last group -- append a newline. */ ICDiovset(&iov[2], NEWLINE, STRLEN(NEWLINE)); } ret = ICDwritevactive(iov, 3); ICDiovrelease(&iov[0]); ICDiovrelease(&iov[1]); ICDiovrelease(&iov[2]); return ret; } /* ** Add a newsgroup. Append a line to the end of the active file and reload. */ BOOL ICDnewgroup(Name, Rest) char *Name; char *Rest; { char buff[SMBUF]; IOVEC iov[2]; BOOL ret; /* Set up the scatter/gather vectors. */ if (strlen(Name) + strlen(Rest) > (SIZE_T)(SMBUF - 24)) { syslog(L_ERROR, "%s too_long %s", LogName, MaxLength(Name, Name)); return FALSE; } (void)sprintf(buff, "%s 0000000000 0000000001 %s\n", Name, Rest); ICDiovset(&iov[0], ICDactpointer, ICDactsize); ICDiovset(&iov[1], buff, strlen(buff)); ret = ICDwritevactive(iov, 2); ICDiovrelease(&iov[0]); ICDiovrelease(&iov[1]); return ret; } /* ** Remove a newsgroup. Splice the line out of the active file and reload. */ BOOL ICDrmgroup(ngp) NEWSGROUP *ngp; { IOVEC iov[2]; int i; BOOL ret; /* If this is the first group in the file, write everything after. */ if (ngp == &Groups[0]) { i = ngp[1].Start; ICDiovset(&iov[0], &ICDactpointer[i], ICDactsize - i); ret = ICDwritevactive(iov, 1); ICDiovrelease(&iov[0]); return ret; } /* Write everything up to this group. */ ICDiovset(&iov[0], ICDactpointer, ngp->Start); /* If this is the last group, that's all we have to write. */ if (ngp == &Groups[nGroups - 1]) { ret = ICDwritevactive(iov, 1); ICDiovrelease(&iov[0]); return ret; } /* Write everything after this group. */ i = ngp[1].Start; ICDiovset(&iov[1], &ICDactpointer[i], ICDactsize - i); ret = ICDwritevactive(iov, 2); ICDiovrelease(&iov[0]); ICDiovrelease(&iov[1]); return ret; } /* ** Open the active file and "map" it into memory. */ char * ICDreadactive(endp) char **endp; { struct stat Sb; if (ICDactpointer) { *endp = ICDactpointer + ICDactsize; return ICDactpointer; } if ((ICDactfd = open(ICDactpath, O_RDWR)) < 0) { syslog(L_FATAL, "%s cant open %s %m", LogName, ICDactpath); exit(1); } CloseOnExec(ICDactfd, TRUE); #if defined(ACT_MMAP) if (fstat(ICDactfd, &Sb) < 0) { syslog(L_FATAL, "%s cant fstat %d %s %m", LogName, ICDactfd, ICDactpath); exit(1); } ICDactsize = Sb.st_size; ICDactpointer = mmap((caddr_t)0, ICDactsize, PROT_READ|PROT_WRITE, MAP__ARG, ICDactfd, (OFFSET_T)0); if (ICDactpointer == (char *)-1) { syslog(L_FATAL, "%s cant mmap %d %s %m", LogName, ICDactfd, ICDactpath); exit(1); } #else if ((ICDactpointer = ReadInDescriptor(ICDactfd, &Sb)) == NULL) { syslog(L_FATAL, "%s cant read %s %m", LogName, ICDactpath); exit(1); } ICDactsize = Sb.st_size; #endif /* defined(ACT_MMAP) */ *endp = ICDactpointer + ICDactsize; return ICDactpointer; } /* ** Write the active file out. */ void ICDwriteactive() { #if defined(ACT_MMAP) #if defined (DO_MMAP_SYNC) #if defined (DO_MSYNC_3_ARG) if (msync(ICDactpointer, ICDactsize, MS_ASYNC) < 0) { syslog(L_FATAL, "%s msync failed %s %m", LogName, ICDactpath); exit(1); } #else if (msync(ICDactpointer, 0) < 0) { syslog(L_FATAL, "%s msync failed %s %m", LogName, ICDactpath); exit(1); } #endif #endif #else if (lseek(ICDactfd, 0L, SEEK_SET) == -1) { syslog(L_FATAL, "%s cant rewind %s %m", LogName, ICDactpath); exit(1); } if (xwrite(ICDactfd, ICDactpointer, ICDactsize) < 0) { syslog(L_FATAL, "%s cant write %s %m", LogName, ICDactpath); exit(1); } #endif /* defined(ACT_MMAP) */ } inn-1.7.2/sedf.sun0100644000175100001440000000041306443103542012275 0ustar mdusers/## Filter noise out of Sun, BSD, v7 lint output./d /## $Revision: 1.7 $/d /^[a-z32.]*.c:$/d /Lint pass2:/d /## My specific fluff I don't want to see/d /yynewstate unused in function date_parse/d /errno used( .* ), but not defined/d /dbz.3.* Unmatched \.SM/d /./p inn-1.7.2/sample-configs/0040755000175100001440000000000006443103542013541 5ustar mdusersinn-1.7.2/sample-configs/config.data-linux-2.0.180100644000175100001440000010524106443103542017522 0ustar mdusers## Sample config.data for linux 2.0.18 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-irix-5.20100644000175100001440000010523506443103542017117 0ustar mdusers## Sample config.data for IRIX 5.2 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-hpux-9.050100644000175100001440000010523606443103542017220 0ustar mdusers## Sample config.data for HPUX 9.05 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-aix-4.1.40100644000175100001440000010523606443103542017066 0ustar mdusers## Sample config.data for AIX 4.1.4 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-irix-6.20100644000175100001440000010523006443103542017113 0ustar mdusers## Sample config for Irix 6.2 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-newsos-4.2.10100644000175100001440000010525406443103542017621 0ustar mdusers## Sample config.data file for Sony NEWS-OS 4.2.1 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-netbsd-1.20100644000175100001440000010523706443103542017421 0ustar mdusers## Sample config.data for NetBSD 1.2 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-dynixptx2.10100644000175100001440000010524206443103542017750 0ustar mdusers## Sample config.data for dynix ptx 2.1 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-ux48000100644000175100001440000010524006443103542016606 0ustar mdusers## Sample config.data for UX4800 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC cc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DONT ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lelf -lsocket -lnsl ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sysv ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB echo ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR int ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DONT ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DONT ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DONT ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE FCNTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE TIMES ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE MMAP ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DO ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DO ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/ucblib/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /sbin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/local/bin/gzip ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .gz ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/local/bin/perl ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/local/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /usr/ucb/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 3 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-irix-5.30100644000175100001440000010524006443103542017114 0ustar mdusers## Sample config.data for IRIX 5.2 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC cc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lmalloc -lmld ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB echo ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DONT ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DONT ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK fork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE FCNTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE MMAP ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR void * ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/lib/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bsd/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-aux3.10100644000175100001440000010523406443103542016660 0ustar mdusers## Sample config.data for AUX 3.1 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-solaris2.3-40100644000175100001440000010527006443103542017701 0ustar mdusers## Smaple config.data for Solaris 2.3 and 2.4 (and maybe 2.5) ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-OSF3.00100644000175100001440000010523606443103542016513 0ustar mdusers## Sample config.data for OSF/1 3.0 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-next4.10100644000175100001440000010523506443103542017043 0ustar mdusers## Sample config.data for Next 3.2 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-hpux-9.070100644000175100001440000010523606443103542017222 0ustar mdusers## Sample config.data for HPUX 9.07 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-FreeBSD-2.00100644000175100001440000010524006443103542017345 0ustar mdusers## Sample config.data for FreeBSD 2.x ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-next3.20100644000175100001440000010523506443103542017043 0ustar mdusers## Sample config.data for Next 3.2 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-ultrix4.30100644000175100001440000010521706443103542017416 0ustar mdusers## Sample config.data for Ultrix 4.3 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -O ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -p ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lresolv -l44bsd ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -u -x $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sysv ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T unsigned int ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T int #### =()@>()= GID_T int ## Type of a pid, for use in kill(2). #### =()@>()= PID_T int ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR int ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FLOCK ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DONT ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DONT ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DONT ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DO ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DO ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETDTAB ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL int ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL int ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/lib/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/ucb/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/local/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-sco-5.00100644000175100001440000010524106443103542016723 0ustar mdusers## Sampel config for SCO OpenServer 5 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-OSF1.3a0100644000175100001440000010523706443103542016656 0ustar mdusers## Sample config.data for OSF/1 1.3a ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-uxpds0100644000175100001440000010524506443103542017006 0ustar mdusers## Sample config.data for UXPDS ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC /usr/ccs/bin/cc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -O ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -p ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS -g ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lnsl -lsocket -lelf ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE SYSV ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sysv ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB echo ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR int ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE LOCKF ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DONT ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DONT ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE FCNTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE TIMES ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE SYSCONF ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/ucblib/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/local/bin/perl ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/README0100644000175100001440000000074006443103542014417 0ustar mdusersINN is developed on BSD/OS 2.1. The config.dist file in the config directory is ready to go for that system, so there is no sample for bsd/os in this directory. You may want to tweak things (like whether to use the Perl hooks), though. The sample config.data files in here have been donated by many people. I have made some changes to make things (like installed paths) consistent across all samples. If anything in here is broken, please le me know James Brister inn-1.7.2/sample-configs/config.data-solaris2.50100644000175100001440000010532606443103542017544 0ustar mdusers## Sample config file for solaris 2.5 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include -DSUNOS5 -DPOLL_BUG ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) -DMMAP ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS -g ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lnsl -lsocket -lelf -lresolv ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR long ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE LOCKF ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DONT ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DONT ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE FCNTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE TIMES ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE SYSCONF ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT 1024 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE MMAP ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/lib/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/local/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /usr/ucb/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 3 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-DU4.00100644000175100001440000010525306443103542016374 0ustar mdusers## Sample config.data for Digital Unix 4.0. ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil -ldb ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-sco-3.2.20100644000175100001440000010523706443103542017070 0ustar mdusers# sample config.dayta for SCO 3.2.2 ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FCNTL ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/sample-configs/config.data-sunos-4.1.x0100644000175100001440000010527606443103542017564 0ustar mdusers## Sample config.data for SunOS 4.1.x ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lresolv ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER char ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR int ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FLOCK ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DONT ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DO ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DONT ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL int ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC strerror.c memmove.c #### =()@>()= MISSING_OBJ strerror.o memmove.o ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE MMAP ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/lib/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/nawk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/news/spool/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 3 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/config/0040755000175100001440000000000006443103542012077 5ustar mdusersinn-1.7.2/config/subst.c0100644000175100001440000002735706443103542013416 0ustar mdusers/* $Revision: 1.16 $ ** ** A C version of Henry Spencer's "subst" script. */ #include #include #include #define LINESIZE 1024 #define FNAMESIZE 1024 #define PARAMSIZE 128 #define WHITE(c) ((c) == ' ' || (c) == '\t') /* ** AFS doesn't support hard links, so enable this #define. #define USE_RENAME */ /* ** If you don't have getopt in your C library, enable this #define. #define NEED_GETOPT */ typedef struct _PAIR { char *Name; int Length; char *Value; } PAIR; static char *argv0; extern char *optarg; extern int optind; extern void exit(); extern char *malloc(); extern char *strcpy(); /* ** Local implementations of common C library functions. */ /* ** Return string represtation of errno. */ static char * xstrerror() { extern int sys_nerr; #if !defined(__FreeBSD__) && !defined(__NetBSD__) extern char *sys_errlist[]; #endif extern int errno; static char buff[30]; if (errno >= 0 && errno < sys_nerr) return sys_errlist[errno]; (void)sprintf(buff, "Error code %d\n", errno); return buff; } /* ** Return the first occurrence of 'c' in 'p' or NULL if not there. */ static char * xstrchr(p, c) register char *p; register char c; { for ( ; *p; p++) if (*p == c) return p; return NULL; } /* ** Return the last occurrence of 'c' in 'p' or NULL if not there. */ static char * xstrrchr(p, c) register char *p; register char c; { register char *ret; for (ret = NULL; *p; p++) if (*p == c) ret = p; return ret; } /* ** Copy a string to malloc'd memory or exit. */ static char * xstrdup(p) char *p; { char *new; if ((new = malloc(strlen(p) + 1)) == NULL) { (void)fprintf(stderr, "%s: Can't copy \"%s\", %s\n", argv0, p, xstrerror()); exit(1); } return strcpy(new, p); } #if defined(NEED_GETOPT) #define TYPE int #define ERR(s, c) \ if (opterr) { \ char buff[2]; \ buff[0] = c; buff[1] = '\n'; \ (void)write(2, av[0], (TYPE)strlen(av[0])); \ (void)write(2, s, (TYPE)strlen(s)); \ (void)write(2, buff, 2); \ } int opterr = 1; int optind = 1; int optopt; char *optarg; /* ** Return options and their values from the command line. ** This comes from the AT&T public-domain getopt published in mod.sources ** (i.e., comp.sources.unix before the great Usenet renaming). */ int getopt(ac, av, opts) int ac; char *av[]; char *opts; { static int i = 1; char *p; /* Move to next value from argv? */ if (i == 1) { if (optind >= ac || av[optind][0] != '-' || av[optind][1] == '\0') return EOF; if (strcmp(av[optind], "--") == 0) { optind++; return EOF; } } /* Get next option character. */ if ((optopt = av[optind][i]) == ':' || (p = IDX(opts, optopt)) == NULL) { ERR(": illegal option -- ", optopt); if (av[optind][++i] == '\0') { optind++; i = 1; } return '?'; } /* Snarf argument? */ if (*++p == ':') { if (av[optind][i + 1] != '\0') optarg = &av[optind++][i + 1]; else { if (++optind >= ac) { ERR(": option requires an argument -- ", optopt); i = 1; return '?'; } optarg = av[optind++]; } i = 1; } else { if (av[optind][++i] == '\0') { i = 1; optind++; } optarg = NULL; } return optopt; } #endif /* defined(NEED_GETOPT) */ /* ** Simulate "mv $from $to" -- return no useful status. We know that ** the $from and $to are on the same filesystem. */ static void mv(from, to) char *from; char *to; { if (unlink(to) < 0 && errno != ENOENT) { (void)fprintf(stderr, "%s: Can't unlink %s, %s\n", argv0, to, xstrerror()); return; } #if defined(USE_RENAME) if (rename(from, to) < 0) { (void)fprintf(stderr, "%s: Can't rename %s to %s, %s\n", argv0, from, to, xstrerror()); return; } #else if (link(from, to) < 0) { (void)fprintf(stderr, "%s: Can't link %s to %s, %s\n", argv0, from, to, xstrerror()); return; } if (unlink(from) < 0) (void)fprintf(stderr, "%s: Can't unlink %s, %s\n", argv0, from, xstrerror()); #endif /* defined(USE_RENAME) */ } /* ** Simulate "cmp -s $n1 $n2" -- return 0 if files are the same. */ static int cmp(n1, n2) char *n1; char *n2; { FILE *f1; FILE *f2; int c; if ((f1 = fopen(n1, "r")) == NULL) return 1; if ((f2 = fopen(n2, "r")) == NULL) { (void)fclose(f1); return 1; } while ((c = getc(f1)) != EOF) if (getc(f2) != c) { (void)fclose(f1); (void)fclose(f2); return 1; } if (getc(f2) != EOF) { (void)fclose(f1); (void)fclose(f2); return 1; } (void)fclose(f1); (void)fclose(f2); return 0; } /* ** If line does not look like a template, return NULL, otherwise modify ** it to delete the trailing gunk and return the start of the template. */ static char * istemplate(line) char *line; { char *p; char *start; /* Find "=()<" and remember where it starts. */ for (p = line; (p = xstrchr(p, '=')) != NULL; p++) if (p[1] == '(' && p[2] == ')' && p[3] == '<') break; if (p == NULL) return NULL; start = &p[4]; /* Now find ">()=" and nip it off. */ for (p = start; (p = xstrchr(p, '>')) != NULL; p++) if (p[1] == '(' && p[2] == ')' && p[3] == '=') { *p++ = '\n'; *p = '\0'; return start; } return NULL; } /* ** Splice three strings together, returning an allocated copy. */ static char * splice(s1, s2, s3) char *s1; char *s2; char *s3; { int i; char *new; i = strlen(s1) + strlen(s2) + strlen(s3) + 1; if ((new = malloc(i)) == NULL) { (void)fprintf(stderr, "%s: Can't splice %s+%s+%s, %s\n", argv0, s1, s2, s3, xstrerror()); exit(1); } (void)sprintf(new, "%s%s%s", s1, s2, s3); return new; } /* ** Substitute all found patterns in the line and print it. Using the goto ** makes the code more clear than using do/while. */ static int doline(f, out, line, tp, end) char *f; FILE *out; char *line; PAIR *tp; PAIR *end; { char *p; char *new; char save; int count; for (count = 0, line = xstrdup(line); tp < end; tp++) { Again: for (p = line; (p = xstrchr(p, tp->Name[0])) != NULL; p++) if (strncmp(p, tp->Name, tp->Length) == 0) { save = *p; *p = '\0'; count++; new = splice(line, tp->Value, p + tp->Length); *p = save; if (strcmp(new, line) == 0) { (void)fprintf(stderr, "%s: subst loop in %s:\n\t%s\n", argv0, f, line); free(new); break; } free(line); line = new; goto Again; } } if (count > 0 && fputs(line, out) == EOF) { (void)fprintf(stderr, "%s: can't write %s, %s\n", argv0, f, xstrerror()); free(line); return -1; } free(line); return count; } /* ** Process one file, carefully substituting it in place. */ static void Process(f, Table, end) char *f; PAIR *Table; PAIR *end; { char new[FNAMESIZE]; char old[FNAMESIZE]; char line[LINESIZE]; int bad; int i; int count; FILE *in; FILE *out; FILE *temp; char *p; /* First, figure out temporary names. */ if ((p = xstrrchr(f, '/')) == NULL) { (void)strcpy(new, "substtmp.new"); (void)strcpy(old, "substtmp.old"); } else { *p = '\0'; (void)sprintf(new, "%s/substtmp.new", f); (void)sprintf(old, "%s/substtmp.old", f); *p = '/'; } /* Test existences. */ if ((in = fopen(f, "r")) == NULL) { (void)fprintf(stderr, "%s: can't open %s, %s\n", argv0, f, xstrerror()); return; } if ((temp = fopen(new, "r")) != NULL) { (void)fclose(in); (void)fprintf(stderr, "%s: %s exists, cannot proceed\n", argv0, new); exit(1); } if ((temp = fopen(old, "r")) != NULL) { (void)fprintf(stderr, "%s: %s exists, cannot proceed\n", argv0, old); exit(1); } temp = fopen(old, "w"); out = fopen(new, "w"); if (out == NULL || temp == NULL) { if (temp != NULL) (void)fclose(temp); (void)unlink(old); if (out != NULL) (void)fclose(out); (void)unlink(new); (void)fprintf(stderr, "%s: cannot create temporaries %s and %s\n", argv0, old, new); exit(1); } (void)fclose(temp); /* Generate the new version. */ for (i = 1, bad = 0; fgets(line, sizeof line, in) != NULL; i++) { if ((p = xstrchr(line, '\n')) == NULL) { (void)fprintf(stderr, "%s: Line %d of %s is too long (or doesn't end with a newline)\n", argv0, i, f); bad++; break; } (void)fputs(line, out); if ((p = istemplate(line)) != NULL) { if ((count = doline(f, out, p, Table, end)) < 0) { bad++; break; } if (count > 0) { (void)fgets(line, sizeof line, in); i++; } else (void)fprintf(stderr, "%s: %s:%d unknown parameter or bad line:\n\t%s", argv0, f, i, p); } } (void)fclose(in); if (fflush(out) == EOF || fclose(out) == EOF) { (void)fprintf(stderr, "%s: can't close %s, %s\n", argv0, f, xstrerror()); bad++; } if (bad || cmp(new, f) == 0) { (void)unlink(old); (void)unlink(new); (void)printf("%s: unchanged\n", f); return; } /* Substitute new for old the only safe way -- ignore signals. */ (void)signal(SIGHUP, SIG_IGN); (void)signal(SIGINT, SIG_IGN); (void)signal(SIGTERM, SIG_IGN); mv(f, old); mv(new, f); (void)signal(SIGHUP, SIG_DFL); (void)signal(SIGINT, SIG_DFL); (void)signal(SIGTERM, SIG_DFL); (void)printf("%s: updated\n", f); (void)unlink(old); } /* ** Print usage message and exit. */ static void Usage() { (void)fprintf(stderr, "Usage: %s -f file victims...\n", argv0); exit(1); } int main(ac, av) int ac; char *av[]; { static char NIL[] = ""; char *ctlfile; char *p; char *dest; FILE *F; int i; char buff[LINESIZE]; char name[PARAMSIZE]; PAIR *Table; PAIR *tp; /* Set defaults. */ ctlfile = NULL; argv0 = av[0]; /* Parse JCL. */ while ((i = getopt(ac, av, "e:f:")) != EOF) switch (i) { default: Usage(); /* NOTREACHED */ case 'e': break; case 'f': if (ctlfile != NULL) Usage(); ctlfile = optarg; break; } ac -= optind; av += optind; /* Open control file, count lines, allocate table. */ if ((F = fopen(ctlfile, "r")) == NULL) { (void)fprintf(stderr, "%s: Can't open %s to read it, %s\n", argv0, ctlfile, xstrerror()); exit(1); } for (i = 0; fgets(buff, sizeof buff, F) != NULL; i++) continue; if ((Table = (PAIR *)malloc(i * sizeof *Table)) == NULL) { (void)fprintf(stderr, "%s: Can't allocate %d table elements, %s\n", argv0, i, xstrerror()); exit(1); } /* Now parse the table. */ (void)fseek(F, 0L, 0); for (i = 1, tp = Table; fgets(buff, sizeof buff, F) != NULL; i++) { if ((p = xstrchr(buff, '\n')) == NULL) { (void)fprintf(stderr, "%s: Line %d of %s is too long\n", argv0, i, ctlfile); exit(1); } *p = '\0'; /* Skip empty lines, comment lines, and all-blank lines. */ if (buff[0] == '\0' || buff[0] == '#') continue; for (p = buff; WHITE(*p); p++) continue; if (*p == '\0') continue; /* Find end of first word, copy second word (or empty string) */ for (p = buff; *p && !WHITE(*p); p++) continue; if (*p == '\0') tp->Value = NIL; else { for (*p++ = '\0'; *p && WHITE(*p); p++) continue; tp->Value = xstrdup(p); /* Turn things like \& into &. */ for (p = dest = tp->Value; *p; p++) *dest++ = (*p == '\\' && p[1] != '\0') ? *++p : *p; *dest = '\0'; } /* Turn first word into something directly searchable. */ if (strlen(buff) > sizeof name - 4) { (void)fprintf(stderr, "%s: Parameter %s is too long\n", argv0, buff); exit(1); } (void)sprintf(name, "@<%s>@", buff); tp->Name = xstrdup(name); tp->Length = strlen(tp->Name); tp++; } (void)fclose(F); while (*av != NULL) Process(*av++, Table, tp); exit(0); /* NOTREACHED */ } inn-1.7.2/config/checkconf.sh0100644000175100001440000000135406443103542014356 0ustar mdusers#! /bin/sh ## $Revision: 1.2 $ ## ## Check the config.data file to make sure there is a tab on every ## non-comment line. case $# in *) ;; 0) echo "Can't check config.data: wrong number of arguments." 1>&2 esac ## Get the lines we care about. CONF="$1" shift sed -e '/^#/d' -e '/^$/d' "${CONF}" >config.x$$ ## Find the lines with tabs. grep ' ' config.y$$ ## If the lines we care about don't all have tabs, complain. diff config.x$$ config.y$$ >config.z$$ if [ -s config.z$$ ] ; then echo The following config parameters have no tabs: ## Work around lack of "-n" in some sed's. grep '<' config.z$$ | sed -e 's/ -- berkeley-unix -- # Start Date: Fri, 08 Nov 1996 14:48:44 +0100 # Project: INN # File: fixinterps.pl # RCSId: $Id: fixinterps.pl,v 1.2 1996/12/16 20:53:50 brister Exp $ # Description: Fix interpreter scripts based on config.data values (as # substituted into innshellvars.pl). This is written for # perl 4.0 on purpose. # # The normal subst must have been run on innshellvars.pl # beforehand. This doesn't get subst'd as it's done # before installation of innshellvars.pl (and hence must # use the one in the samples directory) # require 'getopts.pl' ; $0 =~ s!.*/!! ; $usage = "$0 [ -v -n -q ][ -d dir ][ -f innshellvars.pl ][ -t topdir ] file...\n" ; &Getopts ("vnqd:f:h") || die $usage ; die $usage if $opt_h ; $topdir = ($opt_t || "..") ; if ( ! -d $topdir ) { warn "No such directory: $topdir\n" ; $die = 1 ; } $config = ($opt_f || "$topdir/samples/innshellvars.pl") ; if ( ! -f $config ) { warn "No such file: $config\n" ; $die = 1 ; } $dir = ( $opt_d || "." ) ; if ( ! -d $dir ) { warn "No such directory: $dir\n" ; $die = 1 ; } $verbose = $opt_v ; $quiet = $opt_q ; exit (1) if $die ; do "$config" ; %interps = ( 'perl', $inn'perl, #' ) ; $perlver = &perlVersion($interps{'perl'}); chdir ($dir) ; foreach ( @ARGV ) { &fixInterp ($_) ; } # fix up the FILE script. sub fixInterp { local ($file) = @_ ; local ($newval,$isperl,$line,$warned,$_); if ( ! -f $file ) { warn "$file: no such file\n" ; return ; } open (INFILE, "<$file") || die "open($file): $!" ; chop ($line = ) ; ($interp = $line) =~ s/^#!\s*(\S+).*/$1/ ; ($base = $interp) =~ s!^.*/([^-_.0-9]*).*!$1! ; $newval = $interps{$base}; $isperl = ($base eq "perl"); if ( ! $newval ) { warn "$file: no substitution defined for $base\n" unless $quiet ; return ; } elsif ( $newval eq $interp ) { # Read the script and check that it doesn't require perl 5.x # and that we're substituting in perl4 while () { if ($isperl && $perlver < 5.0 && /^\s*require\s+(5\.\S+)/) { $warned++; warn ("\nWARNING. The script $file requires perl version ". "$1 (or greater),\nbut ". "your perl\n\n\t$newval\n\nlooks to be version " . "$perlver." . " If you're going to use this script you must fix\n" . "this in config.data, or after installation.\n\n") ; } } close (INFILE) ; warn "$file: no change\n" if $verbose ; return ; } $line =~ s/#!(\s*\S+)(.*)/#!$newval$2/ ; ($dev,$ino,$mode,$uid,$gid,$atime,$mtime) = (stat INFILE)[0,1,2,4,5,8,9] ; $mode = 0755 unless $dev ; $mtime = time unless $dev ; rename ($file,"$file.bak") ; if ( !open (OUTFILE,">$file") ) { close (INFILE) ; warn "open($file): $!" ; return ; } print OUTFILE "$line\n" ; while ( ) { if ($isperl && $perlver < 5.0 && /^\s*require\s+(5\.\S+)/) { warn ("\nWARNING. The script $file requires perl version ". "$1 (or greater),\nbut ". "your perl\n\n\t$newval\n\nlooks to be version " . "$perlver." . " If you're going to use this script you must fix\n" . "this in config.data, or after installation.\n\n") ; } print OUTFILE $_ ; } close (OUTFILE) ; chmod $mode, $file ; chown ($uid, $gid, $file) if ($> == 0) ; utime ($atime,$mtime,$file) || die "utime ($atime,$mtime,$file)" ; warn "$file: to $interps{$base}\n" if $verbose ; warn "$file: uid is different\n" if ($> != 0 && $uid != $> && !$quiet) ; close (INFILE) ; } sub perlVersion { local ($perl) = @_ ; local ($line); local ($_); local ($rval); return 0 if (! -x $perl) ; open (PERL,"$perl -v|") || die "Can't check version of perl ($perl)\n"; while () { if (/^this\s+is\s+perl,\s+version\s+(\S+)/i) { $rval = $1; } } close (PERL); if ($rval !~ /^\d+\.\d+(_\d+|)$/) { warn "perl version from $perl looks suspicious: $rval\n"; } return $rval; } inn-1.7.2/config/config.dist0100644000175100001440000010565006443103542014235 0ustar mdusers## $Revision: 1.64 $ ## ## InterNetNews configuration file. ## Note that if you leave a field blank, you must have the trailing tab! ## ## ## NOTE. This file is ready to build on BSD/OS (although you may want to ## tweak some things). If you're not on BSD/OS, then pay attention to ## variables like LIBS. ## ## ## 1. MAKE CONFIG PARAMETERS ## Where the DBZ sources are, from C News. INN has a (maybe old) copy. #### =()@>()= DBZDIR ../dbz ## If you have a parallel make, set this to "&" #### =()

@>()= P ## C pre-processor flags #### =()@>()= DEFS -I../include ## C compiler #### =()@>()= CC gcc ## Does your compiler properly do "char const *"? Pick DO DONT or DUNNO #### =()@>()= USE_CHAR_CONST DUNNO ## C compiler flags #### =()@>()= CFLAGS $(DEFS) -g ## C compiler flags to use when compiling dbz #### =()@>()= DBZCFLAGS $(CFLAGS) ## What flags to use if profiling; -p or -pg, e.g. #### =()@>()= PROF -pg ## Flags for the "cc -o" line; e.g., -Bstatic on SunOS4.x while debugging. #### =()@>()= LDFLAGS ## If you use the standard NNTP way of connecting, where is the library? #### =()@>()= NNTPLIB ## If you need to link in other libraries, add them here. ## On NetBSD and FreeBSD, you must add the -lcrypt directive here ## -lutil on BSD/OS gives you setproctitle() see HAVE_SETPROCTITLE. #### =()@>()= LIBS -lutil ## How to make a lint library; pick BSD, SYSV, or NONE. #### =()@>()= LINTLIBSTYLE NONE ## Flags for lint. AIX wants "-wkD"; it and others don't want "-z". #### =()@>()= LINTFLAGS -b -h -z $(DEFS) ## Some lints insist on putting out the filename and other crap. ## Possible values: ## LINTFILTER | sed -n -f ../sedf.aix ## LINTFILTER | sed -n -f ../sedf.osx ## LINTFILTER | sed -n -f ../sedf.sun ## LINTFILTER | sed -n -f ../sedf.sysv ## LINTFILTER #### =()@>()= LINTFILTER | sed -n -f ../sedf.sun ## How to install manpages; pick SOURCE, NROFF-PACK, NROFF-PACK-SCO, ## BSD4.4 or NONE. #### =()@>()= MANPAGESTYLE SOURCE ## Where various manpages should go #### =()@>()= MAN1 /usr/news/man/man1 #### =()@>()= MAN3 /usr/news/man/man3 #### =()@>()= MAN5 /usr/news/man/man5 #### =()@>()= MAN8 /usr/news/man/man8 ## Ranlib command. Use echo if you don't need ranlib. #### =()@>()= RANLIB ranlib ## YACC (yet another config control?) #### =()@>()= YACC yacc ## Ctags command. Use echo if you don't have ctags. #### =()@>()= CTAGS ctags -t -w ## ## 2. LOGGING LEVELS ## Facility innd should log under. #### =()@>()= LOG_INN_SERVER LOG_NEWS ## Facility all other programs should log under. #### =()@>()= LOG_INN_PROG LOG_NEWS ## Flags to use in opening the logs; some programs add LOG_PID. #### =()@>()= L_OPENLOG_FLAGS (LOG_CONS | LOG_NDELAY) ## Log a fatal error; program is about to exit. #### =()@>()= L_FATAL LOG_CRIT ## Log an error that might mean one or more articles get lost. #### =()@>()= L_ERROR LOG_ERR ## Informational notice, usually not worth caring about. #### =()@>()= L_NOTICE LOG_WARNING ## A protocol trace. #### =()@>()= L_TRACE LOG_DEBUG ## All incoming control commands (ctlinnd, etc). #### =()@>()= L_CC_CMD LOG_INFO ## ## 3. OWNERSHIPS AND FILE MODES ## Owner of articles and directories and _PATH_INNDDIR #### =()@>()= NEWSUSER news ## Group, for same purpose #### =()@>()= NEWSGROUP news ## Who gets email from news.daily and about control messages. #### =()@>()= NEWSMASTER usenet ## Who gets email on the Path line? #### =()@>()= PATHMASTER not-for-mail ## Umask to set. #### =()@>()= NEWSUMASK 02 ## Mode that incoming articles are created under. #### =()@>()= ARTFILE_MODE 0664 ## Mode that batch files are created under. #### =()@>()= BATCHFILE_MODE 0664 ## Mode that directories are created under. #### =()@>()= GROUPDIR_MODE 0775 ## ## 4. C LIBRARY DIFFERENCES ## Use stdargs, varargs, or neither? Pick VARARGS STDARGS or NONE. ## You need vfprintf and vfsprintf if not NONE. #### =()@>()= VAR_STYLE STDARGS ## If you don't have , set this to "mystring.h" #### =()@>()= STR_HEADER ## If you don't have , set this to "mymemory.h" #### =()@>()= MEM_HEADER ## What is a file offset? MUST BE LONG FOR NOW. #### =()@>()= OFFSET_T long ## What is the type of an object size? Usually size_t or unsigned int. #### =()@>()= SIZE_T size_t ## What is the type of a passwd uid and gid, for use in chown(2)? #### =()@>()= UID_T uid_t #### =()@>()= GID_T gid_t ## Type of a pid, for use in kill(2). #### =()@>()= PID_T pid_t ## Generic pointer, used by memcpy, malloc, etc. Usually char or void. #### =()@>()= POINTER void ## Worst-case alignment, in order to shut lint up #### =()@>()= ALIGNPTR int ## What should a signal handler return? Usually int or void. #### =()@>()= SIGHANDLER void ## Type of variables can be modified in a signal handler? sig_atomic_t #### =()@>()= SIGVAR sig_atomic_t ## Function that returns no value, and a pointer to it. Pick int or void #### =()@>()= FUNCTYPE void ## Type of 32 bit unsigned integer. #### =()@>()= U_INT32_T unsigned int ## Type of 32 bit signed integer. #### =()@>()= INT32_T int ## Use BSD4.2 or Posix directory names? Pick DIRENT or DIRECT. #### =()@>()= DIR_STYLE DIRENT ## Use flock, lockf, or nothing to lock files? ## Pick FLOCK, LOCKF, FCNTL, or NONE #### =()@>()= LOCK_STYLE FLOCK ## Do you have ? Pick DO or DONT #### =()@>()= HAVE_UNISTD DO ## Do you have setbuffer? Pick DO or DONT. #### =()@>()= HAVE_SETBUFFER DO ## Do you have gettimeofday? Pick DO or DONT. #### =()@>()= HAVE_GETTIMEOFDAY DO ## Do you have setproctitle()? Pick DO or DONT. ## You may need to adjust LIBS for this. #### =()@>()= HAVE_SETPROCTITLE DO ## Do you have fchmod? Pick DO or DONT. #### =()@>()= HAVE_FCHMOD DO ## Do you have setsid()? Pick DO or DONT. #### =()@>()= HAVE_SETSID DO ## Does your (struct tm) have a tm_gmtoff field? Pick DO or DONT. #### =()@>()= HAVE_TM_GMTOFF DO ## Does your (struct stat) have a st_blksize field? Pick DO or DONT. #### =()@>()= HAVE_ST_BLKSIZE DO ## Use waitpid instead of wait3? Pick DO or DONT. #### =()@>()= HAVE_WAITPID DO ## Use "union wait" instead of int? Pick DO or DONT. #### =()@>()= USE_UNION_WAIT DONT ## How to fork? Pick fork or vfork. #### =()@>()= FORK vfork ## Do you have ? Pick DO or DONT. #### =()@>()= HAVE_VFORK DONT ## Do you have symbolic links? Pick DO or DONT. #### =()@>()= HAVE_SYMLINK DO ## Do you have Unix-domain sockets? Pick DO or DONT. #### =()@>()= HAVE_UNIX_DOMAIN DO ## Does your AF_UNIX bind use sizeof for the socket size? Pick DO or DONT. #### =()@>()= BIND_USE_SIZEOF DO ## How should close-on-exec be done? Pick IOCTL or FCNTL. #### =()@>()= CLX_STYLE IOCTL ## How should non-blocking I/O be done? Pick IOCTL or FCNTL. #### =()@>()= NBIO_STYLE FCNTL ## How should resource-totalling be done? Pick RUSAGE or TIMES #### =()@>()= RES_STYLE RUSAGE ## How to get number of available descriptors? ## Pick GETDTAB, GETRLIMIT, SYSCONF, ULIMIT, or CONSTANT. #### =()@>()= FDCOUNT_STYLE GETRLIMIT ## If greater than -1, then use [gs]etrlimit to set that many descriptors. ## If -1, then no [gs]etrlimit calls are done. #### =()@>()= NOFILE_LIMIT -1 ## Do you need as well as ? Pick DO or DONT. #### =()@>()= NEED_TIME DONT ## What predicate, if any, the macros need #### =()@>()= CTYPE (isascii((c)) && isXXXXX((c))) #CTYPE ((c) > 0 && isXXXXX((c))) #CTYPE isXXXXX((c)) ## What's the return type of abort? Usually int or void. #### =()@>()= ABORTVAL void ## What's the return type of alarm? Usually int or unsigned int. #### =()@>()= ALARMVAL unsigned int ## What's the return type of getpid? Usually int or unsigned int. #### =()@>()= GETPIDVAL pid_t ## What's the return type of sleep? Usually int or unsigned int. #### =()@>()= SLEEPVAL unsigned int ## What's the return type of qsort? Usually int or void. #### =()@>()= QSORTVAL void ## What's the return type of lseek? Usually long or off_t. #### =()@>()= LSEEKVAL off_t ## What's the return type of free? Usually int or void. #### =()@>()= FREEVAL void ## What's the return type of exit? Usually int or void. ## (For gcc (not pedantic ANSI) use "volatile void" in EXITVAL and _EXITVAL.) #### =()@>()= EXITVAL void ## What's the return type of _exit? Usually int or void. #### =()<_EXITVAL @<_EXITVAL>@>()= _EXITVAL void ## ## 5. C LIBRARY OMISSIONS ## Possible values: ## MISSING_MAN strcasecmp.3 syslog.3 ## MISSING_SRC strcasecmp.c syslog.c strerror.c getdtab.c ## MISSING_OBJ strcasecmp.o syslog.o strerror.o getdtab.c ## getdtab has a getdtablesize() routine if you need it; see the lib ## directory and Install.ms for others. ## OSx systems should add $(OSXATTOBJ) to MISSING_OBJ. #### =()@>()= MISSING_MAN #### =()@>()= MISSING_SRC #### =()@>()= MISSING_OBJ ## ## 6. MISCELLANEOUS CONFIG DATA ## ## Use read/write to update the active file, or mmap? Pick READ or MMAP. #### =()@>()= ACT_STYLE READ ## Do you want mail notifications of bad control messages. DO or DONT ## Setting it to do results in a lot of mail with the number of spammers ## out there. #### =()@>()= MAIL_BADCONTROLS DONT ## What type of pointer does mmap() manage? Normally ``caddr_t'' or ``void *'' ## or ``char *'' #### =()@>()= MMAP_PTR caddr_t ## Should we msync when using mmap? Pick DO or DONT. Useful ## with some slightly broken mmap implementations. (like HPUX and BSD/OS). #### =()@>()= MMAP_SYNC DONT ## Should we call your msync() with 3 args? (addr,len,flags) ## Choose DO or DONT. #### =()@>()= MSYNC_3_ARG DONT ## Do clients use our NNTP-server-open routine, or the one in NNTP? ## INND is nicer, but you must install inn.conf files everywhere; NNTP ## is better if you already have lots of /usr/lib/news/server files. ## Pick INND or NNTP. #### =()@>()= REM_STYLE INND ## Should rnews save articles that the server rejects? Pick DO or DONT. #### =()@>()= RNEWS_SAVE_BAD DONT ## Should rnews log articles innd already has? Pick SYSLOG, FILE, OR DONT. #### =()@>()= RNEWS_LOG_DUPS DONT ## Look in _PATH_RNEWSPROGS for rnews unpackers? Pick DO or DONT. #### =()@>()= RNEWSPROGS DO ## Should rnews try the local host? Pick DO or DONT. #### =()@>()= RNEWSLOCALCONNECT DO ## Environment variable that has remote hostname for rnews. #### =()<_ENV_UUCPHOST @<_ENV_UUCPHOST>@>()= _ENV_UUCPHOST UU_MACHINE ## Require posts to have under 50% inclusion (">") lines? Pick DO OR DONT. ## (This is only for inews and nnrpd.) #### =()@>()= CHECK_INCLUDED_TEXT DO ## Put hosts in the inews Path header? Pick DO or DONT. #### =()@>()= INEWS_PATH DO ## Munge the gecos field of password entry? Pick DO or DONT. #### =()@>()= MUNGE_GECOS DO ## How many times to try to fork before giving up #### =()@>()= MAX_FORKS 10 ## Largest acceptable article size; 0 allows any size #### =()@>()= MAX_ART_SIZE 1000000L ## Value of dbzincore(FLAG) call in innd. Pick 1 or 0. #### =()@>()= INND_DBZINCORE 1 ## Should sub-processes get a nice(2) value? Pick DO or DONT. #### =()@>()= INND_NICE_KIDS DO ## Value for nice(2) call in innd. #### =()@>()= INND_NICE_VALUE 4 ## Null-terminated list of unknown commands to not log to syslog. ## INND_QUIET_BADLIST "xstream", "xfoo", NULL #### =()@>()= INND_QUIET_BADLIST NULL ## Null-terminated set of illegal distribution patterns for local postings. #### =()@>()= BAD_DISTRIBS "*.*",NULL ## Verify that the poster is the person doing the cancel? Pick DO or DONT. ## (Can't do this if cancel arrives before the article does, by the way, ## in which case the early cancel will be ignored.) #### =()@>()= VERIFY_CANCELS DONT ## Log "ctlinnd cancel" commands to syslog? Pick DO or DONT. #### =()@>()= LOG_CANCEL_COMMANDS DONT ## File unknown "to.*" groups into the "to" newsgroup? Pick DO or DONT. #### =()@>()= MERGE_TO_GROUPS DONT ## File articles in unknown newsgroups into junk? Pick DO or DONT. #### =()@>()= WANT_TRASH DONT ## Record rejected articles in history? Pick DO or DONT. #### =()@>()= REMEMBER_TRASH DO ## Check the linecount against the Lines header? Pick DO or DONT. #### =()@>()= CHECK_LINECOUNT DONT ## If checking, the error must be within LINECOUNT_FUZZ lines. ## Five is number of .signature lines + 1. #### =()@>()= LINECOUNT_FUZZ 5 ## Have innd throttle itself after this many I/O errors. #### =()@>()= IO_ERROR_COUNT 50 ## Default value for ctlinnd -t flag; use 0 to wait and poll. #### =()@>()= CTLINND_TIMEOUT 0 ## Flush logs if we go this long with no I/O. #### =()@>()= DEFAULT_TIMEOUT 300 ## INND closes channel if inactive this long (seconds). #### =()@>()= PEER_TIMEOUT (1 * 60 * 60) ## NNRP exits if first command doesn't arrive within this time (seconds). #### =()@>()= INIT_CLIENT_TIMEOUT 30 ## NNRP exits if inactive for this long (seconds). #### =()@>()= CLIENT_TIMEOUT (10 * 60) ## Allow nnrpd readers when paused or throttled? Pick DO or DONT. #### =()@>()= ALLOW_READERS DO ## Refuse newsreader connections if load is higher then this; -1 disables. #### =()@>()= NNRP_LOADLIMIT 16 ## Don't readdir() spool dir if same group within this many secs. #### =()@>()= NNRP_RESCAN_DELAY 60 ## Do gethostbyaddr on client adresses in nnrp? Pick DO or DONT. ## (If DONT, then use only IP addresses in hosts.nnrp) #### =()@>()= NNRP_GETHOSTBYADDR DO ## How many Message-ID retrievals until nnrpd does a dbzincore? Set ## to -1 to never do incore. #### =()@>()= NNRP_DBZINCORE_DELAY 40 ## Strip Sender from posts that didn't authenticate? Pick DO or DONT. #### =()@>()= NNRP_AUTH_SENDER DO ## Do you want to make life easy for peers to pull feeds from you (it's ## harder on your machine). Pick DO or DONT. With DONT, you get a small ## sleep inserted before each ARTICLE command is processed. (With ## apologies to the Australians in the audience). #### =()@>()= LIKE_PULLERS DO ## Allow the NEWNEWS NNTP command? Pick DO or DONT. ## (RFC 977 says you should; your server performance may not agree...) #### =()@>()= ALLOW_NEWNEWS DONT ## How many read/write failures until channel is put to sleep or closed? #### =()@>()= BAD_IO_COUNT 5 ## Multiplier for sleep in EWOULDBLOCK writes (seconds). #### =()@>()= BLOCK_BACKOFF (2 * 60) ## How many article-writes between active and history updates? #### =()@>()= ICD_SYNC_COUNT 10 ## Tell resolver _res.options to be fast? Pick DO or DONT. #### =()@>()= FAST_RESOLV DONT ## Drop articles that were posted this many days ago. #### =()@>()= DEFAULT_CUTOFF 14 ## Maximum number of incoming NNTP connections. #### =()@>()= DEFAULT_CONNECTIONS 50 ## Wait this many seconds before channel restarts. #### =()@>()= CHANNEL_RETRY_TIME (5 * 60) ## Wait this many seconds before seeing if pause is ended. #### =()@>()= PAUSE_RETRY_TIME (5 * 60) ## Wait this many seconds between noticing inactive channels. #### =()@>()= CHANNEL_INACTIVE_TIME (10 * 60) ## Put nntplink info (filename) into the log? #### =()@>()= NNTPLINK_LOG DONT ## Put article size into the log? #### =()@>()= LOG_SIZE DO ## Log by host IP address, rather than from Path line? #### =()@>()= IPADDR_LOG DO ## Log NNTP activity after this many articles. #### =()@>()= NNTP_ACTIVITY_SYNC 200 ## Free buffers bigger than this when we're done with them. #### =()@>()= BIG_BUFFER (2 * START_BUFF_SIZE) ## A general small buffer. #### =()@>()= SMBUF 256 ## Buffer for a single article name. #### =()@>()= MAXARTFNAME 10 ## Buffer for a single pathname in the spool directory. #### =()@>()= SPOOLNAMEBUFF 512 ## Maximum size of a single header. #### =()@>()= MAXHEADERSIZE 1024 ## Byte limit on locally-posted articles; 0 to disable the check. #### =()@>()= LOCAL_MAX_ARTSIZE 1000000L ## Default number of bytes to hold in memory when buffered. #### =()@>()= SITE_BUFFER_SIZE (16 * 1024) ## Do you have uustat, or just uuq? Pick DO or DONT #### =()@>()= HAVE_UUSTAT DO ## Should INN do some setsockopts on network connections. Pick DO or DONT. ## Some versions of Solaris should set to DONT (pre 2.4 it seems) #### =()@>()= SET_SOCKOPT DO ## ## 7. PATHS TO COMMON PROGRAMS ## Where the raison d'etre for this distribution lives. #### =()<_PATH_INND @<_PATH_INND>@>()= _PATH_INND /usr/news/bin/innd ## Where the optional front-end that exec's innd lives. #### =()<_PATH_INNDSTART @<_PATH_INNDSTART>@>()= _PATH_INNDSTART /usr/news/bin/inndstart ## Where news boot-up script should be installed. #### =()<_PATH_NEWSBOOT @<_PATH_NEWSBOOT>@>()= _PATH_NEWSBOOT /usr/news/bin/rc.news ## Where sendmail, or a look-alike, lives. Inlude %s for addresses. #### =()<_PATH_SENDMAIL @<_PATH_SENDMAIL>@>()= _PATH_SENDMAIL /usr/sbin/sendmail -oi %s ## Where the shell is. #### =()<_PATH_SH @<_PATH_SH>@>()= _PATH_SH /bin/sh ## Where the compress program lives. #### =()<_PATH_COMPRESS @<_PATH_COMPRESS>@>()= _PATH_COMPRESS /usr/bin/compress ## What extension your compress appends #### =()<_PATH_COMPRESSEXT @<_PATH_COMPRESSEXT>@>()= _PATH_COMPRESSEXT .Z ## Where egrep lives (you might need the FSF one; see scanlogs) #### =()<_PATH_EGREP @<_PATH_EGREP>@>()= _PATH_EGREP /usr/bin/egrep ## Where perl lives #### =()<_PATH_PERL @<_PATH_PERL>@>()= _PATH_PERL /usr/bin/perl5 ## Where awk lives #### =()<_PATH_AWK @<_PATH_AWK>@>()= _PATH_AWK /usr/bin/awk ## Where sed lives (you might need the FSF one) #### =()<_PATH_SED @<_PATH_SED>@>()= _PATH_SED /usr/bin/sed ## Where sort lives (you may want the FSF one). #### =()<_PATH_SORT @<_PATH_SORT>@>()= _PATH_SORT /usr/bin/sort ## Where inews lives. #### =()<_PATH_INEWS @<_PATH_INEWS>@>()= _PATH_INEWS /usr/news/bin/inews ## Where rnews lives. #### =()<_PATH_RNEWS @<_PATH_RNEWS>@>()= _PATH_RNEWS /usr/news/bin/rnews ## Where generic authentication programs live. #### =()<_PATH_AUTHDIR @<_PATH_AUTHDIR>@>()= _PATH_AUTHDIR /usr/news/bin/auth ## Where the NNRP server lives. #### =()<_PATH_NNRPD @<_PATH_NNRPD>@>()= _PATH_NNRPD /usr/news/bin/nnrpd ## The path of the process run when an unknown host connects to innd. ## Usually the same as _PATH_NNRPD, but may be, e.g., the path to ## nntpd from the reference implementation. #### =()<_PATH_NNTPD @<_PATH_NNTPD>@>()= _PATH_NNTPD /usr/news/bin/nnrpd ## Where the NNQR server lives. Make same as _PATH_NNRPD for now #### =()<_PATH_NNQRD @<_PATH_NNRPD>@>()= _PATH_NNQRD /usr/news/bin/nnrpd ## Where most other programs live. ## See also _PATH_RNEWSPROGS and _PATH_CONTROLPROGS, below. #### =()<_PATH_NEWSBIN @<_PATH_NEWSBIN>@>()= _PATH_NEWSBIN /usr/news/bin ## Where temporary files live on the server. Probably shouldn't be world ## writable. #### =()<_PATH_TMP @<_PATH_TMP>@>()= _PATH_TMP /var/tmp ## Command to send mail (with -s "subject" allowed) #### =()<_PATH_MAILCMD @<_PATH_MAILCMD>@>()= _PATH_MAILCMD /usr/news/bin/innmail ## Where scripts should have shlock create locks. #### =()<_PATH_LOCKS @<_PATH_LOCKS>@>()= _PATH_LOCKS /var/news/locks ## Where your GNU gzip binary is (for rnews to run on gzipped batches). #### =()<_PATH_GZIP @<_PATH_GZIP>@>()= _PATH_GZIP /usr/contrib/bin/gzip ## ## 8. PATHS RELATED TO THE SPOOL DIRECTORY ## Spool directory, where articles live. #### =()<_PATH_SPOOL @<_PATH_SPOOL>@>()= _PATH_SPOOL /var/news/spool/articles ## Spool directory where overview data lives. #### =()<_PATH_OVERVIEWDIR @<_PATH_OVERVIEWDIR>@>()= _PATH_OVERVIEWDIR /var/news/spool/over.view ## Name of overview file within its spool directory. #### =()<_PATH_OVERVIEW @<_PATH_OVERVIEW>@>()= _PATH_OVERVIEW .overview ## Where rnews spools its input. #### =()<_PATH_SPOOLNEWS @<_PATH_SPOOLNEWS>@>()= _PATH_SPOOLNEWS /var/news/spool/in.coming ## Where rnews creates temporary files until finished #### =()<_PATH_SPOOLTEMP @<_PATH_SPOOLTEMP>@>()= _PATH_SPOOLTEMP /var/tmp ## Where rnews puts bad input. #### =()<_PATH_BADNEWS @<_PATH_BADNEWS>@>()= _PATH_BADNEWS /var/news/spool/in.coming/bad ## Where rnews puts bad input, relative to _PATH_SPOOLNEWS. #### =()<_PATH_RELBAD @<_PATH_RELBAD>@>()= _PATH_RELBAD bad ## Where the XBATCH command should put the batches. Normally same as ## _PATH_SPOOLNEWS so that 'rnews -U' can find it. #### =()<_PATH_XBATCHES @<_PATH_XBATCHES>@>()= _PATH_XBATCHES /var/news/spool/in.coming ## ## 9. EXECUTION PATHS FOR INND AND RNEWS ## Pathname where dups are logged if RNEWS_LOG_DUPS is FILE. #### =()<_PATH_RNEWS_DUP_LOG @<_PATH_RNEWS_DUP_LOG>@>()= _PATH_RNEWS_DUP_LOG /dev/null ## Rnews may execute any program in this directory; see RNEWSPROGS. #### =()<_PATH_RNEWSPROGS @<_PATH_RNEWSPROGS>@>()= _PATH_RNEWSPROGS /usr/news/bin/rnews.libexec ## Path to control messages scripts. #### =()<_PATH_CONTROLPROGS @<_PATH_CONTROLPROGS>@>()= _PATH_CONTROLPROGS /usr/news/bin/control ## Default "unknown/illegal" control script, within _PATH_CONTROLPROGS. #### =()<_PATH_BADCONTROLPROG @<_PATH_BADCONTROLPROG>@>()= _PATH_BADCONTROLPROG default ## ## 10. SOCKETS CREATED BY INND OR CLIENTS #### =()<_PATH_INNDDIR @<_PATH_INNDDIR>@>()= _PATH_INNDDIR /var/news/run ## Unix-domain stream socket that rnews connects to. #### =()<_PATH_NNTPCONNECT @<_PATH_NNTPCONNECT>@>()= _PATH_NNTPCONNECT /var/news/run/nntpin ## Unix-domain datagram socket that ctlinnd to. #### =()<_PATH_NEWSCONTROL @<_PATH_NEWSCONTROL>@>()= _PATH_NEWSCONTROL /var/news/run/control ## Temporary socket created by ctlinnd; run through mktemp #### =()<_PATH_TEMPSOCK @<_PATH_TEMPSOCK>@>()= _PATH_TEMPSOCK /var/news/run/ctlinndXXXXXX ## ## 11. LOG AND CONFIG FILES ## Shell script that sets most of these as shell vars #### =()<_PATH_SHELLVARS @<_PATH_SHELLVARS>@>()= _PATH_SHELLVARS /var/news/etc/innshellvars ## Perl script that sets most of these as perl variables #### =()<_PATH_PERL_SHELLVARS @<_PATH_PERL_SHELLVARS>@>()= _PATH_PERL_SHELLVARS /var/news/etc/innshellvars.pl ## TCL script that sets most of these as tcl variables #### =()<_PATH_TCL_SHELLVARS @<_PATH_TCL_SHELLVARS>@>()= _PATH_TCL_SHELLVARS /var/news/etc/innshellvars.tcl ## csh script that sets most of these as csh variables #### =()<_PATH_CSH_SHELLVARS @<_PATH_CSH_SHELLVARS>@>()= _PATH_CSH_SHELLVARS /var/news/etc/innshellvars.csh ## Where most config and data files are usually stored; not required ## to the home directory of NEWSUSER. #### =()<_PATH_NEWSLIB @<_PATH_NEWSLIB>@>()= _PATH_NEWSLIB /var/news/etc ## The group owner of the rnews program. Usually uucp. #### =()@>()= RNEWS_GROUP uucp ## The server's log file. #### =()<_PATH_LOGFILE @<_PATH_LOGFILE>@>()= _PATH_LOGFILE /var/log/news/news ## The server's error log file. #### =()<_PATH_ERRLOG @<_PATH_ERRLOG>@>()= _PATH_ERRLOG /var/log/news/errlog ## Where most sylog log files go; see also scanlogs, innstat, etc. #### =()<_PATH_MOST_LOGS @<_PATH_MOST_LOGS>@>()= _PATH_MOST_LOGS /var/log/news ## How many generates of log files to keep. #### =()@>()= LOG_CYCLES 3 ## Text value of the server's pid. #### =()<_PATH_SERVERPID @<_PATH_SERVERPID>@>()= _PATH_SERVERPID /var/news/run/innd.pid ## The newsfeeds file, on the server host. #### =()<_PATH_NEWSFEEDS @<_PATH_NEWSFEEDS>@>()= _PATH_NEWSFEEDS /var/news/etc/newsfeeds ## The article history database, on the server host. #### =()<_PATH_HISTORY @<_PATH_HISTORY>@>()= _PATH_HISTORY /var/news/etc/history ## File listing the sites that feed us news. #### =()<_PATH_INNDHOSTS @<_PATH_INNDHOSTS>@>()= _PATH_INNDHOSTS /var/news/etc/hosts.nntp ## The active file, on the server host. #### =()<_PATH_ACTIVE @<_PATH_ACTIVE>@>()= _PATH_ACTIVE /var/news/etc/active ## A temporary active file, for writing on the server host. #### =()<_PATH_NEWACTIVE @<_PATH_NEWACTIVE>@>()= _PATH_NEWACTIVE /var/news/etc/active.tmp ## An old active file on the server host. #### =()<_PATH_OLDACTIVE @<_PATH_OLDACTIVE>@>()= _PATH_OLDACTIVE /var/news/etc/active.old ## The log of when groups are created. #### =()<_PATH_ACTIVETIMES @<_PATH_ACTIVETIMES>@>()= _PATH_ACTIVETIMES /var/news/etc/active.times ## Where batch files are located. #### =()<_PATH_BATCHDIR @<_PATH_BATCHDIR>@>()= _PATH_BATCHDIR /var/news/spool/out.going ## Where archives are kept. #### =()<_PATH_ARCHIVEDIR @<_PATH_ARCHIVEDIR>@>()= _PATH_ARCHIVEDIR /var/news/spool/archive ## Where NNRP distributions file is #### =()<_PATH_NNRPDIST @<_PATH_NNRPDIST>@>()= _PATH_NNRPDIST /var/news/etc/distributions ## Where the NNRP automatic subscriptions file is #### =()<_PATH_NNRPSUBS @<_PATH_NNRPSUBS>@>()= _PATH_NNRPSUBS /var/news/etc/subscriptions ## Where the default Distribution assignments file is #### =()<_PATH_DISTPATS @<_PATH_DISTPATS>@>()= _PATH_DISTPATS /var/news/etc/distrib.pats #### =()<_PATH_NEWSGROUPS @<_PATH_NEWSGROUPS>@>()= _PATH_NEWSGROUPS /var/news/etc/newsgroups ## File where client configuration parameters can be read. #### =()<_PATH_CONFIG @<_PATH_CONFIG>@>()= _PATH_CONFIG /var/news/etc/inn.conf ## The possible active file, on clients (NFS-mounted, e.g.). #### =()<_PATH_CLIENTACTIVE @<_PATH_CLIENTACTIVE>@>()= _PATH_CLIENTACTIVE /var/news/etc/active ## A temporary file, for client inews to use. #### =()<_PATH_TEMPACTIVE @<_PATH_TEMPACTIVE>@>()= _PATH_TEMPACTIVE /var/tmp/activeXXXXXX ## Where to mail to the moderators. #### =()<_PATH_MODERATORS @<_PATH_MODERATORS>@>()= _PATH_MODERATORS /var/news/etc/moderators ## A temporary file, for client inews to use. #### =()<_PATH_TEMPMODERATORS @<_PATH_TEMPMODERATORS>@>()= _PATH_TEMPMODERATORS /var/tmp/moderatorsXXXXXX ## Where NNTP puts the name of the server. #### =()<_PATH_SERVER @<_PATH_SERVER>@>()= _PATH_SERVER /var/news/etc/server ## File with name/password for all remote connections. #### =()<_PATH_NNTPPASS @<_PATH_NNTPPASS>@>()= _PATH_NNTPPASS /var/news/etc/passwd.nntp ## NNRP access file. #### =()<_PATH_NNRPACCESS @<_PATH_NNRPACCESS>@>()= _PATH_NNRPACCESS /var/news/etc/nnrp.access ## Default expire control file. #### =()<_PATH_EXPIRECTL @<_PATH_EXPIRECTL>@>()= _PATH_EXPIRECTL /var/news/etc/expire.ctl ## Prolog to parse control scripts #### =()<_PATH_PARSECTL @<_PATH_PARSECTL>@>()= _PATH_PARSECTL /var/news/etc/parsecontrol ## Access control file for control scripts. #### =()<_PATH_CONTROLCTL @<_PATH_CONTROLCTL>@>()= _PATH_CONTROLCTL /var/news/etc/control.ctl ## Innwatch control file. #### =()<_PATH_CTLWATCH @<_PATH_CTLWATCH>@>()= _PATH_CTLWATCH /var/news/etc/innwatch.ctl ## Where innwatch writes its own pid. #### =()<_PATH_WATCHPID @<_PATH_WATCHPID>@>()= _PATH_WATCHPID /var/news/run/innwatch.pid ## Where innwatch writes status when it gets an interrupt #### =()<_PATH_INNWSTATUS @<_PATH_INNWSTATUS>@>()= _PATH_INNWSTATUS /var/news/run/innwatch.status ## Format of news overview database #### =()<_PATH_SCHEMA @<_PATH_SCHEMA>@>()= _PATH_SCHEMA /var/news/etc/overview.fmt ## ## 12. INNWATCH CONFIGURATION ## Load average (* 100) at which innd should be paused. #### =()@>()= INNWATCH_PAUSELOAD 1500 ## Load average (* 100) at which innd should be throttled. #### =()@>()= INNWATCH_HILOAD 2000 ## Load average (* 100) at which to restart innd (pause/throttle undone). #### =()@>()= INNWATCH_LOLOAD 1000 ## Space, in df output units, at which to throttle innd on _PATH_SPOOL ## or _PATH_OVERVIEWDIR. #### =()@>()= INNWATCH_SPOOLSPACE 8000 ## Space, in df output units, at which to throttle innd on _PATH_BATCHDIR. #### =()@>()= INNWATCH_BATCHSPACE 800 ## Space, in df output units, at which to throttle innd on _PATH_NEWSLIB. #### =()@>()= INNWATCH_LIBSPACE 25000 ## Number of inodes at which to throttle innd on _PATH_SPOOL. #### =()@>()= INNWATCH_SPOOLNODES 200 ## How long to sleep between innwatch iterations. #### =()@>()= INNWATCH_SLEEPTIME 600 ## How inn (not just innwatch anymore) gets disk space usage ## (SVR4 machine would probably use /usr/ucb/df) #### =()@>()= INNWATCH_DF /bin/df ## Field number of INNWATCH_DF (with -i) output that gives free ## inodes (starting at 1). #### =()@>()= INNWATCH_INODES 7 ## Field number of INNWATCH_DF output that gives the free block count. ##### =()@>()= INNWATCH_BLOCKS 4 ## ## 13. TCL Configuration ## Do you want TCL support? Pick DO or DONT #### =()@>()= TCL_SUPPORT DONT ## Where your tcl header file live. Blank if no TCL ### =()@>()= TCL_INC # TCL_INC -I/usr/local/include ## How do you get the TCL library? Probably -ltcl -lm, blank if no TCL #### =()@>()= TCL_LIB # TCL_LIB -ltcl -lm ## TCL Startup File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_STARTUP @<_PATH_TCL_STARTUP>@>()= _PATH_TCL_STARTUP /usr/news/bin/control/startup.tcl ## TCL Filter File. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_TCL_FILTER @<_PATH_TCL_FILTER>@>()= _PATH_TCL_FILTER /usr/news/bin/control/filter.tcl ## ## 14. PGP Configuration ## ## Do you want PGP verification of control messages? Pick DO or DONT ## If you change this then you need to fiddle with control.ctl. ## Setting it DONT is a really bad idea with all the miscreants out there... #### =()@>()= WANT_PGPVERIFY DO ## PGP binary. #### =()<_PATH_PGP @<_PATH_PGP>@>()= _PATH_PGP /usr/local/bin/pgp ## ## 15. Local Configuration ## ## Home of the NEWSUSER #### =()<_PATH_NEWSHOME @<_PATH_NEWSHOME>@>()= _PATH_NEWSHOME /usr/news ## ## 16. Actsync Configuration. ## ## Host to synchoronize active file with (see actsync and actsyncd manpages). #### =()@>()= ACTSYNC_HOST news.foo.bar.com ## Flags actsyncd is to pass to actsync. #### =()@>()= ACTSYNC_FLAGS -v 2 -q 2 -b 0 -d 0 -g 7 -s 79 -t 2 ## Actsyncd config file. #### =()<_PATH_ACTSYNC_CFG @<_PATH_ACTSYNC_CFG>@>()= _PATH_ACTSYNC_CFG /var/news/etc/actsync.cfg ## Actsyncd ignore file. #### =()<_PATH_ACTSYNC_IGN @<_PATH_ACTSYNC_IGN>@>()= _PATH_ACTSYNC_IGN /var/news/etc/actsync.ign ## 17. Perl Configuration ## Do you want Perl support? Pick DO or DONT #### =()@>()= PERL_SUPPORT DONT ## How do you get the PERL libraries? Probably -lperl -lm, blank if no PERL #### =()@>()= PERL_LIB #PERL_LIB -L/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE -lperl -lm ## Core directory (includes, libs). See perlembed(1) #### =()@>()= PERL_INC #PERL_INC -I/usr/local/gnu/lib/perl5/i386-bsdos/5.003/CORE ## Perl Filter Files. Should probably be prefixed with the same value as ## _PATH_CONTROLPROGS. #### =()<_PATH_PERL_STARTUP_INND @<_PATH_PERL_STARTUP_INND>@>()= _PATH_PERL_STARTUP_INND /usr/news/bin/control/startup_innd.pl #### =()<_PATH_PERL_FILTER_INND @<_PATH_PERL_FILTER_INND>@>()= _PATH_PERL_FILTER_INND /usr/news/bin/control/filter_innd.pl #### =()<_PATH_PERL_FILTER_NNRPD @<_PATH_PERL_FILTER_NNRPD>@>()= _PATH_PERL_FILTER_NNRPD /usr/news/bin/control/filter_nnrpd.pl inn-1.7.2/config/subst.sh0100755000175100001440000000275506443103542013604 0ustar mdusers#! /bin/sh # subst - substitute strings into files, carefully PATH=/bin:/usr/bin ; export PATH sed=sed case "$1" in -e) sed=$2 shift ; shift ;; esac case "$1" in -f) substs=$2 shift ; shift ;; *) echo "$0: no substitutions file given" >&2 exit 2 ;; esac them="`${sed} -e '/^#/d' \ -e '/^[ ]*$/d' \ -e '/&/s/&/\\\\&/g' \ -e 's/^\\([^ ]*\\) *\\([^ ]*\\)$/s#@<\\1>@#\\2#g/' \ $substs`" for f do # first, figure out temporary names case "$f" in */*) file="`expr \"$f\" : '.*/\\([^/]*\\)'`" dir="`expr \"$f\" : '\\(.*\\)/[^/]*'`" new="$dir/substtmp.new" old="$dir/substtmp.old" ;; *) new="substtmp.new" old="substtmp.old" ;; esac echo "$f: " | tr -d '\012' # test existences if test ! -f $f then echo "$0: cannot find \`$f'" >&2 continue # NOTE CONTINUE fi if test -r $new then echo "$0: $new exists, cannot proceed" >&2 exit 1 fi if test -r $old then echo "$0: $old exists, cannot proceed" >&2 exit 1 fi ( >$old >$new ) 2>/dev/null if test ! -w "$old" -o ! -w "$new" then rm -f $old $new echo "$0: cannot create temporaries $old $new" >&2 exit 1 fi # generate the new version trap "rm -f $new; exit" 1 2 15 ${sed} "/=()<.*>()=/{ h n g s/.*=()()=.*// $them }" $f >$new # substitute new for old, if necessary if cmp -s $new $f then rm -f $new $old echo "unchanged" else trap "mv $old $f; exit" 1 2 15 mv $f $old mv $new $f trap "rm -f $old; exit" 1 2 15 rm -f $old echo "updated" fi done inn-1.7.2/config/files.list0100644000175100001440000000441106443103542014073 0ustar mdusers;; $Revision: 1.31 $ ;; List of InterNetNews files that are fed to subst. ;; Lines beginning with a semi-colon are comment lines. ../backends/Makefile ../backends/actsync.c ../backends/actmerge.sh ../backends/actsyncd.sh ../backends/sendxbatches.sh ../doc/Makefile ../doc/active.5 ../doc/actsync.8 ../doc/archive.8 ../doc/batcher.8 ../doc/buffchan.8 ../doc/control.ctl.5 ../doc/crosspost.8 ../doc/ctlinnd.8 ../doc/cvtbatch.8 ../doc/distrib.pats.5 ../doc/expire.8 ../doc/expire.ctl.5 ../doc/expireover.8 ../doc/expirerm.8 ../doc/filechan.8 ../doc/getlist.1 ../doc/history.5 ../doc/hosts.nntp.5 ../doc/inews.1 ../doc/inn.conf.5 ../doc/innd.8 ../doc/inndcomm.3 ../doc/innwatch.8 ../doc/innwatch.ctl.5 ../doc/innxbatch.8 ../doc/innxmit.8 ../doc/libinn.3 ../doc/makeactive.8 ../doc/makehistory.8 ../doc/moderators.5 ../doc/news.daily.8 ../doc/newsfeeds.5 ../doc/newslog.5 ../doc/nnrp.access.5 ../doc/nnrpd.8 ../doc/nntpsend.8 ../doc/nntpsend.ctl.5 ../doc/overchan.8 ../doc/overview.fmt.5 ../doc/passwd.nntp.5 ../doc/prunehistory.8 ../doc/qio.3 ../doc/rnews.1 ../doc/shlock.1 ../doc/shrinkfile.1 ../doc/writelog.8 ../expire/Makefile ../frontends/Makefile ../include/clibrary.h ../include/configdata.h ../include/libinn.h ../include/logging.h ../include/macros.h ../include/paths.h ../innd/Makefile ../lib/Makefile ../makedirs.sh ../nnrpd/Makefile ../samples/actsync.cfg ;; ../samples/actsync.ign ../samples/checkgroups ../samples/default ../samples/docheckgroups ../samples/expirerm ../samples/ihave ../samples/inncheck ../samples/innstat ../samples/innwatch ../samples/innwatch.ctl ../samples/innshellvars ../samples/innshellvars.csh ../samples/innshellvars.pl ../samples/innshellvars.tcl ;; ../samples/makegroup ../samples/newgroup ../samples/news.daily ../samples/nntpsend ../samples/parsecontrol ../samples/pgpverify ../samples/rc.news ../samples/rmgroup ../samples/scanlogs ../samples/scanspool ../samples/send-ihave ../samples/send-nntp ../samples/send-uucp ../samples/sendbatch ../samples/sendme ../samples/sendsys ../samples/senduuname ../samples/startup.tcl ;; ../samples/filter.tcl ../samples/tally.control ../samples/tally.unwanted ../samples/version ../samples/writelog ../site/Makefile ../syslog/syslog.c ../syslog/syslog.conf ../syslog/syslogd.c ;; Do not run subst on its own manpage! ../doc/subst.1 inn-1.7.2/config/Makefile0100644000175100001440000000610206443103542013533 0ustar mdusers## $Revision: 1.31 $ SHELL = /bin/sh MAKE = make DESTDIR = D = $(DESTDIR) IFTRUE = @$(SHELL) ../iftrue.sh CONF = config.data FILE = files.list LIST = `grep -v '^;' <$(FILE)` BACKUP = backup.tar INTERPLIST = inncheck innlog.pl pgpverify scanspool innmail ## Pick your method of source control: RCS, SCCS, or NONE SRCCTL = NONE CHECKOUT = $(SRCCTL)-checkout CHECKIN = $(SRCCTL)-checkin ## If you use the script version of subst, and your version of sed chokes ## then get FSF sed and edit the next line as appropriate. #SED = -e /usr/gnu/bin/sed all: quiet # Yes, we really want to do nothing here! install: clobber clean: rm -f subst.tmp config.new subst substitutions rm -f all install lint profiled quiet: @$(MAKE) 'FILE=$(FILE)' substitutions interpreters | grep -v unchanged tags ctags: cp /dev/null tags lint profiled: cp /dev/null $@ substitutions: $(CHECKOUT) subst files.list $(CONF) -@rm -f ../*/substtmp.new ../*/substtmp.old @$(SHELL) ./checkconf.sh $(CONF) ./subst $(SED) -f $(CONF) $(LIST) $(IFTRUE) '$(SRCCTL) != NONE' '$(MAKE) $(CHECKIN)' interpreters: @echo "Fixing interpreter paths." perl fixinterps.pl -v -d ../samples $(INTERPLIST) RCS-checkout: co -l $(LIST) RCS-checkin: ci $(LIST) SCCS-checkout: sccs get -e $(LIST) SCCS-checkin: sccs delta $(LIST) NONE-checkout: -chmod u+w $(LIST) NONE-checkin: backup: $(IFTRUE) '-f $(BACKUP)' 'echo $(BACKUP) exists! ; exit 1' tar cf $(BACKUP) $(LIST) restore: $(IFTRUE) '! -f $(BACKUP)' 'echo No $(BACKUP)! ; exit 1' tar vxf $(BACKUP) $(LIST) config.data: config.dist $(IFTRUE) '-f config.new' 'echo config.new exists! ; exit 1' $(IFTRUE) '-f config.old' 'echo config.old exists! ; exit 1' $(IFTRUE) '! -f config.data' '$(MAKE) CLOBBER=YES SCRATCH' cat config.data config.dist >subst.tmp cp config.dist config.new ./subst $(SED) -f subst.tmp config.new -@rm -f subst.tmp @echo "Update config.old from config.new!" $(IFTRUE) '-f config.data' \ 'echo "Renaming config file to config.old"; mv config.data config.old' exit 1 ; SCRATCH: $(IFTRUE) '-z $(CLOBBER)' 'echo No way! ; exit 1' @echo 'You do not have a config.data file.' @echo 'Setting one up using the default file.' @echo 'You must edit this file, then remove config.new and config.old.' @echo 'Then restart the make.' cat config.dist >config.data subst: subst.c subst.sh -$(MAKE) c || $(MAKE) sh || rm -f subst $(IFTRUE) '! -f subst' 'echo Cannot make subst ; exit 1' c: @rm -f subst $(CC) -o subst subst.c sh: @rm -f subst cp subst.sh subst chmod +x subst sedtest: @echo 'This line should not be touched' >sedtest @echo '=()@>()=' >>sedtest @echo 'ERROR: do not use the SED version of subst' >>sedtest -$(SHELL) ./subst.sh $(SED) -f $(CONF) sedtest -@grep ERROR: sedtest $(IFTRUE) '! -s sedtest' 'echo Do not use sed ; rm sedtest ; exit 1' -@grep OK: sedtest rm -f sedtest .PRECIOUS: $(CONF) files.list ## Dependencies. Default list, below, is probably good enough. depend: Makefile $(SOURCES) makedepend $(DEFS) $(SOURCES) # DO NOT DELETE THIS LINE -- make depend depends on it. inn-1.7.2/CONTRIBUTORS0100644000175100001440000000551506443103542012515 0ustar mdusersThis file is somewhat incomplete due to it being taken from 1.5.1 and not 1.6 (didn't want to mention work done that's not in this release). -------------------------------------------------- The following is a list of the people who've helped out by contributing code. If anyone's name has been left out (probably), or if I've not correctly attributed something to you (ditto), please let me know (don't be embarrased). Rich Salz: Designed and wrote most of it. Bob Halley: Did the TCL extension. Christophe Wolfhugel: Did the Perl extension. Doug Needham: Made nnrpd spool if innd is unavailable. Made nnrpd handle the LIST SUBSCRIPTIONS command. Added the rebilding of control connections to innd (SIGUSR1 handling) Got inews to ask the nntp peer for moderator info instead of digging it out of a local file. David Lawrence: Did the hooks for PGP verificiation of control messages. John Stapleton: Wrote the poison newsgroup code ('@') for newsfeeds(5). Wrote the too-many-connects support ('-X -H -T' flags to innd). Landon Curt Noll: Wrote actsync, nntpsend, shrinkfile. John Levine: Wrote the '-e' support for expire (expire on shortest time). Matthias Urlichs: Made rnews recognise gzip compression. Made newsfeeds(5) take the 'Wp' flag. Stefan Petri: Did the original XBATCH support Russel Street: Did more XBATCH support. Alan Barrett: Did the work-limiter in the select loop to stop streaming from killing performance. Greg Patten: Wrote the perl innlog Craig Leres: Did work on dbz. Oliver Friedrichs tracked down a lot of potential buffer overflows. Jerry Aguirre Did a whole bunch stuff for INN (including crosspost and streaming). Provided a speed-up for channel processes. Forrest J. Cavalier III Did a lot of work cleaning up and removing bugs introduced by the fixes to the security holes. Dave Barr Managed the project after Rich couldn't do it any more. The following people helped above and beyond the call of duty with testing (provided patches, bug reports, suggestions etc): Paul Vixie, Robert Elz, Evan Champion, Robert Keller, Barry Bouwsma, markd@mira.net.au, Ollivier Robert, Kevin Jameson, Heiko W. Rupp, Fletcher Mattox, Matus Uhlar, Gabor Kiss, Joe Greco, Matthias Scheler, Richard Michael Todd, Fabien Tassin, Trevor Riley, Katsuhiro Kondou, Alex Bligh, J. Porter Clark, Alan Brown, Bert Hyman, Petter Nilsen, Gary E. Miller, Kim Culhan, Marc Baudoin, Neal Becker, Bjorn Knutsson, Stephen Marquard, Frederick Korz, Benedict Lofstedt, Dan Ellis, Joe Ramey, Odd Einar Aurbakken, Jon Lewis, Dan Riley, Peter Eriksson, Ken Lalonde, Sven Paulus, Koichi Mouri, J. Richard Sladkey, Trine Krogstad, Holger Burbach, Per Hedeland, Larry Rosenman, Andrew Burgess, Michael Brunnbauer, Mike Brudenell, Philippe Charnier, Karsten Thygesen, John Giannandrea, John Line, Philippe Michel inn-1.7.2/README.perl_hook0100644000175100001440000001167106443103542013476 0ustar mdusersThis is $Revision: 1.2 $ dated $Date: 1996/09/13 16:46:50 $. innd and nnrpd now support some amount of Perl filtering of articles received from another peer or from a newsreader. This code is based very heavily on work Christophe Wolfhugel did. He in turn was inspired by the existing TCL support. Send me () and not Christophe any bug reports, as I fiddled with the code, and am probably the cause of any problems. What you get with the Perl support is described in more detail below, but basically you can supply a perl subroutine that will be invoked on every article received by innd from a peer, or by nnrpd from a reader. The subroutine causes nnrpd or innd to accept or reject the article. This will be most useful for spam killing. To include Perl support you need to have version perl 5.003. Version 5.001 defintely doesn't work. 5.002 might, but hasn't been tried. Go to http://www.perl.com/CPAN for the latest Perl goodies. In config.dist there is a section (#17) devoted to Perl. You must set PERL_SUPPORT to DO and PERL_INC and PERL_LIB to the appropriate values for your system for the compilation to work properly. -------------------------------------------------- Innd: When innd starts it loads the file _PATH_PERL_STARTUP_INND, next it loads _PATH_PERL_FILTER_INND. Everytime, before _PATH_PERL_FILTER_INND is loaded, including the first time, if the perl subroutine ``filter_before_reload'' is defined, then it will be called with no arguments, and it is not expected to return any values. After the _PATH_PERL_FILTER_INND is loaded the routine ``filter_after_reload'' is executed in the same way. These two functions are normally defined in _PATH_PERL_STARTUP_INND. They could be used for doing things like flushing cached data to disk, or loading up a cache etc. Whenever ctlinnd is run with the command ``reload'' and the first argument ``filter.perl'' or ``all'', the filter file _PATH_PERL_FILTER_INND is reloaded with the before and after functions being run as just described. If the subroutine ``filter_art'' is defined after the file has been reloaded, then filtering is turned on. If is not defined, then filtering is turned of. Whenever ctlinnd is run with the command ``throttle'', or ``pause'' or ``go'', then the perl function ``filter_mode'' is called. It recives no arguments and returns no value. It has access to a global associative array called ``%mode'', which has three keyed values: 'Mode' ==> the current mode (``throttled'', ``paused'', or ``running'') 'NewMode' ==> the new mode. 'reason' ==> the reason given for the mode change. Whenever an article is received from a peer via IHAVE or TAKETHIS, and filtering is turned on, the perl subroutine ``filter_art'' is called. It receives no arguments and returns a single scalar value or the undefined value. It has access to a global associative array called ``%hdr'', which contains values for all standard headers with a non-null value of the article. The standard headers are: Approved, Control, Date, Distribution, Expires, From, Lines, Message-ID, Newsgroups, Path, Reply-To, Sender, Subject, Supersedes, Bytes, Also-Control, References For example: %hdr = ('Subject', 'MAKE MONEY FAST!!', 'From', 'Joe Spamer ', 'Date', '10 Sep 1996 15:32:28 UTC', 'Newsgroups', 'alt.test', 'Path', 'data.ramona.vix.com!gw.home.vix.com!not-for-mail', 'Organization', 'Spammers Anonymous', 'Lines' '5', 'Distribution', 'world' 'Message-ID', '<6.20232.842369548@home.octet.com.au>' ) If ``filter_art'' returns a null string (not a zero), then the article is accepted. If it returns a non-zero value, then it is rejected, and the value returned (typically a string) is used to log the reason why it was rejected. -------------------------------------------------- nnrpd: When nnrpd starts it load the file _PATH_PERL_FILTER_NNRPD. If the function ``filter_post'' is defined, then filtering is turned on. If it isn't, then filtering is turned off. When filtering is on, every article received via the POST command is given to the ``filter_post'' subroutine in exactly the same manner as for filter_art in innd. The return value must be a null string to accept the article, anything else will cause the article to be rejected and the reason sent back to the client will be the returned value of the ``filter_post'' function. -------------------------------------------------- Some notes: In the samples directory there are filter_inn.pl, filter_nnrpd.pl and startup_innd.pl, with some simplistic examples on how to use them. Note that all perl evaluation is done inside an implicit ``eval'', so calling die() will not kill the innd or nnrpd process, nor any other sort of syntax or functional error. You should always do 'perl -c -w file' before starting or reloading. If you change the file after innd is running, and then reload it, filtering wil be disabled if there was an error in the file. At which point you'll have to fix the file and reload it. inn-1.7.2/iftrue.sh0100755000175100001440000000105006443103542012460 0ustar mdusers#! /bin/sh ## $Revision: 1.3 $ ## Perform a test(1) and execute a command string if the test is true; ## otherwise exit 0. Usage: ## testit ## On some systems (those with a /bin/sh from BSD4.2), the following ## line in a Makefile will always fail: ## if [ ! -f x ] ; then echo No x -- stop. ; exit 1 ; else exit 0 ; fi case $# in 2) ;; *) echo "Can't perform test: wrong number of arguments." 1>&2 exit 1 ;; esac TEST="$1" COMMAND="$2" if eval "test ${TEST}" ; then eval "${COMMAND}" exit $? fi exit 0 inn-1.7.2/lib/0040755000175100001440000000000006443103542011400 5ustar mdusersinn-1.7.2/lib/defdist.c0100644000175100001440000000720006443103542013162 0ustar mdusers/* $Revision: 1.8 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include "libinn.h" #include "paths.h" #include "macros.h" typedef struct _DDENTRY { char *Pattern; char *Value; int Weight; } DDENTRY; struct _DDHANDLE { int Count; DDENTRY *Entries; DDENTRY *Current; }; typedef struct _DDHANDLE DDHANDLE; extern FILE *CA_listopen(); struct _DDHANDLE * DDstart(FromServer, ToServer) FILE *FromServer; FILE *ToServer; { DDHANDLE *h; DDENTRY *ep; FILE *F; char buff[BUFSIZ]; char *p; char *q; int i; char name[sizeof _PATH_TEMPACTIVE + 10]; /* Open the file. */ if ((F = fopen(_PATH_DISTPATS, "r")) != NULL) name[0] = '\0'; else { /* Not available locally; try remotely. */ if (FromServer == NULL || ToServer == NULL) /* We're probably nnrpd running on the server and the * file isn't installed. Oh well. */ return NULL; (void)strcpy(name, _PATH_TEMPACTIVE); (void)mktemp(name); if ((F = CA_listopen(name, FromServer, ToServer, "distrib.pats")) == NULL) return NULL; } /* Count lines. */ for (i = 0; fgets(buff, sizeof buff, F) != NULL; i++) continue; /* Allocate space for the handle. */ if ((h = NEW(DDHANDLE, 1)) == NULL) { i = errno; (void)fclose(F); if (name[0]) (void)unlink(name); errno = i; return NULL; } h->Count = 0; h->Current = NULL; if (i == 0) { return NULL ; } else if ((h->Entries = NEW(DDENTRY, i)) == NULL) { i = errno; DISPOSE(h); (void)fclose(F); if (name[0]) (void)unlink(name); errno = i; return NULL; } (void)fseek(F, (OFFSET_T)0, SEEK_SET); for (ep = h->Entries; fgets(buff, sizeof buff, F) != NULL; ) { if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; if (buff[0] == '\0' || buff[0] == '#') continue; if ((p = strchr(buff, ':')) == NULL || (q = strchr(p + 1, ':')) == NULL) continue; *p++ = '\0'; ep->Weight = atoi(buff); ep->Pattern = COPY(p); q = strchr(ep->Pattern, ':'); *q++ = '\0'; ep->Value = q; ep++; } h->Count = ep - h->Entries; (void)fclose(F); if (name[0]) (void)unlink(name); return h; } void DDcheck(h, group) DDHANDLE *h; char *group; { DDENTRY *ep; int i; int w; if (h == NULL || group == NULL) return; w = h->Current ? h->Current->Weight : -1; for (ep = h->Entries, i = h->Count; --i >= 0; ep++) if (ep->Weight > w && wildmat(group, ep->Pattern)) { h->Current = ep; w = ep->Weight; } } char * DDend(h) DDHANDLE *h; { static char NIL[] = ""; char *p; int i; DDENTRY *ep; if (h == NULL) { p = NIL; return COPY(p); } if (h->Current == NULL) p = NIL; else p = h->Current->Value; p = COPY(p); for (ep = h->Entries, i = h->Count; --i >= 0; ep++) DISPOSE(ep->Pattern); DISPOSE(h->Entries); DISPOSE(h); return p; } #if defined(TEST) int main(ac, av) int ac; char *av[]; { struct _DDHANDLE *h; char *p; FILE *FromServer; FILE *ToServer; char buff[SMBUF]; if (NNTPremoteopen(&FromServer, &ToServer, buff) < 0) { if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; if ((p = strchr(buff, '\r')) != NULL) *p = '\0'; if (buff[0]) (void)fprintf(stderr, "%s\n", buff); else perror("Can't connect"); exit(1); } if ((h = DDstart(FromServer, ToServer)) == NULL) perror("Init failed, proceeding anyway"); while ((p = *++av) != NULL) DDcheck(h, p); p = DDend(h); printf(">%s<\n", p); exit(0); /* NOTREACHED */ } #endif /* defined(TEST) */ inn-1.7.2/lib/inet_ntoa.c0100644000175100001440000000500206443103542013516 0ustar mdusers/* $Revision: 1.3 $ ** ** This file has been modified to get it to compile more easily ** on pre-4.4BSD systems. Rich $alz, January 1991. */ #include #include #include "configdata.h" #include "clibrary.h" /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)inet_ntoa.c 5.6 (Berkeley) 2/24/91"; #endif /* LIBC_SCCS and not lint */ /* * Convert network-format internet address * to base 256 d.d.d.d representation. */ #include #define UC(c) (((int)c) & 0xFF) char * inet_ntoa(in) struct in_addr in; { static char buff[18]; register char *p; p = (char *)∈ (void)sprintf(buff, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3])); return buff; } inn-1.7.2/lib/checkart.c0100644000175100001440000000065706443103542013335 0ustar mdusers/* $Revision: 1.2 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include "nntp.h" /* ** See if an article is longer than the NNTP line-length limits. */ int NNTPcheckarticle(p) register char *p; { register char *next; for (; p && *p; p = next) { if ((next = strchr(p, '\n')) == NULL) break; if (next - p > NNTP_STRLEN) return -1; } return 0; } inn-1.7.2/lib/memset.c0100644000175100001440000000336106443103542013036 0ustar mdusers/* $Revision: 1.3 $ ** ** This file has been modified to get it to compile more easily ** on pre-4.4BSD systems. Rich $alz, June 1991. */ #include #include #include "configdata.h" #include "clibrary.h" #define const /* NULL */ #define void char #define size_t int #define NULL 0 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms are permitted * provided that: (1) source distributions retain this entire copyright * notice and comment, and (2) distributions including binaries display * the following acknowledgement: ``This product includes software * developed by the University of California, Berkeley and its contributors'' * in the documentation or other materials provided with the distribution * and in all advertising materials mentioning features or use of this * software. Neither the name of the University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if 0 #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)memset.c 5.5 (Berkeley) 5/15/90"; #endif /* LIBC_SCCS and not lint */ #include #include #endif void * memset(dst, c, n) void *dst; register int c; register size_t n; { if (n != 0) { register char *d = dst; do *d++ = c; while (--n != 0); } return (dst); } inn-1.7.2/lib/gettime.c0100644000175100001440000000357606443103542013212 0ustar mdusers/* $Revision: 1.6 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include "libinn.h" int GetTimeInfo(Now) TIMEINFO *Now; { static time_t NextHour; static long LastTzone; struct tm *tm; int secondsUntilNextHour; #if defined(DO_HAVE_GETTIMEOFDAY) struct timeval tv; #endif /* defined(DO_HAVE_GETTIMEOFDAY) */ #if defined(DONT_HAVE_TM_GMTOFF) struct tm local; struct tm gmt; #endif /* !defined(DONT_HAVE_TM_GMTOFF) */ /* Get the basic time. */ #if defined(DO_HAVE_GETTIMEOFDAY) if (gettimeofday(&tv, (struct timezone *)NULL) == -1) return -1; Now->time = tv.tv_sec; Now->usec = tv.tv_usec; #else /* Can't check for -1 since that might be a time, I guess. */ (void)time(&Now->time); Now->usec = 0; #endif /* defined(DO_HAVE_GETTIMEOFDAY) */ /* Now get the timezone if the last time < HH:00:00 <= now for some HH. */ if (NextHour <= Now->time) { if ((tm = localtime(&Now->time)) == NULL) return -1; secondsUntilNextHour = 60 * (60 - tm->tm_min) - tm->tm_sec; #if defined(DONT_HAVE_TM_GMTOFF) /* To get the timezone, compare localtime with GMT. */ local = *tm; if ((tm = gmtime(&Now->time)) == NULL) return -1; gmt = *tm; /* Assume we are never more than 24 hours away. */ LastTzone = gmt.tm_yday - local.tm_yday; if (LastTzone > 1) LastTzone = -24; else if (LastTzone < -1) LastTzone = 24; else LastTzone *= 24; /* Scale in the hours and minutes; ignore seconds. */ LastTzone += gmt.tm_hour - local.tm_hour; LastTzone *= 60; LastTzone += gmt.tm_min - local.tm_min; #else LastTzone = (0 - tm->tm_gmtoff) / 60; #endif /* defined(DONT_HAVE_TM_GMTOFF) */ NextHour = Now->time + secondsUntilNextHour; } Now->tzone = LastTzone; return 0; } inn-1.7.2/lib/dbz.pch0100644000175100001440000006334706443103542012665 0ustar mdusersDBZ as distributed by CNEWS has a few bits of lint in it. They fall into the following categories: 1. There is code after return statements, like return(value); break; 2. If you turn off DBZDEBUG some fluff is left behind. 3. A couple of (void) casts should be added to fprintf calls since ferror is checked right after. 4. Use "clibrary.h" for many C library declarations, and the POINTER typedef found there. In addition, DBZ cannot be used with vfork. (Yes, I agree with all the other purists that vfork is a crock, but I'm a realist enough to recognize that it can get some major performance benefits if used in innd.) Applying this patch makes sure that any files that DBZ opens have the close-on-exec flag set. This patch also includes two performance enhancements by Rob Robertson . The first is the new dbzwritethrough() routine that makes the incore mode of DBZ use a write-through cache. The second is automatic calculation of the database tags; Craig Leres contributed dbztagmask() based on Rob's code. This patch also includes the option to memory-map the database using the mmap() call. This original version of that code was by David Robinson, formerly now (January, 1993). Apply the following diff by using the "patch" program. The Makefile will normally do this for you automatically. DBZ is great, and Jon and Henry (and the others mentioned in the source) deserve a lot of credit for it. *** ../dbz/dbz.c Mon Sep 16 10:06:10 1996 --- dbz.c Tue Sep 24 07:20:08 1996 *************** *** 12,17 **** --- 12,24 ---- Major reworking by Henry Spencer as part of the C News project. + Minor lint and CodeCenter (Saber) fluff removal by Rich $alz (March, 1991). + Non-portable CloseOnExec() calls added by Rich $alz (September, 1991). + Added "writethrough" and tagmask calculation code from + and by Rich $alz (December, 1992). + Merged in MMAP code by David Robinson, formerly + now (January, 1993). + These routines replace dbm as used by the usenet news software (it's not a full dbm replacement by any means). It's fast and simple. It contains no AT&T code. *************** *** 22,41 **** */ #include #include ! #include #include #include #ifndef __STDC__ extern int errno; #endif #include /* * #ifdef index. "LIA" = "leave it alone unless you know what you're doing". * - * FUNNYSEEKS SEEK_SET is not 0, get it from * INDEX_SIZE backward compatibility with old dbz; avoid using this * NMEMORY number of days of memory for use in sizing new table (LIA) * INCORE backward compatibility with old dbz; use dbzincore() instead --- 29,49 ---- */ + #include "configdata.h" #include #include ! #include #include #include #ifndef __STDC__ extern int errno; #endif #include + #include "clibrary.h" /* * #ifdef index. "LIA" = "leave it alone unless you know what you're doing". * * INDEX_SIZE backward compatibility with old dbz; avoid using this * NMEMORY number of days of memory for use in sizing new table (LIA) * INCORE backward compatibility with old dbz; use dbzincore() instead *************** *** 50,62 **** * MAXRUN length of run which shifts to next table (see below) (LIA) * OVERFLOW long-int arithmetic overflow must be avoided, will trap * NOBUFFER do not buffer hash-table i/o, B News locking is defective */ ! #ifdef FUNNYSEEKS ! #include ! #else ! #define SEEK_SET 0 #endif #ifdef OVERFLOW #include #endif --- 58,72 ---- * MAXRUN length of run which shifts to next table (see below) (LIA) * OVERFLOW long-int arithmetic overflow must be avoided, will trap * NOBUFFER do not buffer hash-table i/o, B News locking is defective + * MMAP Use SunOS style mmap() for efficient incore */ + /* SUPPRESS 530 *//* Empty body for statement */ + /* SUPPRESS 701 on free *//* Conflicting declaration */ ! #ifndef SEEK_SET ! #define SEEK_SET 0 #endif + #ifdef OVERFLOW #include #endif *************** *** 203,208 **** --- 213,236 ---- static void mybytemap(); static of_t bytemap(); + /* + * Using mmap() is a more efficent way of keeping the .pag file incore. On + * average, it cuts the number of system calls and buffer copies in half. + * It also allows one copy to be shared among many processes without + * consuming any extra resources. + */ + #ifdef MMAP + #include + #ifdef MAP_FILE + #define MAP__ARG (MAP_FILE | MAP_SHARED) + #else + #define MAP__ARG (MAP_SHARED) + #endif + #ifndef INCORE + #define INCORE + #endif + #endif + /* * For a program that makes many, many references to the database, it * is a large performance win to keep the table in core, if it will fit. *************** *** 228,233 **** --- 256,269 ---- #endif /* + * Write to filesystem even if incore? This replaces a single multi- + * megabyte write when doing a dbzsync with a multi-byte write each + * time an article is added. On most systems, this will give an overall + * performance boost. + */ + static int writethrough = 0; + + /* * Stdio buffer for .pag reads. Buffering more than about 16 does not help * significantly at the densities we try to maintain, and the much larger * buffers that most stdios default to are much more expensive to fill. *************** *** 298,316 **** * alternative (under most compilers) is to pack around 2K of unused * strings -- there's just no way to get rid of them. */ - static int debug; /* controlled by dbzdebug() */ #ifdef DBZDEBUG ! #define DEBUG(args) if (debug) { (void) printf args ; } #else #define DEBUG(args) ; #endif /* externals used */ extern char *malloc(); extern char *calloc(); extern void free(); /* ANSI C; some old implementations say int */ extern int atoi(); extern long atol(); /* misc. forwards */ static long hash(); --- 334,357 ---- * alternative (under most compilers) is to pack around 2K of unused * strings -- there's just no way to get rid of them. */ #ifdef DBZDEBUG ! static int debug; /* controlled by dbzdebug() */ ! #define DEBUG(args) if (debug) { (void) printf args ; } else #else #define DEBUG(args) ; #endif /* externals used */ + #if 0 + extern char *memcpy(); + extern char *memchr(); extern char *malloc(); extern char *calloc(); extern void free(); /* ANSI C; some old implementations say int */ + #endif /* 0 */ extern int atoi(); extern long atol(); + extern void CloseOnExec(); /* misc. forwards */ static long hash(); *************** *** 336,342 **** --- 377,385 ---- static of_t *corepag; /* incore version of .pag file, if any */ static FILE *bufpagf; /* well-buffered pagf, for incore rewrite */ static of_t *getcore(); + #ifndef MMAP static int putcore(); + #endif static int written; /* has a store() been done? */ /* *************** *** 391,399 **** default: DEBUG(("dbzfresh case map `%c' unknown\n", cmap)); return(-1); - break; } ! switch (tagmask) { case 0: /* default */ break; case 1: /* no tags */ --- 434,441 ---- default: DEBUG(("dbzfresh case map `%c' unknown\n", cmap)); return(-1); } ! switch ((int)tagmask) { case 0: /* default */ break; case 1: /* no tags */ *************** *** 418,424 **** if (fn == NULL) return(-1); f = fopen(fn, "w"); ! free(fn); if (f == NULL) { DEBUG(("dbzfresh: unable to write config\n")); return(-1); --- 460,466 ---- if (fn == NULL) return(-1); f = fopen(fn, "w"); ! free((POINTER)fn); if (f == NULL) { DEBUG(("dbzfresh: unable to write config\n")); return(-1); *************** *** 437,443 **** if (fn == NULL) return(-1); f = fopen(fn, "w"); ! free(fn); if (f == NULL) { DEBUG(("dbzfresh: unable to create/truncate .pag file\n")); return(-1); --- 479,485 ---- if (fn == NULL) return(-1); f = fopen(fn, "w"); ! free((POINTER)fn); if (f == NULL) { DEBUG(("dbzfresh: unable to create/truncate .pag file\n")); return(-1); *************** *** 522,527 **** --- 564,571 ---- register FILE *f; register int newtable; register of_t newsize; + struct stat sb; + register of_t m; if (pagf != NULL) { DEBUG(("dbzagain: database already open\n")); *************** *** 533,539 **** if (fn == NULL) return(-1); f = fopen(fn, "r"); ! free(fn); if (f == NULL) { DEBUG(("dbzagain: cannot open old .dir file\n")); return(-1); --- 577,583 ---- if (fn == NULL) return(-1); f = fopen(fn, "r"); ! free((POINTER)fn); if (f == NULL) { DEBUG(("dbzagain: cannot open old .dir file\n")); return(-1); *************** *** 545,550 **** --- 589,607 ---- return(-1); } + /* calculate tagging from old file */ + if (stat(oldname, &sb) != -1) { + for (m = 1, i = 0; m < sb.st_size; i++, m <<= 1) + continue; + + /* if we had more tags than the default, use the new data */ + if ((c.tagmask | c.tagenb) && m > (1 << TAGSHIFT)) { + c.tagshift = i; + c.tagmask = (~(unsigned long)0) >> (i + 1); + c.tagenb = (c.tagmask << 1) & ~c.tagmask; + } + } + /* tinker with it */ top = 0; newtable = 0; *************** *** 570,576 **** if (fn == NULL) return(-1); f = fopen(fn, "w"); ! free(fn); if (f == NULL) { DEBUG(("dbzagain: unable to write new .dir\n")); return(-1); --- 627,633 ---- if (fn == NULL) return(-1); f = fopen(fn, "w"); ! free((POINTER)fn); if (f == NULL) { DEBUG(("dbzagain: unable to write new .dir\n")); return(-1); *************** *** 587,593 **** if (fn == NULL) return(-1); f = fopen(fn, "w"); ! free(fn); if (f == NULL) { DEBUG(("dbzagain: unable to create/truncate .pag file\n")); return(-1); --- 644,650 ---- if (fn == NULL) return(-1); f = fopen(fn, "w"); ! free((POINTER)fn); if (f == NULL) { DEBUG(("dbzagain: unable to create/truncate .pag file\n")); return(-1); *************** *** 629,639 **** dirronly = 1; } else dirronly = 0; ! free(dirfname); if (dirf == NULL) { DEBUG(("dbminit: can't open .dir file\n")); return(-1); } /* open the .pag file */ pagfname = enstring(name, pag); --- 686,697 ---- dirronly = 1; } else dirronly = 0; ! free((POINTER)dirfname); if (dirf == NULL) { DEBUG(("dbminit: can't open .dir file\n")); return(-1); } + CloseOnExec((int)fileno(dirf), 1); /* open the .pag file */ pagfname = enstring(name, pag); *************** *** 647,653 **** if (pagf == NULL) { DEBUG(("dbminit: .pag open failed\n")); (void) fclose(dirf); ! free(pagfname); return(-1); } pagronly = 1; --- 705,711 ---- if (pagf == NULL) { DEBUG(("dbminit: .pag open failed\n")); (void) fclose(dirf); ! free((POINTER)pagfname); return(-1); } pagronly = 1; *************** *** 655,660 **** --- 713,720 ---- pagronly = 1; else pagronly = 0; + if (pagf != NULL) + CloseOnExec((int)fileno(pagf), 1); #ifdef NOBUFFER /* * B News does not do adequate locking on its database accesses. *************** *** 679,690 **** if (basefname == NULL) { (void) fclose(pagf); (void) fclose(dirf); ! free(pagfname); pagf = NULL; return(-1); } } else basefname = NULL; #ifdef _IOFBF if (basef != NULL) (void) setvbuf(basef, basebuf, _IOFBF, sizeof(basebuf)); --- 739,752 ---- if (basefname == NULL) { (void) fclose(pagf); (void) fclose(dirf); ! free((POINTER)pagfname); pagf = NULL; return(-1); } } else basefname = NULL; + if (basef != NULL) + CloseOnExec((int)fileno(basef), 1); #ifdef _IOFBF if (basef != NULL) (void) setvbuf(basef, basebuf, _IOFBF, sizeof(basebuf)); *************** *** 696,702 **** (void) fclose(basef); (void) fclose(pagf); (void) fclose(dirf); ! free(pagfname); pagf = NULL; errno = EDOM; /* kind of a kludge, but very portable */ return(-1); --- 758,764 ---- (void) fclose(basef); (void) fclose(pagf); (void) fclose(dirf); ! free((POINTER)pagfname); pagf = NULL; errno = EDOM; /* kind of a kludge, but very portable */ return(-1); *************** *** 714,726 **** s = (size_t)conf.tsize * SOF; if (incore && (of_t)(s/SOF) == conf.tsize) { bufpagf = fopen(pagfname, (pagronly) ? "rb" : "r+b"); ! if (bufpagf != NULL) corepag = getcore(bufpagf); } else { bufpagf = NULL; corepag = NULL; } ! free(pagfname); /* misc. setup */ crcinit(); --- 776,790 ---- s = (size_t)conf.tsize * SOF; if (incore && (of_t)(s/SOF) == conf.tsize) { bufpagf = fopen(pagfname, (pagronly) ? "rb" : "r+b"); ! if (bufpagf != NULL) { corepag = getcore(bufpagf); + CloseOnExec((int)fileno(bufpagf), 1); + } } else { bufpagf = NULL; corepag = NULL; } ! free((POINTER)pagfname); /* misc. setup */ crcinit(); *************** *** 775,788 **** ret = -1; } if (corepag != NULL) ! free((char *)corepag); corepag = NULL; if (fclose(basef) == EOF) { DEBUG(("dbmclose: fclose(basef) failed\n")); ret = -1; } if (basefname != NULL) ! free(basefname); basef = NULL; pagf = NULL; if (fclose(dirf) == EOF) { --- 839,859 ---- ret = -1; } if (corepag != NULL) ! #ifdef MMAP ! if (munmap((MMAP_PTR) corepag, (int)conf.tsize * SOF) == -1) { ! DEBUG(("dbmclose: munmap failed\n")); ! ret = -1; ! } ! #else ! free((POINTER)corepag); ! #endif corepag = NULL; if (fclose(basef) == EOF) { DEBUG(("dbmclose: fclose(basef) failed\n")); ret = -1; } if (basefname != NULL) ! free((POINTER)basefname); basef = NULL; pagf = NULL; if (fclose(dirf) == EOF) { *************** *** 809,820 **** if (!written) return(0); ! if (corepag != NULL) { if (putcore(corepag, bufpagf) < 0) { DEBUG(("dbzsync: putcore failed\n")); ret = -1; } } if (!conf.olddbz) if (putconf(dirf, &conf) < 0) ret = -1; --- 880,893 ---- if (!written) return(0); ! #ifndef MMAP ! if (corepag != NULL && !writethrough) { if (putcore(corepag, bufpagf) < 0) { DEBUG(("dbzsync: putcore failed\n")); ret = -1; } } + #endif if (!conf.olddbz) if (putconf(dirf, &conf) < 0) ret = -1; *************** *** 922,928 **** DEBUG(("fetch: seek failed\n")); return(output); } ! if (fread(buffer, 1, keysize, basef) != keysize) { DEBUG(("fetch: read failed\n")); return(output); } --- 995,1001 ---- DEBUG(("fetch: seek failed\n")); return(output); } ! if (fread((POINTER)buffer, 1, keysize, basef) != keysize) { DEBUG(("fetch: read failed\n")); return(output); } *************** *** 932,938 **** (void) mapcase(buffer, buffer, keysize); DEBUG(("fetch: buffer (%s) looking for (%s) size = %d\n", buffer, key.dptr, keysize)); ! if (memcmp(key.dptr, buffer, cmplen) == 0 && (*sepp == conf.fieldsep || *sepp == '\0')) { /* we found it */ output.dptr = (char *)&key_ptr; --- 1005,1011 ---- (void) mapcase(buffer, buffer, keysize); DEBUG(("fetch: buffer (%s) looking for (%s) size = %d\n", buffer, key.dptr, keysize)); ! if (memcmp((POINTER)key.dptr, (POINTER)buffer, cmplen) == 0 && (*sepp == conf.fieldsep || *sepp == '\0')) { /* we found it */ output.dptr = (char *)&key_ptr; *************** *** 965,976 **** DEBUG(("latebase: still can't open base\n")); } else { DEBUG(("latebase: late open succeeded\n")); ! free(basefname); basefname = NULL; #ifdef _IOFBF (void) setvbuf(it, basebuf, _IOFBF, sizeof(basebuf)); #endif } return(it); } --- 1038,1051 ---- DEBUG(("latebase: still can't open base\n")); } else { DEBUG(("latebase: late open succeeded\n")); ! free((POINTER)basefname); basefname = NULL; #ifdef _IOFBF (void) setvbuf(it, basebuf, _IOFBF, sizeof(basebuf)); #endif } + if (it != NULL) + CloseOnExec((int)fileno(it), 1); return(it); } *************** *** 1034,1040 **** } /* copy the value in to ensure alignment */ ! (void) memcpy((char *)&value, data.dptr, SOF); DEBUG(("store: (%s, %ld)\n", key.dptr, (long)value)); if (!okayvalue(value)) { DEBUG(("store: reserved bit or overflow in 0x%lx\n", value)); --- 1109,1115 ---- } /* copy the value in to ensure alignment */ ! (void) memcpy((POINTER)&value, (POINTER)data.dptr, SOF); DEBUG(("store: (%s, %ld)\n", key.dptr, (long)value)); if (!okayvalue(value)) { DEBUG(("store: reserved bit or overflow in 0x%lx\n", value)); *************** *** 1062,1072 **** --- 1137,1187 ---- { register int old = incore; + #ifndef MMAP incore = value; + #endif + return(old); + } + + /* + - dbzwritethrough - write through the pag file in core + */ + int /* old setting */ + dbzwritethrough(value) + int value; + { + register int old = writethrough; + + writethrough = value; return(old); } /* + - dbztagmask - calculate the correct tagmask for the given base file size + */ + long + dbztagmask(size) + register long size; + { + register long m; + register long tagmask; + register int i; + + if (size <= 0) + return(0L); /* silly size */ + + for (m = 1, i = 0; m < size; i++, m <<= 1) + continue; + + if (m < (1 << TAGSHIFT)) + return(0L); /* not worth tagging */ + + tagmask = (~(unsigned long)0) >> (i + 1); + tagmask = tagmask << i; + return(tagmask); + } + + /* - getconf - get configuration from .dir file */ static int /* 0 success, -1 failure */ *************** *** 1107,1113 **** if (getno(df, &err) != dbzversion) err = -1; cp->tsize = getno(df, &err); ! cp->fieldsep = getno(df, &err); while ((c = getc(df)) == ' ') continue; cp->casemap = c; --- 1222,1228 ---- if (getno(df, &err) != dbzversion) err = -1; cp->tsize = getno(df, &err); ! cp->fieldsep = (int)getno(df, &err); while ((c = getc(df)) == ' ') continue; cp->casemap = c; *************** *** 1124,1129 **** --- 1239,1245 ---- cp->bytemap[i] = getno(df, &err); if (getc(df) != '\n') err = -1; + #ifdef DBZDEBUG DEBUG(("size %ld, sep %d, cmap %c, tags 0x%lx/0x%lx<<%d, ", cp->tsize, cp->fieldsep, cp->casemap, cp->tagenb, cp->tagmask, cp->tagshift)); *************** *** 1132,1137 **** --- 1248,1254 ---- DEBUG((" %d", cp->bytemap[i])); } DEBUG(("\n")); + #endif /* second line, the usages */ for (i = 0; i < NUSEDS; i++) *************** *** 1201,1214 **** DEBUG(("fseek failure in putconf\n")); ret = -1; } ! fprintf(f, "dbz %d %ld %d %c %ld %ld %d %d", dbzversion, cp->tsize, cp->fieldsep, cp->casemap, cp->tagenb, cp->tagmask, cp->tagshift, cp->valuesize); for (i = 0; i < cp->valuesize; i++) ! fprintf(f, " %d", cp->bytemap[i]); ! fprintf(f, "\n"); for (i = 0; i < NUSEDS; i++) ! fprintf(f, "%ld%c", cp->used[i], (i < NUSEDS-1) ? ' ' : '\n'); (void) fflush(f); if (ferror(f)) --- 1318,1331 ---- DEBUG(("fseek failure in putconf\n")); ret = -1; } ! (void) fprintf(f, "dbz %d %ld %d %c %ld %ld %d %d", dbzversion, cp->tsize, cp->fieldsep, cp->casemap, cp->tagenb, cp->tagmask, cp->tagshift, cp->valuesize); for (i = 0; i < cp->valuesize; i++) ! (void) fprintf(f, " %d", cp->bytemap[i]); ! (void) fprintf(f, "\n"); for (i = 0; i < NUSEDS; i++) ! (void) fprintf(f, "%ld%c", cp->used[i], (i < NUSEDS-1) ? ' ' : '\n'); (void) fflush(f); if (ferror(f)) *************** *** 1229,1255 **** register size_t i; register size_t nread; register char *it; it = malloc((size_t)conf.tsize * SOF); if (it == NULL) { DEBUG(("getcore: malloc failed\n")); return(NULL); } ! nread = fread(it, SOF, (size_t)conf.tsize, f); if (ferror(f)) { DEBUG(("getcore: read failed\n")); ! free(it); return(NULL); } p = (of_t *)it + nread; i = (size_t)conf.tsize - nread; while (i-- > 0) *p++ = VACANT; return((of_t *)it); } /* - putcore - try to rewrite an in-core table */ --- 1346,1401 ---- register size_t i; register size_t nread; register char *it; + #ifdef MMAP + struct stat st; + if (fstat(fileno(f), &st) == -1) { + DEBUG(("getcore: fstat failed\n")); + return(NULL); + } + if (((size_t)conf.tsize * SOF) > st.st_size) { + /* file too small; extend it */ + if (ftruncate((int)fileno(f), conf.tsize * SOF) == -1) { + DEBUG(("getcore: ftruncate failed\n")); + return(NULL); + } + } + it = mmap((caddr_t)0, (size_t)conf.tsize * SOF, + pagronly ? PROT_READ : PROT_WRITE | PROT_READ, MAP__ARG, + (int)fileno(f), (off_t)0); + if (it == (char *)-1) { + DEBUG(("getcore: mmap failed\n")); + return(NULL); + } + #ifdef MC_ADVISE + /* not present in all versions of mmap() */ + madvise(it, (size_t)conf.tsize * SOF, MADV_RANDOM); + #endif + #else it = malloc((size_t)conf.tsize * SOF); if (it == NULL) { DEBUG(("getcore: malloc failed\n")); return(NULL); } ! nread = fread((POINTER)it, SOF, (size_t)conf.tsize, f); if (ferror(f)) { DEBUG(("getcore: read failed\n")); ! free((POINTER)it); return(NULL); } + /* NOSTRICT *//* Possible pointer alignment problem */ p = (of_t *)it + nread; i = (size_t)conf.tsize - nread; while (i-- > 0) *p++ = VACANT; + #endif + /* NOSTRICT *//* Possible pointer alignment problem */ return((of_t *)it); } + #ifndef MMAP /* - putcore - try to rewrite an in-core table */ *************** *** 1262,1271 **** DEBUG(("fseek failure in putcore\n")); return(-1); } ! (void) fwrite((char *)tab, SOF, (size_t)conf.tsize, f); (void) fflush(f); return((ferror(f)) ? -1 : 0); } /* - start - set up to start or restart a search --- 1408,1418 ---- DEBUG(("fseek failure in putcore\n")); return(-1); } ! (void) fwrite((POINTER)tab, SOF, (size_t)conf.tsize, f); (void) fflush(f); return((ferror(f)) ? -1 : 0); } + #endif /* - start - set up to start or restart a search *************** *** 1343,1349 **** } /* read it */ ! if (fread((char *)&val, sizeof(val), 1, pagf) == 1) value = MAPIN(val); else if (ferror(pagf)) { DEBUG(("search: read failed\n")); --- 1490,1496 ---- } /* read it */ ! if (fread((POINTER)&val, sizeof(val), 1, pagf) == 1) value = MAPIN(val); else if (ferror(pagf)) { DEBUG(("search: read failed\n")); *************** *** 1425,1443 **** if (corepag != NULL && place < conf.tsize) { corepag[place] = value; DEBUG(("set: incore\n")); return(0); } /* seek to spot */ pagpos = -1; /* invalidate position memory */ ! if (fseek(pagf, place * SOF, SEEK_SET) != 0) { DEBUG(("set: seek failed\n")); sp->aborted = 1; return(-1); } /* write in data */ ! if (fwrite((char *)&value, SOF, 1, pagf) != 1) { DEBUG(("set: write failed\n")); sp->aborted = 1; return(-1); --- 1572,1595 ---- if (corepag != NULL && place < conf.tsize) { corepag[place] = value; DEBUG(("set: incore\n")); + #ifdef MMAP return(0); + #else + if (!writethrough) + return(0); + #endif } /* seek to spot */ pagpos = -1; /* invalidate position memory */ ! if (fseek(pagf, (of_t)(place * SOF), SEEK_SET) != 0) { DEBUG(("set: seek failed\n")); sp->aborted = 1; return(-1); } /* write in data */ ! if (fwrite((POINTER)&value, SOF, 1, pagf) != 1) { DEBUG(("set: write failed\n")); sp->aborted = 1; return(-1); *************** *** 1474,1479 **** --- 1626,1632 ---- u.o = 1; for (ntodo = (int)SOF; ntodo > 0; ntodo--) { for (i = 0; i < SOF; i++) + /* SUPPRESS 112 *//* Retrieving char where long is stored */ if (u.c[i] != 0) break; if (i == SOF) { *************** *** 1485,1490 **** --- 1638,1644 ---- } DEBUG(("mybytemap: byte %d\n", i)); *--mp = i; + /* SUPPRESS 112 *//* Retrieving char where long is stored */ while (u.c[i] != 0) u.o <<= 1; } *************** *** 1728,1747 **** switch (conf.casemap) { case '0': /* unmapped, sensible */ return(NULL); - break; case 'C': /* C News, RFC 822 conformant (approx.) */ ! p = memchr(s, '@', siz); if (p == NULL) /* no local/domain split */ return(NULL); /* assume all local */ ! else if (p - (s+1) == plen && CISTREQN(s+1, post, plen)) { /* crazy -- "postmaster" is case-insensitive */ return(s); ! } else ! return(p); ! break; case '=': /* 2.11, neither sensible nor conformant */ return(s); /* all case-insensitive */ - break; } DEBUG(("cipoint: unknown case mapping `%c'\n", conf.casemap)); --- 1882,1898 ---- switch (conf.casemap) { case '0': /* unmapped, sensible */ return(NULL); case 'C': /* C News, RFC 822 conformant (approx.) */ ! p = memchr((POINTER)s, '@', siz); if (p == NULL) /* no local/domain split */ return(NULL); /* assume all local */ ! if (p - (s+1) == plen && CISTREQN(s+1, post, plen)) { /* crazy -- "postmaster" is case-insensitive */ return(s); ! } ! return(p); case '=': /* 2.11, neither sensible nor conformant */ return(s); /* all case-insensitive */ } DEBUG(("cipoint: unknown case mapping `%c'\n", conf.casemap)); *************** *** 1751,1766 **** /* - dbzdebug - control dbz debugging at run time */ int /* old value */ dbzdebug(value) int value; { - #ifdef DBZDEBUG register int old = debug; debug = value; return(old); - #else - return(-1); - #endif } --- 1902,1915 ---- /* - dbzdebug - control dbz debugging at run time */ + #ifdef DBZDEBUG int /* old value */ dbzdebug(value) int value; { register int old = debug; debug = value; return(old); } + #endif inn-1.7.2/lib/strchr.c0100644000175100001440000000317106443103542013050 0ustar mdusers/* $Revision: 1.3 $ ** ** This file has been modified to get it to compile more easily ** on pre-4.4BSD systems. Rich $alz, June 1991. */ #include #include #include "configdata.h" #include "clibrary.h" #define NULL 0 #define STRCHR /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if 0 #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)index.c 5.6 (Berkeley) 6/23/90"; #endif /* LIBC_SCCS and not lint */ #include #include #endif char * #ifdef STRCHR strchr(p, ch) #else index(p, ch) #endif register char *p, ch; { for (;; ++p) { if (*p == ch) return(p); if (!*p) return((char *)NULL); } /* NOTREACHED */ } inn-1.7.2/lib/getopt.c0100644000175100001440000000307506443103542013050 0ustar mdusers/* $Revision: 1.2 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #define ERR(s, c) \ if (opterr) { \ char buff[2]; \ buff[0] = c; buff[1] = '\n'; \ (void)write(2, av[0], strlen(av[0])); \ (void)write(2, s, strlen(s)); \ (void)write(2, buff, 2); \ } int opterr = 1; int optind = 1; int optopt; char *optarg; /* ** Return options and their values from the command line. ** This comes from the AT&T public-domain getopt published in mod.sources ** (i.e., comp.sources.unix before the great Usenet renaming). */ int getopt(ac, av, opts) int ac; char *av[]; char *opts; { extern char *strchr(); static int i = 1; char *p; /* Move to next value from argv? */ if (i == 1) { if (optind >= ac || av[optind][0] != '-' || av[optind][1] == '\0') return EOF; if (strcmp(av[optind], "--") == 0) { optind++; return EOF; } } /* Get next option character. */ if ((optopt = av[optind][i]) == ':' || (p = strchr(opts, optopt)) == NULL) { ERR(": illegal option -- ", optopt); if (av[optind][++i] == '\0') { optind++; i = 1; } return '?'; } /* Snarf argument? */ if (*++p == ':') { if (av[optind][i + 1] != '\0') optarg = &av[optind++][i + 1]; else { if (++optind >= ac) { ERR(": option requires an argument -- ", optopt); i = 1; return '?'; } optarg = av[optind++]; } i = 1; } else { if (av[optind][++i] == '\0') { i = 1; optind++; } optarg = NULL; } return optopt; } inn-1.7.2/lib/memcpy.c0100644000175100001440000000717706443103542013047 0ustar mdusers/* $Revision: 1.4 $ ** ** This file has been modified to get it to compile more easily ** on pre-4.4BSD systems. Rich $alz, June 1991. */ #include #include #include "configdata.h" #include "clibrary.h" #define const /* NULL */ #define void char #define size_t int #define NULL 0 #define MEMCOPY /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if 0 #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)bcopy.c 5.8 (Berkeley) 6/23/90"; #endif /* LIBC_SCCS and not lint */ #include #include #endif /* * sizeof(word) MUST BE A POWER OF TWO * SO THAT wmask BELOW IS ALL ONES */ typedef int word; /* "word" used for optimal copy speed */ #define wsize sizeof(word) #define wmask (wsize - 1) /* * Copy a block of memory, handling overlap. * This is the routine that actually implements * (the portable versions of) bcopy, memcpy, and memmove. */ #ifdef MEMCOPY void * memcpy(dst0, src0, length) #else #ifdef MEMMOVE void * memmove(dst0, src0, length) #else void bcopy(src0, dst0, length) #endif #endif char *dst0; const char *src0; register size_t length; { register char *dst = dst0; register const char *src = src0; register size_t t; if (length == 0 || dst == src) /* nothing to do */ goto retval; /* * Macros: loop-t-times; and loop-t-times, t>0 */ #define TLOOP(s) if (t) TLOOP1(s) #define TLOOP1(s) do { s; } while (--t) if ((unsigned long)dst < (unsigned long)src) { /* * Copy forward. */ t = (int)src; /* only need low bits */ if ((t | (int)dst) & wmask) { /* * Try to align operands. This cannot be done * unless the low bits match. */ if ((t ^ (int)dst) & wmask || length < wsize) t = length; else t = wsize - (t & wmask); length -= t; TLOOP1(*dst++ = *src++); } /* * Copy whole words, then mop up any trailing bytes. */ t = length / wsize; TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize); t = length & wmask; TLOOP(*dst++ = *src++); } else { /* * Copy backwards. Otherwise essentially the same. * Alignment works as before, except that it takes * (t&wmask) bytes to align, not wsize-(t&wmask). */ src += length; dst += length; t = (int)src; if ((t | (int)dst) & wmask) { if ((t ^ (int)dst) & wmask || length <= wsize) t = length; else t &= wmask; length -= t; TLOOP1(*--dst = *--src); } t = length / wsize; TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src); t = length & wmask; TLOOP(*--dst = *--src); } retval: #ifdef MEMCOPY return(dst0); #else #ifdef MEMMOVE return(dst0); #else return; #endif #endif } inn-1.7.2/lib/lockfile.c0100644000175100001440000000232606443103542013334 0ustar mdusers/* $Revision: 1.5 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #if defined(LOCK_NONE) #include #endif /* defined(LOCK_NONE) */ #if defined(LOCK_FLOCK) #include #endif /* defined(LOCK_FLOCK) */ #if defined(LOCK_LOCKF) #if defined(DO_HAVE_UNISTD) #include #endif /* defined(DO_HAVE_UNISTD) */ #include #endif /* defined(LOCK_LOCKF) */ #if defined(LOCK_FCNTL) #include #if !defined(SEEK_SET) #define SEEK_SET 0 #endif /* !defined(SEEK_SET) */ #endif /* defined(LOCK_FCNTL) */ /* ** Try to lock a file descriptor. */ int LockFile(fd, Block) int fd; BOOL Block; { #if defined(LOCK_NONE) struct stat Sb; return fstat(fd, &Sb); #endif /* defined(LOCK_NONE) */ #if defined(LOCK_FLOCK) return flock(fd, Block ? LOCK_EX : LOCK_EX | LOCK_NB); #endif /* defined(LOCK_FLOCK) */ #if defined(LOCK_LOCKF) return lockf(fd, Block ? F_LOCK : F_TLOCK, 0L); #endif /* defined(LOCK_LOCKF) */ #if defined(LOCK_FCNTL) struct flock fl; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; return fcntl(fd, Block ? F_SETLKW : F_SETLK, &fl); #endif /* defined(LOCK_FCNTL) */ } inn-1.7.2/lib/xfopena.c0100644000175100001440000000072406443103542013204 0ustar mdusers/* $Revision: 1.2 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include /* ** Open a file in append mode. Since not all fopen's set the O_APPEND ** flag, we do it by hand. */ FILE * xfopena(p) char *p; { int fd; /* We can't trust stdio to really use O_APPEND, so open, then fdopen. */ fd = open(p, O_WRONLY | O_APPEND | O_CREAT, 0666); return fd >= 0 ? fdopen(fd, "a") : NULL; } inn-1.7.2/lib/cleanfrom.c0100644000175100001440000000172606443103542013515 0ustar mdusers/* $Revision: 1.5 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include "macros.h" #define LPAREN '(' #define RPAREN ')' /* ** Clean up a from line, making the following transformations: ** address address ** address (stuff) address ** stuff

address */ void HeaderCleanFrom(from) char *from; { register char *p; register char *end; /* Do the equivalent of sed's "1q" */ if ((p = strchr(from, '\n')) != NULL) *p = '\0'; /* Do pretty much the equivalent of sed's "s/ (.*)//"; doesn't * work for "(save (delete this)" but that's okay. */ if ((p = strchr(from, LPAREN)) && p > from && *--p == ' ' && (end = strrchr(p, RPAREN))) { while (*++end) *p++ = *end; *p = '\0'; } /* Do the equivalent of sed's "s/.*<\(.*\)>/\1/" */ if ((p = strrchr(from, '<')) && (end = strrchr(p, '>'))) { while (++p < end) *from++ = *p; *from = '\0'; } } inn-1.7.2/lib/memchr.c0100644000175100001440000000350306443103542013015 0ustar mdusers/* $Revision: 1.4 $ ** ** This file has been modified to get it to compile more easily ** on pre-4.4BSD systems. Rich $alz, June 1991. */ #include #include #include "configdata.h" #include "clibrary.h" #define const /* NULL */ #define void char #define size_t int #define NULL 0 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms are permitted * provided that: (1) source distributions retain this entire copyright * notice and comment, and (2) distributions including binaries display * the following acknowledgement: ``This product includes software * developed by the University of California, Berkeley and its contributors'' * in the documentation or other materials provided with the distribution * and in all advertising materials mentioning features or use of this * software. Neither the name of the University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if 0 #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)memchr.c 5.5 (Berkeley) 5/15/90"; #endif /* LIBC_SCCS and not lint */ #include #include #endif void * memchr(s, c, n) const void *s; register unsigned char c; register size_t n; { if (n != 0) { register const unsigned char *p = (unsigned char *)s; do { if (*p++ == c) return ((void *)(p - 1)); } while (--n != 0); } return (NULL); } inn-1.7.2/lib/wildmat.c0100644000175100001440000001134706443103542013210 0ustar mdusers/* $Revision: 1.10 $ ** ** Do shell-style pattern matching for ?, \, [], and * characters. ** Might not be robust in face of malformed patterns; e.g., "foo[a-" ** could cause a segmentation violation. It is 8bit clean. ** ** Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986. ** Rich $alz is now . ** April, 1991: Replaced mutually-recursive calls with in-line code ** for the star character. ** ** Special thanks to Lars Mathiesen for the ABORT code. ** This can greatly speed up failing wildcard patterns. For example: ** pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-* ** text 1: -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1 ** text 2: -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1 ** Text 1 matches with 51 calls, while text 2 fails with 54 calls. Without ** the ABORT code, it takes 22310 calls to fail. Ugh. The following ** explanation is from Lars: ** The precondition that must be fulfilled is that DoMatch will consume ** at least one character in text. This is true if *p is neither '*' nor ** '\0'.) The last return has ABORT instead of FALSE to avoid quadratic ** behaviour in cases like pattern "*a*b*c*d" with text "abcxxxxx". With ** FALSE, each star-loop has to run to the end of the text; with ABORT ** only the last one does. ** ** Once the control of one instance of DoMatch enters the star-loop, that ** instance will return either TRUE or ABORT, and any calling instance ** will therefore return immediately after (without calling recursively ** again). In effect, only one star-loop is ever active. It would be ** possible to modify the code to maintain this context explicitly, ** eliminating all recursive calls at the cost of some complication and ** loss of clarity (and the ABORT stuff seems to be unclear enough by ** itself). I think it would be unwise to try to get this into a ** released version unless you have a good test data base to try it out ** on. */ #include #include #include "configdata.h" #include "clibrary.h" #define TRUE 1 #define FALSE 0 #define ABORT -1 /* What character marks an inverted character class? */ #define NEGATE_CLASS '^' /* Is "*" a common pattern? */ #define OPTIMIZE_JUST_STAR /* Do tar(1) matching rules, which ignore a trailing slash? */ #undef MATCH_TAR_PATTERN /* ** Match text and p, return TRUE, FALSE, or ABORT. */ static int DoMatch(text, p) register char *text; register char *p; { register int last; register int matched; register int reverse; for ( ; *p; text++, p++) { if (*text == '\0' && *p != '*') return ABORT; switch (*p) { case '\\': /* Literal match with following character. */ p++; /* FALLTHROUGH */ default: if (*text != *p) return FALSE; continue; case '?': /* Match anything. */ continue; case '*': while (*++p == '*') /* Consecutive stars act just like one. */ continue; if (*p == '\0') /* Trailing star matches everything. */ return TRUE; while (*text) if ((matched = DoMatch(text++, p)) != FALSE) return matched; return ABORT; case '[': reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE; if (reverse) /* Inverted character class. */ p++; matched = FALSE; if (p[1] == ']' || p[1] == '-') if (*++p == *text) matched = TRUE; for (last = *p; *++p && *p != ']'; last = *p) /* This next line requires a good C compiler. */ if (*p == '-' && p[1] != ']' ? *text <= *++p && *text >= last : *text == *p) matched = TRUE; if (matched == reverse) return FALSE; continue; } } #ifdef MATCH_TAR_PATTERN if (*text == '/') return TRUE; #endif /* MATCH_TAR_ATTERN */ return *text == '\0'; } /* ** User-level routine. Returns TRUE or FALSE. */ int wildmat(text, p) char *text; char *p; { #ifdef OPTIMIZE_JUST_STAR if (p[0] == '*' && p[1] == '\0') return TRUE; #endif /* OPTIMIZE_JUST_STAR */ return DoMatch(text, p) == TRUE; } #if defined(TEST) /* Yes, we use gets not fgets. Sue me. */ extern char *gets(); int main() { char p[80]; char text[80]; printf("Wildmat tester. Enter pattern, then strings to test.\n"); printf("A blank line gets prompts for a new pattern; a blank pattern\n"); printf("exits the program.\n"); for ( ; ; ) { printf("\nEnter pattern: "); (void)fflush(stdout); if (gets(p) == NULL || p[0] == '\0') break; for ( ; ; ) { printf("Enter text: "); (void)fflush(stdout); if (gets(text) == NULL) exit(0); if (text[0] == '\0') /* Blank line; go back and get a new pattern. */ break; printf(" %s\n", wildmat(text, p) ? "YES" : "NO"); } } exit(0); /* NOTREACHED */ } #endif /* defined(TEST) */ inn-1.7.2/lib/radix32.c0100644000175100001440000000226506443103542013022 0ustar mdusers/* $Revision: 1.4 $ ** ** Radix-32 strings divide a number into five-bit nibbles and use the ** alphabet 0..9a..v to represent 0..32. */ #include #include #include "configdata.h" #include "clibrary.h" #include static char ALPHABET[] = "0123456789abcdefghijklmnopqrstuv"; /* ** Turn a number into a Radix-32 string. Assume the number fits into ** 32 bits. */ void Radix32(l, buff) register unsigned long l; register char *buff; { register char *p; register int i; char temp[10]; /* Simple sanity checks. */ if ((l &= 0xFFFFFFFFL) == 0) { *buff++ = ALPHABET[0]; *buff = '\0'; return; } /* Format the string, in reverse. */ for (p = temp; l; l >>= 5) *p++ = ALPHABET[(int)(l & 037)]; /* Reverse it. */ for (i = p - temp; --i >= 0; ) *buff++ = *--p; *buff = '\0'; } #if 0 /* ** Return a Radix-32 string as a number, or ~0 on error. */ unsigned long Decode32(p) register char *p; { register unsigned long l; register char *cp; for (l = 0; *p; p++) { if ((cp = strchr(ALPHABET, *p)) == NULL) return ~0; l = (l << 6) + cp - ALPHABET; } return l; } #endif /* 0 */ inn-1.7.2/lib/getmodaddr.c0100644000175100001440000000735006443103542013660 0ustar mdusers/* $Revision: 1.13 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include #include "paths.h" #include "libinn.h" #include "macros.h" #include "nntp.h" STATIC char GMApathname[sizeof _PATH_TEMPMODERATORS]; STATIC FILE *GMAfp; /* ** Close the file opened by GMAlistopen. */ void GMAclose() { if (GMAfp) { (void)fclose(GMAfp); GMAfp = NULL; } if (GMApathname[0]) { (void)unlink(GMApathname); GMApathname[0] = '\0'; } } /* ** Internal library routine. */ FILE * GMA_listopen(pathname, FromServer, ToServer, request) char *pathname; FILE *FromServer; FILE *ToServer; char *request; { char buff[BUFSIZ]; char *p; int oerrno; FILE *F; (void)unlink(pathname); if ((F = fopen(pathname, "w")) == NULL) return NULL; /* Send a LIST command to and capture the output. */ if (request == NULL) (void)fprintf(ToServer, "list moderators\r\n"); else (void)fprintf(ToServer, "list %s\r\n", request); (void)fflush(ToServer); /* Get the server's reply to our command. */ if (fgets(buff, sizeof buff, FromServer) == NULL || !EQn(buff, NNTP_LIST_FOLLOWS, STRLEN(NNTP_LIST_FOLLOWS))) { oerrno = errno; GMAclose(); errno = oerrno; return NULL; } /* Slurp up the rest of the response. */ while (fgets(buff, sizeof buff, FromServer) != NULL) { if ((p = strchr(buff, '\r')) != NULL) *p = '\0'; if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; if (buff[0] == '.' && buff[1] == '\0') { if (ferror(F) || fflush(F) == EOF || fclose(F) == EOF) break; return fopen(pathname, "r"); } (void)fprintf(F, "%s\n", buff); } /* Ran out of input before finding the terminator; quit. */ oerrno = errno; (void)fclose(F); GMAclose(); errno = oerrno; return NULL; } /* ** Read the moderators file, looking for a moderator. */ char * GetModeratorAddress(FromServer, ToServer, group) FILE *FromServer; FILE *ToServer; char *group; { static char address[SMBUF]; register char *p; char *save; char buff[BUFSIZ]; char name[SMBUF]; (void)strcpy(name, group); address[0] = '\0'; if (FromServer==NULL || ToServer==NULL){ /* * This should be part of nnrpd or the like running on the server. * Open the server copy of the moderators file. */ GMAfp = fopen(_PATH_MODERATORS, "r"); }else{ /* * Get a local copy of the moderators file from the server. */ (void)strcpy(GMApathname, _PATH_TEMPMODERATORS); (void)mktemp(GMApathname); GMAfp = GMA_listopen(GMApathname, FromServer, ToServer, "moderators"); } if (GMAfp != NULL) { while (fgets(buff, sizeof buff, GMAfp) != NULL) { /* Skip blank and comment lines. */ if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; if (buff[0] == '\0' || buff[0] == COMMENT_CHAR) continue; /* Snip off the first word. */ if ((p = strchr(buff, ':')) == NULL) /* Malformed line... */ continue; *p++ = '\0'; /* If it pattern-matches the newsgroup, the second field is a * format for mailing, with periods changed to dashes. */ if (wildmat(name, buff)) { for (save = p; ISWHITE(*save); save++) continue; for (p = name; *p; p++) if (*p == '.') *p = '-'; (void)sprintf(address, save, name); break; } } (void) GMAclose(); if (address[0]) return address; } /* If we don't have an address, see if the config file has a default. */ if ((save = GetConfigValue(_CONF_MODMAILER)) == NULL) return NULL; for (p = name; *p; p++) if (*p == '.') *p = '-'; (void)sprintf(address, save, name); return address; } inn-1.7.2/lib/localopen.c0100644000175100001440000000366606443103542013530 0ustar mdusers/* $Revision: 1.9 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include "paths.h" #include "nntp.h" #include "macros.h" #if defined(DO_HAVE_UNIX_DOMAIN) #include #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ /* ** Open a connection to the local InterNetNews NNTP server and optionally ** create stdio FILE's for talking to it. Return -1 on error. */ int NNTPlocalopen(FromServerp, ToServerp, errbuff) FILE **FromServerp; FILE **ToServerp; char *errbuff; { #if defined(DO_HAVE_UNIX_DOMAIN) int i; int j; int oerrno; struct sockaddr_un server; FILE *F; char mybuff[NNTP_STRLEN + 2]; char *buff; buff = errbuff ? errbuff : mybuff; *buff = '\0'; /* Create a socket. */ if ((i = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) return -1; /* Connect to the server. */ (void)memset((POINTER)&server, 0, sizeof server); server.sun_family = AF_UNIX; (void)strcpy(server.sun_path, _PATH_NNTPCONNECT); if (connect(i, (struct sockaddr *)&server, AF_UNIX_SOCKSIZE(server)) < 0) { oerrno = errno; (void)close(i); errno = oerrno; return -1; } /* Connected -- now make sure we can post. */ if ((F = fdopen(i, "r")) == NULL) { oerrno = errno; (void)close(i); errno = oerrno; return -1; } if (fgets(buff, sizeof mybuff, F) == NULL) { oerrno = errno; (void)fclose(F); errno = oerrno; return -1; } j = atoi(buff); if (j != NNTP_POSTOK_VAL && j != NNTP_NOPOSTOK_VAL) { (void)fclose(F); /* This seems like a reasonable error code to use... */ errno = EPERM; return -1; } *FromServerp = F; if ((*ToServerp = fdopen(dup(i), "w")) == NULL) { oerrno = errno; (void)fclose(F); errno = oerrno; return -1; } return 0; #else return NNTPconnect(LOOPBACK_HOST, FromServerp, ToServerp, errbuff); #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ } inn-1.7.2/lib/strtok.c0100644000175100001440000000433706443103542013076 0ustar mdusers/* $Revision: 1.3 $ ** ** This file has been modified to get it to compile more easily ** on pre-4.4BSD systems. Rich $alz, June 1991. */ #include #include #include "configdata.h" #include "clibrary.h" #define NULL 0 /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that: (1) source distributions retain this entire copyright * notice and comment, and (2) distributions including binaries display * the following acknowledgement: ``This product includes software * developed by the University of California, Berkeley and its contributors'' * in the documentation or other materials provided with the distribution * and in all advertising materials mentioning features or use of this * software. Neither the name of the University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if 0 #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)strtok.c 5.7 (Berkeley) 6/1/90"; #endif /* LIBC_SCCS and not lint */ #include #include #endif char * strtok(s, delim) register char *s, *delim; { register char *spanp; register int c, sc; char *tok; static char *last; if (s == NULL && (s = last) == NULL) return (NULL); /* * Skip (span) leading delimiters (s += strspn(s, delim), sort of). */ cont: c = *s++; for (spanp = delim; (sc = *spanp++) != 0;) { if (c == sc) goto cont; } if (c == 0) { /* no non-delimiter characters */ last = NULL; return (NULL); } tok = s - 1; /* * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). * Note that delim must have one NUL; we stop if we see that, too. */ for (;;) { c = *s++; spanp = delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = 0; last = s; return (tok); } } while (sc != 0); } /* NOTREACHED */ } inn-1.7.2/lib/xmalloc.c0100644000175100001440000000067206443103542013205 0ustar mdusers/* $Revision: 1.8 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include #include "libinn.h" #include "macros.h" /* ** Allocate some memory or call the memory failure handler. */ ALIGNPTR xmalloc(i) unsigned int i; { POINTER new; while ((new = malloc(i)) == NULL) (*xmemfailure)("malloc", i); #if 0 memset (new,0,i) ; #endif return CAST(ALIGNPTR, new); } inn-1.7.2/lib/strcasecmp.c0100644000175100001440000001020006443103542013676 0ustar mdusers#include #include #include "configdata.h" #include "clibrary.h" /* $Revision: 1.3 $ * * Copyright (c) 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that: (1) source distributions retain this entire copyright * notice and comment, and (2) distributions including binaries display * the following acknowledgement: ``This product includes software * developed by the University of California, Berkeley and its contributors'' * in the documentation or other materials provided with the distribution * and in all advertising materials mentioning features or use of this * software. Neither the name of the University nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #define const /* NULL */ #define size_t int #if defined(LIBC_SCCS) && !defined(lint) static const char sccsid[] = "@(#)strcasecmp.c 5.9 (Berkeley) 6/1/90"; #endif /* LIBC_SCCS and not lint */ typedef unsigned char u_char; /* * This array is designed for mapping upper and lower case letter * together for a case independent comparison. The mappings are * based upon ascii character sequences. */ static const u_char charmap[] = { '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', }; int strcasecmp(s1, s2) const char *s1, *s2; { register const u_char *cm = charmap, *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; while (cm[*us1] == cm[*us2++]) if (*us1++ == '\0') return (0); return (cm[*us1] - cm[*--us2]); } int strncasecmp(s1, s2, n) const char *s1, *s2; register size_t n; { if (n != 0) { register const u_char *cm = charmap, *us1 = (const u_char *)s1, *us2 = (const u_char *)s2; do { if (cm[*us1] != cm[*us2++]) return (cm[*us1] - cm[*--us2]); if (*us1++ == '\0') break; } while (--n != 0); } return (0); } inn-1.7.2/lib/waitnb.c0100644000175100001440000000144106443103542013025 0ustar mdusers/* $Revision: 1.4 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include #if defined(DO_USE_UNION_WAIT) typedef union wait WAITER; #if defined(WEXITSTATUS) #define WAITVAL(x) (WEXITSTATUS(x)) #else #define WAITVAL(x) ((x).w_retcode) #endif /* defined(WEXITSTATUS) */ #else typedef int WAITER; #define WAITVAL(x) (((x) >> 8) & 0xFF) #endif /* defined(DO_USE_UNION_WAIT) */ PID_T waitnb(statusp) int *statusp; { WAITER w; PID_T pid; #if defined(DO_HAVE_WAITPID) pid = waitpid(-1, &w, WNOHANG); #endif /* defined(DO_HAVE_WAITPID) */ #if defined(DONT_HAVE_WAITPID) pid = wait3(&w, WNOHANG, (struct rusage *)NULL); #endif /* defined(DONT_HAVE_WAITPID) */ if (pid > 0) *statusp = WAITVAL(w); return pid; } inn-1.7.2/lib/mkfifo.c0100644000175100001440000000043006443103542013011 0ustar mdusers/* $Revision: 1.2 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include /* ** Call mknod(2) to make a fifo. */ int mkfifo(path, mode) char *path; int mode; { return mknod(path, S_IFIFO | mode, 0); } inn-1.7.2/lib/inndcomm.c0100644000175100001440000002134206443103542013347 0ustar mdusers/* $Revision: 1.24 $ ** ** Library routines to let other programs control innd. */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include #include #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include #include #if defined(DO_HAVE_UNIX_DOMAIN) #include #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ #include "nntp.h" #include "paths.h" #include "libinn.h" #include "inndcomm.h" #include "macros.h" #define MIN_BUFFER_SIZE 4096 STATIC char ICCsockname[sizeof _PATH_TEMPSOCK]; #if defined(DO_HAVE_UNIX_DOMAIN) STATIC struct sockaddr_un ICCserv; STATIC struct sockaddr_un ICCclient; #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ STATIC int ICCfd; STATIC int ICCtimeout; char *ICCfailure; /* ** Set the timeout. */ void ICCsettimeout(i) int i; { ICCtimeout = i; } /* ** Get ready to talk to the server. */ int ICCopen() { int mask; int oerrno; /* Create a temporary name. */ (void)strcpy(ICCsockname, _PATH_TEMPSOCK); (void)mktemp(ICCsockname); if (unlink(ICCsockname) < 0 && errno != ENOENT) { ICCfailure = "unlink"; return -1; } #if defined(DO_HAVE_UNIX_DOMAIN) /* Make a socket and give it the name. */ if ((ICCfd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { ICCfailure = "socket"; return -1; } (void)memset((POINTER)&ICCclient, 0, sizeof ICCclient); ICCclient.sun_family = AF_UNIX; (void)strcpy(ICCclient.sun_path, ICCsockname); mask = umask(0); if (bind(ICCfd, (struct sockaddr *)&ICCclient, AF_UNIX_SOCKSIZE(ICCclient)) < 0) { oerrno = errno; (void)umask(mask); errno = oerrno; ICCfailure = "bind"; return -1; } (void)umask(mask); /* Name the server's socket. */ (void)memset((POINTER)&ICCserv, 0, sizeof ICCserv); ICCserv.sun_family = AF_UNIX; (void)strcpy(ICCserv.sun_path, _PATH_NEWSCONTROL); #else /* Make a named pipe and open it. */ mask = umask(0); if (mkfifo(ICCsockname, 0666) < 0) { oerrno = errno; (void)umask(mask); errno = oerrno; ICCfailure = "mkfifo"; return -1; } (void)umask(mask); if ((ICCfd = open(ICCsockname, O_RDWR)) < 0) { ICCfailure = "open"; return -1; } #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ ICCfailure = NULL; return 0; } /* ** Close down. */ int ICCclose() { int i; ICCfailure = NULL; i = 0; if (close(ICCfd) < 0) { ICCfailure = "close"; i = -1; } if (unlink(ICCsockname) < 0 && errno != ENOENT) { ICCfailure = "unlink"; i = -1; } return i; } /* ** Get the server's pid. */ STATIC PID_T ICCserverpid() { PID_T pid; FILE *F; char buff[SMBUF]; pid = 1; if ((F = fopen(_PATH_SERVERPID, "r")) != NULL) { if (fgets(buff, sizeof buff, F) != NULL) pid = (PID_T) atol(buff); (void)fclose(F); } return pid; } /* ** See if the server is still there. When in doubt, assume yes. ** Cache the pid since a rebooted server won't know about our pending ** message. */ STATIC BOOL ICCserveralive(pid) PID_T pid; { if (kill(pid, 0) > 0 || errno != ESRCH) return TRUE; return FALSE; } /* ** Send an arbitrary command to the server. ** ** The command format is now different. There is a protocol version ** (one-byte) on the front of the message, followed by a two byte ** length count. The length includes the protocol byte and the length ** itself. */ int ICCcommand(cmd, argv, replyp) char cmd; char *argv[]; char **replyp; { char *buff; char *p; char *q; char save; int bufsiz; int i ; #if !defined(DO_HAVE_UNIX_DOMAIN) int fd; #endif /* !defined(DO_HAVE_UNIX_DOMAIN) */ int len; FDSET Rmask; struct timeval T; PID_T pid; ICC_MSGLENTYPE rlen ; ICC_PROTOCOLTYPE protocol ; /* Is server there? */ pid = ICCserverpid(); if (!ICCserveralive(pid)) { ICCfailure = "dead server"; return -1; } /* Get the length of the buffer. */ bufsiz = strlen(ICCsockname) + 1 + 1; for (i = 0; (p = argv[i]) != NULL; i++) bufsiz += 1 + strlen(p); bufsiz += HEADER_SIZE ; if (bufsiz < MIN_BUFFER_SIZE) bufsiz = MIN_BUFFER_SIZE; buff = malloc((unsigned int)bufsiz); if (buff == NULL) { ICCfailure = "malloc"; return -1; } if (replyp) *replyp = NULL; buff += HEADER_SIZE; /* Advance to leave space for length + protocol version info. */ /* Format the message. */ (void)sprintf(buff, "%s%c%c", ICCsockname, SC_SEP, cmd); for (p = buff + strlen(buff), i = 0; (q = argv[i]) != NULL; i++) { *p++ = SC_SEP; p += strlen(strcpy(p, q)); } /* Send message. */ ICCfailure = NULL; len = p - buff + HEADER_SIZE ; rlen = htons (len) ; /* now stick in the protocol version and the length. */ buff -= HEADER_SIZE; protocol = ICC_PROTOCOL_1 ; memcpy (buff,&protocol,sizeof (protocol)) ; buff += sizeof (protocol) ; memcpy (buff,&rlen,sizeof (rlen)) ; buff += sizeof (rlen) ; buff -= HEADER_SIZE ; #if defined(DO_HAVE_UNIX_DOMAIN) if (sendto(ICCfd, buff, len, 0, (struct sockaddr *)&ICCserv, AF_UNIX_SOCKSIZE(ICCserv)) < 0) { DISPOSE(buff); ICCfailure = "sendto"; return -1; } #else if ((fd = open(_PATH_NEWSCONTROL, O_WRONLY)) < 0) { DISPOSE(buff); ICCfailure = "open"; return -1; } if (write(fd, buff, len) != len) { i = errno; DISPOSE(buff); (void)close(fd); errno = i; ICCfailure = "write"; return -1; } (void)close(fd); #endif /* defined(DO_HAVE_UNIX_DOMAIN) */ /* Possibly get a reply. */ switch (cmd) { default: if (ICCtimeout >= 0) break; /* FALLTHROUGH */ case SC_SHUTDOWN: case SC_XABORT: case SC_XEXEC: DISPOSE(buff); return 0; } /* Wait for the reply. */ for ( ; ; ) { FD_ZERO(&Rmask); FD_SET(ICCfd, &Rmask); T.tv_sec = ICCtimeout ? ICCtimeout : 120; T.tv_usec = 0; i = select(ICCfd + 1, &Rmask, (FDSET *)NULL, (FDSET *)NULL, &T); if (i < 0) { DISPOSE(buff); ICCfailure = "select"; return -1; } if (i > 0 && FD_ISSET(ICCfd, &Rmask)) /* Server reply is there; go handle it. */ break; /* No data -- if we timed out, return. */ if (ICCtimeout) { DISPOSE(buff); errno = ETIMEDOUT; ICCfailure = "timeout"; return -1; } if (!ICCserveralive(pid)) { DISPOSE(buff); ICCfailure = "dead server"; return -1; } } #if defined (DO_HAVE_UNIX_DOMAIN) /* Read the reply. */ i = RECVorREAD(ICCfd, buff, bufsiz) ; if (i < HEADER_SIZE) { DISPOSE(buff) ; ICCfailure = "read" ; return -1 ; } memcpy (&protocol,buff,sizeof (protocol)) ; memcpy (&rlen,buff + sizeof (protocol),sizeof (rlen)) ; rlen = ntohs (rlen) ; if (i != rlen) { DISPOSE(buff) ; ICCfailure = "short read" ; return -1 ; } if (protocol != ICC_PROTOCOL_1) { DISPOSE(buff) ; ICCfailure = "protocol mismatch" ; return -1 ; } memmove (buff, buff + HEADER_SIZE, rlen - HEADER_SIZE) ; i -= HEADER_SIZE ; buff[i] = '\0'; #else /* defined (DO_HAVE_UNIX_DOMAIN) */ i = RECVorREAD (ICCfd, buff, HEADER_SIZE) ; if (i != HEADER_SIZE) { return -1 ; } memcpy (&protocol,buff,sizeof (protocol)) ; memcpy (&rlen,buff + sizeof (protocol),sizeof (rlen)) ; rlen = ntohs (rlen) - HEADER_SIZE ; i = RECVorREAD(ICCfd, buff, rlen) ; if (i != rlen) { return -1 ; } buff[i] = '\0'; if (protocol != ICC_PROTOCOL_1) { return -1 ; } #endif /* defined (DO_HAVE_UNIX_DOMAIN) */ /* Parse the rest of the reply; expected to be like " */ i = 0; if (CTYPE(isdigit, buff[0])) { for (p = buff; *p && CTYPE(isdigit, *p); p++) continue; if (*p) { save = *p; *p = '\0'; i = atoi(buff); *p = save; } } if (replyp) { *replyp = buff ; } else { DISPOSE(buff); } return i; } /* ** Send a "cancel" command. */ int ICCcancel(msgid) char *msgid; { char *args[2]; args[0] = msgid; args[1] = NULL; return ICCcommand(SC_CANCEL, args, (char **)NULL); } /* ** Send a "go" command. */ int ICCgo(why) char *why; { char *args[2]; args[0] = why; args[1] = NULL; return ICCcommand(SC_GO, args, (char **)NULL); } /* ** Send a "pause" command. */ int ICCpause(why) char *why; { char *args[2]; args[0] = why; args[1] = NULL; return ICCcommand(SC_PAUSE, args, (char **)NULL); } /* ** Send a "reserve" command. */ int ICCreserve(why) char *why; { char *args[2]; args[0] = why; args[1] = NULL; return ICCcommand(SC_RESERVE, args, (char **)NULL); } inn-1.7.2/lib/getconfig.c0100644000175100001440000000344506443103542013514 0ustar mdusers/* $Revision: 1.11 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include "paths.h" #include "libinn.h" #include "macros.h" /* Global and initialized; to work around SunOS -Bstatic bug, sigh. */ STATIC char ConfigBuff[SMBUF] = ""; char * GetFileConfigValue(value) register char *value; { register FILE *F; register int i; register char *p; register char c; /* Read the config file. */ if ((F = fopen(_PATH_CONFIG, "r")) != NULL) { c = *value; i = strlen(value); while (fgets(ConfigBuff, sizeof ConfigBuff, F) != NULL) { if ((p = strchr(ConfigBuff, '\n')) != NULL) *p = '\0'; if (ConfigBuff[0] == '\0' || ConfigBuff[0] == COMMENT_CHAR) continue; if (ConfigBuff[0] == c && ConfigBuff[i] == ':' && EQn(ConfigBuff, value, i)) { (void)fclose(F); for (p = &ConfigBuff[i + 1]; ISWHITE(*p); p++) continue; return p; } } (void)fclose(F); } return NULL; } /* ** Get a configuration parameter, usually from reading the file. */ char * GetConfigValue(value) register char *value; { register char *p; /* Some environment variables override the file. */ if (EQ(value, _CONF_SERVER) && (p = getenv(_ENV_NNTPSERVER)) != NULL) return p; if (EQ(value, _CONF_ORGANIZATION) && (p = getenv(_ENV_ORGANIZATION)) != NULL) return p; if (EQ(value, _CONF_FROMHOST) && (p = getenv(_ENV_FROMHOST)) != NULL) return p; if ((p = GetFileConfigValue(value)) != NULL) return p; /* Some values have defaults if not in the file. */ if (EQ(value, _CONF_FROMHOST) || EQ(value, _CONF_PATHHOST)) return GetFQDN(); if (EQ(value, _CONF_CONTENTTYPE)) return "text/plain; charset=US-ASCII"; if (EQ(value, _CONF_ENCODING)) return "7bit"; return NULL; } inn-1.7.2/lib/lock.c0100644000175100001440000000221306443103542012467 0ustar mdusers/* $Revision: 1.9 $ ** ** InterNetNews replacement for C news system locking. */ #include #include #include "configdata.h" #include "clibrary.h" static char COMMAND[] = "ctlinnd %s Expire process %ld"; static int IsLocked; /* ** C News debugging function. /* ARGSUSED */ void lockdebug(state) int state; { } /* ** Lock the news system by telling the server to throttle input. */ void newslock() { char buff[72]; int i; (void)sprintf(buff, COMMAND, "throttle", (long)getpid()); i = system(buff) >> 8; if (i) error("Can't lock"); IsLocked = 1; } /* ** Unlock the system and reload the files. */ void newsunlock() { char buff[72]; int i; if (IsLocked) { (void)sprintf(buff, COMMAND, "go", (long)getpid()); i = system(buff) >> 8; if (i) error("Can't reload"); (void)sprintf(buff, "ctlinnd go"); i = system(buff) >> 8; if (i) error("Can't unlock"); IsLocked = 0; } } /* ** Print an error message, then unlock the system. */ void errunlock(text, arg) char *text; char *arg; { warning(text, arg); newsunlock(); exit(1); /* NOTREACHED */ } inn-1.7.2/lib/nonblocking.c0100644000175100001440000000154006443103542014044 0ustar mdusers/* $Revision: 1.7 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #if defined(NBIO_IOCTL) #include /* ** Enable or disable non-blocking I/O mode. */ int SetNonBlocking(fd, flag) int fd; BOOL flag; { int state; state = flag ? 1 : 0; return ioctl(fd, FIONBIO, (char *)&state); } #endif /* defined(NBIO_IOCTL) */ #if defined(NBIO_FCNTL) #include #include #if !defined(FNDELAY) #define FNDELAY O_NDELAY #endif /* !defined(FNDELAY) */ /* ** Enable or disable non-blocking I/O mode. */ int SetNonBlocking(fd, flag) int fd; BOOL flag; { int mode; if ((mode = fcntl(fd, F_GETFL, 0)) < 0) return -1; if (flag) mode |= FNDELAY; else mode &= ~FNDELAY; return fcntl(fd, F_SETFL, mode); } #endif /* defined(NBIO_FCNTL) */ inn-1.7.2/lib/clientlib.c0100644000175100001440000000636406443103542013517 0ustar mdusers/* $Revision: 1.8 $ ** ** Routines compatible with the NNTP "clientlib" routines. */ #include #include #include "configdata.h" #include "clibrary.h" #include "nntp.h" #include "paths.h" #include "libinn.h" #include "myserver.h" FILE *ser_rd_fp = NULL; FILE *ser_wr_fp = NULL; char ser_line[NNTP_STRLEN + 2]; /* ** Get the name of the NNTP server. Ignore the filename; we use ** our own configuration stuff. Return pointer to static data. */ /* ARGSUSED0 */ char * getserverbyfile(file) char *file; { static char buff[256]; char *p; if ((p = GetConfigValue(_CONF_SERVER)) == NULL) return NULL; (void)strcpy(buff, p); return buff; } /* ** Get a connection to the remote news server. Return server's reply ** code or -1 on error. */ int server_init(host) char *host; { char line2[NNTP_STRLEN]; if (NNTPconnect(host, &ser_rd_fp, &ser_wr_fp, ser_line) < 0) { if (ser_line[0] == '\0') /* I/O problem. */ return -1; /* Server rejected connection; return it's reply code. */ return atoi(ser_line); } /* Send the INN command; if understood, use that reply. */ put_server("mode reader"); if (get_server(line2, (int)sizeof line2) < 0) return -1; if (atoi(line2) != NNTP_BAD_COMMAND_VAL) (void)strcpy(ser_line, line2); /* Connected; return server's reply code. */ return atoi(ser_line); } #define CANTPOST \ "NOTE: This machine does not have permission to post articles" #define CANTUSE \ "This machine does not have permission to use the %s news server.\n" /* ** Print a message based on the the server's initial response. ** Return -1 if server wants us to go away. */ int handle_server_response(response, host) int response; char *host; { char *p; switch (response) { default: (void)printf("Unknown response code %d from %s.\n", response, host); return -1; case NNTP_GOODBYE_VAL: if (atoi(ser_line) == response) { p = &ser_line[strlen(ser_line) - 1]; if (*p == '\n' && *--p == '\r') *p = '\0'; if (p > &ser_line[3]) { (void)printf("News server %s unavailable: %s\n", host, &ser_line[4]); return -1; } } (void)printf("News server %s unavailable, try later.\n", host); return -1; case NNTP_ACCESS_VAL: (void)printf(CANTUSE, host); return -1; case NNTP_NOPOSTOK_VAL: (void)printf("%s.\n", CANTPOST); /* FALLTHROUGH */ case NNTP_POSTOK_VAL: break; } return 0; } /* ** Send a line of text to the server. */ void put_server(buff) char *buff; { (void)fprintf(ser_wr_fp, "%s\r\n", buff); (void)fflush(ser_wr_fp); } /* ** Get a line of text from the server, strip trailing \r\n. ** Return -1 on error. */ int get_server(buff, buffsize) register char *buff; int buffsize; { register char *p; if (fgets(buff, buffsize, ser_rd_fp) == NULL) return -1; p = &buff[strlen(buff)]; if (p >= &buff[2] && p[-2] == '\r' && p[-1] == '\n') p[-2] = '\0'; return 0; } /* ** Send QUIT and close the server. */ void close_server() { char buff[NNTP_STRLEN]; if (ser_wr_fp != NULL && ser_rd_fp != NULL) { put_server("QUIT"); (void)fclose(ser_wr_fp); ser_wr_fp = NULL; (void)get_server(buff, (int)sizeof buff); (void)fclose(ser_rd_fp); ser_rd_fp = NULL; } } inn-1.7.2/lib/sendarticle.c0100644000175100001440000000153206443103542014037 0ustar mdusers/* $Revision: 1.5 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include "libinn.h" #include "nntp.h" /* ** Send a string of one or more lines down a stdio FILE using RFC977 ** conventions. Return -1 on error. */ int NNTPsendarticle(p, F, Terminate) register char *p; register FILE *F; BOOL Terminate; { register char *next; for (; p && *p; next[-1] = '\n', p = next) { /* Get pointer to next line. Truncate long lines. */ if ((next = strchr(p, '\n')) != NULL) *next++ = '\0'; /* Write line. */ if (*p == '.' && putc('.', F) == EOF) return -1; if (fprintf(F, "%s\r\n", p) == EOF) return -1; /* Done? */ if (next == NULL) break; } if (Terminate && fprintf(F, ".\r\n") == EOF) return -1; return fflush(F) == EOF || ferror(F) ? -1 : 0; } inn-1.7.2/lib/malloc.c0100644000175100001440000002457606443103542013026 0ustar mdusers/* $Revision: 1.4 $ * * Revision 4.0.1.1 91/04/11 17:48:31 lwall * patch1: Configure now figures out malloc ptr type * * Revision 4.0 91/03/20 01:28:52 lwall * 4.0 baseline. * * Slightly hacked by Matthias Urlichs (urlichs@smurf.sub.org) * to fit into INND; 91/08/28. */ #include #include #include "configdata.h" #include "clibrary.h" #define RCHECK #ifndef lint static char sccsid[] = "@(#)malloc.c 4.3 (Berkeley) 9/16/83"; /* * malloc.c (Caltech) 2/21/82 * Chris Kingsley, kingsley@cit-20. * * This is a very fast storage allocator. It allocates blocks of a small * number of different sizes, and keeps free lists of each size. Blocks that * don't exactly fit are passed up to the next larger size. In this * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long. * This is designed for use in a program that uses vast quantities of memory, * but bombs when it runs out. */ #include "logging.h" static findbucket(), morecore(); /* I don't much care whether these are defined in sys/types.h--LAW */ #define u_char unsigned char #define u_int unsigned int #define u_short unsigned short /* * The overhead on a block is at least 4 bytes. When free, this space * contains a pointer to the next free block, and the bottom two bits must * be zero. When in use, the first byte is set to MAGIC, and the second * byte is the size index. The remaining bytes are for alignment. * If range checking is enabled and the size of the block fits * in two bytes, then the top two bytes hold the size of the requested block * plus the range checking words, and the header word MINUS ONE. */ union overhead { union overhead *ov_next; /* when free */ #if ALIGNBYTES > 4 double strut; /* alignment problems */ #endif struct { u_char ovu_magic; /* magic number */ u_char ovu_index; /* bucket # */ #ifdef RCHECK u_short ovu_size; /* actual block size */ u_int ovu_rmagic; /* range magic number */ #endif } ovu; #define ov_magic ovu.ovu_magic #define ov_index ovu.ovu_index #define ov_size ovu.ovu_size #define ov_rmagic ovu.ovu_rmagic }; #define MAGIC 0xff /* magic # on accounting info */ #define OLDMAGIC 0x7f /* same after a free() */ #define RMAGIC 0x55555555 /* magic # on range info */ #ifdef RCHECK #define RSLOP sizeof (u_int) #else #define RSLOP 0 #endif /* * nextf[i] is the pointer to the next free block of size 2^(i+3). The * smallest allocatable block is 8 bytes. The overhead information * precedes the data area returned to the user. */ #define NBUCKETS 30 static union overhead *nextf[NBUCKETS]; extern char *sbrk(); #ifdef MSTATS /* * nmalloc[i] is the difference between the number of mallocs and frees * for a given block size. */ static u_int nmalloc[NBUCKETS]; #include #endif #ifdef debug #define ASSERT(p) if (!(p)) botch("p"); else static botch(s) char *s; { printf("assertion botched: %s\n", s); abort(); } #else #ifdef __STDC__ #define ASSERT(p) if(!(p)) syslog(L_FATAL, #p); else #else #define ASSERT(p) if(!(p)) syslog(L_FATAL, "p"); else #endif #endif POINTER malloc(nbytes) register SIZE_T nbytes; { register union overhead *p; register int bucket = 0; register unsigned shiftr; /* * Convert amount of memory requested into * closest block size stored in hash buckets * which satisfies request. Account for * space used per block for accounting. */ nbytes += sizeof (union overhead) + RSLOP; nbytes = (nbytes + 3) &~ 3; shiftr = (nbytes - 1) >> 2; /* apart from this loop, this is O(1) */ while (shiftr >>= 1) bucket++; /* * If nothing in hash bucket right now, * request more memory from the system. */ if (nextf[bucket] == NULL) morecore(bucket); if ((p = (union overhead *)nextf[bucket]) == NULL) return (NULL); /* remove from linked list */ #ifdef RCHECK if (*((int*)p) & (sizeof(union overhead) - 1)) #ifndef I286 fprintf(stderr,"Corrupt malloc ptr 0x%x at 0x%x\n",*((int*)p),p); #else fprintf(stderr,"Corrupt malloc ptr 0x%lx at 0x%lx\n",*((int*)p),p); #endif #endif nextf[bucket] = p->ov_next; p->ov_magic = MAGIC; p->ov_index= bucket; #ifdef MSTATS nmalloc[bucket]++; #endif #ifdef RCHECK /* * Record allocated size of block and * bound space with magic numbers. */ if (nbytes <= 0x10000) p->ov_size = nbytes - 1; p->ov_rmagic = RMAGIC; *((u_int *)((caddr_t)p + nbytes - RSLOP)) = RMAGIC; #endif return ((char *)(p + 1)); } /* * Allocate more memory to the indicated bucket. */ static morecore(bucket) register int bucket; { register union overhead *op; register int rnu; /* 2^rnu bytes will be requested */ register int nblks; /* become nblks blocks of the desired size */ register int siz; if (nextf[bucket]) return; /* * Insure memory is allocated * on a page boundary. Should * make getpageize call? */ op = (union overhead *)sbrk(0); #ifndef I286 if ((int)op & 0x3ff) (void)sbrk(1024 - ((int)op & 0x3ff)); #else /* The sbrk(0) call on the I286 always returns the next segment */ #endif #ifndef I286 /* take 2k unless the block is bigger than that */ rnu = (bucket <= 8) ? 11 : bucket + 3; #else /* take 16k unless the block is bigger than that (80286s like large segments!) */ rnu = (bucket <= 11) ? 14 : bucket + 3; #endif nblks = 1 << (rnu - (bucket + 3)); /* how many blocks to get */ if (rnu < bucket) rnu = bucket; op = (union overhead *)sbrk(1 << rnu); /* no more room! */ if ((int)op == -1) return; /* * Round up to minimum allocation size boundary * and deduct from block count to reflect. */ #ifndef I286 if ((int)op & 7) { op = (union overhead *)(((int)op + 8) &~ 7); nblks--; } #else /* Again, this should always be ok on an 80286 */ #endif /* * Add new memory allocated to that on * free list for this hash bucket. */ nextf[bucket] = op; siz = 1 << (bucket + 3); while (--nblks > 0) { op->ov_next = (union overhead *)((caddr_t)op + siz); op = (union overhead *)((caddr_t)op + siz); } } FREEVAL free(cp) POINTER cp; { register int size; register union overhead *op; if (cp == NULL) return; op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); #ifdef debug ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */ #else if (op->ov_magic != MAGIC) { syslog(L_ERROR, "%s free() ignored", op->ov_magic == OLDMAGIC ? "Duplicate" : "Bad"); return; /* sanity */ } op->ov_magic = OLDMAGIC; #endif #ifdef RCHECK ASSERT(op->ov_rmagic == RMAGIC); if (op->ov_index <= 13) ASSERT(*(u_int *)((caddr_t)op + op->ov_size + 1 - RSLOP) == RMAGIC); #endif ASSERT(op->ov_index < NBUCKETS); size = op->ov_index; op->ov_next = nextf[size]; nextf[size] = op; #ifdef MSTATS nmalloc[size]--; #endif } /* * When a program attempts "storage compaction" as mentioned in the * old malloc man page, it realloc's an already freed block. Usually * this is the last block it freed; occasionally it might be farther * back. We have to search all the free lists for the block in order * to determine its bucket: 1st we make one pass thru the lists * checking only the first block in each; if that fails we search * ``reall_srchlen'' blocks in each list for a match (the variable * is extern so the caller can modify it). If that fails we just copy * however many bytes was given to realloc() and hope it's not huge. */ int reall_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */ POINTER realloc(cp, nbytes) POINTER cp; SIZE_T nbytes; { register u_int onb; union overhead *op; char *res; register int i; int was_alloced = 0; if (cp == NULL) return (malloc(nbytes)); op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); if (op->ov_magic == MAGIC) { was_alloced++; i = op->ov_index; } else { /* * Already free, doing "compaction". * * Search for the old block of memory on the * free list. First, check the most common * case (last element free'd), then (this failing) * the last ``reall_srchlen'' items free'd. * If all lookups fail, then assume the size of * the memory block being realloc'd is the * smallest possible. */ if ((i = findbucket(op, 1)) < 0 && (i = findbucket(op, reall_srchlen)) < 0) i = 0; } onb = (1 << (i + 3)) - sizeof (*op) - RSLOP; /* avoid the copy if same size block */ if (was_alloced && nbytes <= onb && nbytes > (onb >> 1) - sizeof(*op) - RSLOP) { #ifdef RCHECK /* * Record new allocated size of block and * bound space with magic numbers. */ if (op->ov_index <= 13) { /* * Convert amount of memory requested into * closest block size stored in hash buckets * which satisfies request. Account for * space used per block for accounting. */ nbytes += sizeof (union overhead) + RSLOP; nbytes = (nbytes + 3) &~ 3; op->ov_size = nbytes - 1; *((u_int *)((caddr_t)op + nbytes - RSLOP)) = RMAGIC; } #endif return(cp); } if ((res = malloc(nbytes)) == NULL) return (NULL); if (cp != res) /* common optimization */ (void)bcopy(cp, res, (int)((nbytes < onb) ? nbytes : onb)); if (was_alloced) free(cp); return (res); } /* * Search ``srchlen'' elements of each free list for a block whose * header starts at ``freep''. If srchlen is -1 search the whole list. * Return bucket number, or -1 if not found. */ static findbucket(freep, srchlen) union overhead *freep; int srchlen; { register union overhead *p; register int i, j; for (i = 0; i < NBUCKETS; i++) { j = 0; for (p = nextf[i]; p && j != srchlen; p = p->ov_next) { if (p == freep) return (i); j++; } } return (-1); } #ifdef MSTATS /* * mstats - print out statistics about malloc * * Prints two lines of numbers, one showing the length of the free list * for each size category, the second showing the number of mallocs - * frees for each size category. */ mstats(s) char *s; { register int i, j; register union overhead *p; int totfree = 0, totused = 0; fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s); for (i = 0; i < NBUCKETS; i++) { for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) ; fprintf(stderr, " %d", j); totfree += j * (1 << (i + 3)); } fprintf(stderr, "\nused:\t"); for (i = 0; i < NBUCKETS; i++) { fprintf(stderr, " %d", nmalloc[i]); totused += nmalloc[i] * (1 << (i + 3)); } fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n", totused, totfree); } #endif #endif /* lint */ inn-1.7.2/lib/perl.c0100644000175100001440000001346106443103542012510 0ustar mdusers/* -*- c -*- * * Author: Christophe Wolfhugel * (although he wouldn't recognise it anymore so don't blame him) * File: perl.c * RCSId: $Id: perl.c,v 1.5 1996/10/16 15:14:20 brister Exp $ * Description: Perl hooks for libinn.a * */ #if ! defined (lint) static const char *rcsid = "$Id: perl.c,v 1.5 1996/10/16 15:14:20 brister Exp $" ; static void use_rcsid (const char *rid) { /* Never called */ use_rcsid (rcsid) ; use_rcsid (rid) ; } #endif #include #include #include "configdata.h" #include "clibrary.h" #include "logging.h" #if defined(DO_PERL) #include #include #include #include "macros.h" int PerlFilterActive = FALSE; static PerlInterpreter *PerlCode; CV *perl_filter_cv ; /* filter_art or filter_post holder */ extern char LogName[]; void LogPerl() { syslog(L_NOTICE, "%s perl filtering %s", LogName, PerlFilterActive ? "enabled" : "disabled"); } void PerlFilter(value) BOOL value ; { dSP; ENTER ; SAVETMPS ; /* Execute an end function */ if (PerlFilterActive && !value) { if (perl_get_cv("filter_end", FALSE) != NULL) { perl_call_argv("filter_end", G_EVAL|G_DISCARD|G_NOARGS, NULL); if (SvTRUE(GvSV(errgv))) /* check $@ */ { syslog (L_ERROR,"%s perl function filter_end died: %s", LogName, SvPV(GvSV(errgv), na)) ; POPs ; } } else { PerlFilterActive = value ; LogPerl () ; } } else if (!PerlFilterActive && value) { /* turning on */ if (perl_filter_cv == NULL) { syslog (L_ERROR,"%s perl filter not defined", LogName) ; } else { PerlFilterActive = value ; LogPerl () ; } } FREETMPS ; LEAVE ; } void PerlParse () { char *argv[] = { "innd", "-e", "sub _load_ { do $_[0] }", "-e", "sub _eval_ { eval $_[0] }", NULL } ; /* We can't call 'eval' and 'do' directly for some reason, so we define some wrapper functions to give us access. */ perl_parse (PerlCode,NULL,5,argv,NULL) ; } /* ** Loads a setup Perl module. startupfile is the name of the file loaded ** one-time at startup. filterfile is the file containing the filter ** functions which is loaded at startup and at each reload. function is a ** function name that must be defined after the file file is loaded for ** filtering to be turned on to start with. */ int PERLsetup (startupfile, filterfile, function) char *startupfile, *filterfile, *function; { if (PerlCode == NULL) { PerlCode = perl_alloc(); perl_construct(PerlCode); PerlParse () ; } if (startupfile != NULL && filterfile != NULL) { char *argv[2] ; int rc ; dSP; ENTER ; SAVETMPS ; argv[0] = startupfile ; argv[1] = NULL ; rc = perl_call_argv ("_load_",G_DISCARD, argv) ; SPAGAIN ; if (SvTRUE(GvSV(errgv))) /* check $@ */ { syslog (L_ERROR,"%s perl loading %s failed: %s", LogName, startupfile, SvPV(GvSV(errgv), na)) ; PerlFilter (FALSE) ; } else { PERLreadfilter (filterfile,function) ; } FREETMPS ; LEAVE ; } else { PERLreadfilter (filterfile,function) ; } } /* Load the perl file FILTERFILE. After it is load check that the give function is defined. If yes filtering is turned on. If not it is turned off. We remember whether the filter function was defined properly so that we can catch when the use tries to turn filtering on without the the funciton there. */ int PERLreadfilter(filterfile, function) char *filterfile, *function ; { dSP ; char *argv [3] ; ENTER ; SAVETMPS ; argv[0] = filterfile ; argv[1] = NULL ; if (perl_get_cv("filter_before_reload", FALSE) != NULL) { perl_call_argv("filter_before_reload",G_EVAL|G_DISCARD|G_NOARGS,NULL); if (SvTRUE(GvSV(errgv))) /* check $@ */ { syslog (L_ERROR,"%s perl function filter_before_reload died: %s", LogName, SvPV(GvSV(errgv), na)) ; POPs ; PerlFilter (FALSE) ; } } perl_call_argv ("_load_", 0, argv) ; if (SvTRUE(GvSV(errgv))) /* check $@ */ { syslog (L_ERROR,"%s perl loading %s failed: %s", LogName, filterfile, SvPV(GvSV(errgv), na)) ; PerlFilter (FALSE) ; /* If the reload failed we don't want the old definition hanging around. */ argv[0] = NEW (char,strlen (function) + strlen ("undef &%s")) ; sprintf (argv[0],"undef &%s",function) ; perl_call_argv ("_eval_",0,argv) ; if (SvTRUE(GvSV(errgv))) /* check $@ */ { syslog (L_ERROR,"%s perl undef &%s failed: %s", LogName, function, SvPV(GvSV(errgv), na)) ; } DISPOSE (argv[0]) ; } else if ((perl_filter_cv = perl_get_cv(function, FALSE)) == NULL) { PerlFilter (FALSE) ; } if (perl_get_cv("filter_after_reload", FALSE) != NULL) { perl_call_argv("filter_after_reload", G_EVAL|G_DISCARD|G_NOARGS, NULL); if (SvTRUE(GvSV(errgv))) /* check $@ */ { syslog (L_ERROR,"%s perl function filter_after_reload died: %s", LogName, SvPV(GvSV(errgv), na)) ; POPs ; PerlFilter (FALSE) ; } } FREETMPS ; LEAVE ; return (perl_filter_cv != NULL) ; } /* ** Stops using the Perl filter */ void PerlClose() { perl_destruct(PerlCode); perl_free(PerlCode); PerlFilterActive = FALSE; } #endif /* defined(DO_PERL) */ inn-1.7.2/lib/genid.c0100644000175100001440000000136406443103542012633 0ustar mdusers/* $Revision: 1.5 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #if defined(DO_NEED_TIME) #include #endif /* defined(DO_NEED_TIME) */ #include #include "libinn.h" /* Scale time back a bit, for shorter Message-ID's. */ #define OFFSET 673416000L char * GenerateMessageID() { static char buff[SMBUF]; static int count; char *p; char sec32[10]; char pid32[10]; TIMEINFO Now; if (GetTimeInfo(&Now) < 0) return NULL; Radix32((unsigned long)Now.time - OFFSET, sec32); Radix32((unsigned long)getpid(), pid32); if ((p = GetFQDN()) == NULL) return NULL; (void)sprintf(buff, "<%s$%s$%d@%s>", sec32, pid32, ++count, p); return buff; } inn-1.7.2/lib/sendpass.c0100644000175100001440000000452706443103542013371 0ustar mdusers/* $Revision: 1.10 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include #include #include "nntp.h" #include "paths.h" #include "libinn.h" #include "macros.h" /* ** Send authentication information to an NNTP server. */ int NNTPsendpassword(server, FromServer, ToServer) char *server; FILE *FromServer; FILE *ToServer; { register FILE *F; register char *p; char buff[SMBUF]; char input[SMBUF]; char *user; char *pass; char *style; int oerrno; /* What server are we interested in? Default to the campus one. */ if (server == NULL && (server = GetConfigValue(_CONF_SERVER)) == NULL) return -1; /* Open the password file; coarse check on errno, but good enough. */ if ((F = fopen(_PATH_NNTPPASS, "r")) == NULL) return errno == EPERM ? -1 : 0; /* Scan the file, skipping blank and comment lines. */ while (fgets(buff, sizeof buff, F) != NULL) { if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; if (buff[0] == '\0' || buff[0] == COMMENT_CHAR) continue; /* Parse the line. */ if ((user = strchr(buff, ':')) == NULL) continue; *user++ = '\0'; if ((pass = strchr(user, ':')) == NULL) continue; *pass++ = '\0'; if ((style = strchr(pass, ':')) != NULL) { *style++ = '\0'; if (!EQ(style, "authinfo")) { errno = EDOM; break; } } if (!caseEQ(server, buff)) continue; if (*user) { /* Send the first part of the command, get a reply. */ (void)fprintf(ToServer, "authinfo user %s\r\n", user); if (fflush(ToServer) == EOF || ferror(ToServer)) break; if (fgets(input, sizeof input, FromServer) == NULL || atoi(input) != NNTP_AUTH_NEXT_VAL) break; } if (*pass) { /* Send the second part of the command, get a reply. */ (void)fprintf(ToServer, "authinfo pass %s\r\n", pass); if (fflush(ToServer) == EOF || ferror(ToServer)) break; if (fgets(input, sizeof input, FromServer) == NULL || atoi(input) != NNTP_AUTH_OK_VAL) break; } /* Authenticated. */ (void)fclose(F); return 0; } /* End of file without finding a password, that's okay. */ if (feof(F)) { (void)fclose(F); return 0; } /* Save errno, close the file, fail. */ oerrno = errno; (void)fclose(F); errno = oerrno; return -1; } inn-1.7.2/lib/writev.c0100644000175100001440000000066306443103542013066 0ustar mdusers/* $Revision: 1.4 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include /* ** "Fake" writev for sites without it. */ int writev(fd, vp, vpcount) int fd; struct iovec *vp; int vpcount; { int count; for (count = 0; --vpcount >= 0; count += vp->iov_len, vp++) if (xwrite(fd, vp->iov_base, vp->iov_len) < 0) return -1; return count; } inn-1.7.2/lib/clientactive.c0100644000175100001440000000547506443103542014226 0ustar mdusers/* $Revision: 1.10 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include #include "paths.h" #include "libinn.h" #include "nntp.h" #include "macros.h" STATIC char CApathname[sizeof _PATH_TEMPACTIVE]; STATIC FILE *CAfp; /* ** Get a copy of the active file for a client host to use, locally or ** remotely. */ FILE * CAopen(FromServer, ToServer) FILE *FromServer; FILE *ToServer; { /* Use a local (or NFS-mounted) copy if available. Make sure we don't * try to delete it when we close it. */ if ((CAfp = fopen(_PATH_CLIENTACTIVE, "r")) != NULL) { CApathname[0] = '\0'; return CAfp; } /* Use the active file from the server */ return CAlistopen(FromServer, ToServer, (char *)NULL); } /* ** Internal library routine. */ FILE * CA_listopen(pathname, FromServer, ToServer, request) char *pathname; FILE *FromServer; FILE *ToServer; char *request; { char buff[BUFSIZ]; char *p; int oerrno; FILE *F; (void)unlink(pathname); if ((F = fopen(pathname, "w")) == NULL) return NULL; /* Send a LIST command to and capture the output. */ if (request == NULL) (void)fprintf(ToServer, "list\r\n"); else (void)fprintf(ToServer, "list %s\r\n", request); (void)fflush(ToServer); /* Get the server's reply to our command. */ if (fgets(buff, sizeof buff, FromServer) == NULL || !EQn(buff, NNTP_LIST_FOLLOWS, STRLEN(NNTP_LIST_FOLLOWS))) { oerrno = errno; CAclose(); errno = oerrno; return NULL; } /* Slurp up the rest of the response. */ while (fgets(buff, sizeof buff, FromServer) != NULL) { if ((p = strchr(buff, '\r')) != NULL) *p = '\0'; if ((p = strchr(buff, '\n')) != NULL) *p = '\0'; if (buff[0] == '.' && buff[1] == '\0') { if (ferror(F) || fflush(F) == EOF || fclose(F) == EOF) break; return fopen(pathname, "r"); } (void)fprintf(F, "%s\n", buff); } /* Ran out of input before finding the terminator; quit. */ oerrno = errno; (void)fclose(F); CAclose(); errno = oerrno; return NULL; } /* ** Use the NNTP list command to get a file from a server. Default is ** the active file, otherwise ask for whatever is in the request param. */ FILE * CAlistopen(FromServer, ToServer, request) FILE *FromServer; FILE *ToServer; char *request; { /* Gotta talk to the server -- see if we can. */ if (FromServer == NULL || ToServer == NULL) return NULL; (void)strcpy(CApathname, _PATH_TEMPACTIVE); (void)mktemp(CApathname); return CAfp = CA_listopen(CApathname, FromServer, ToServer, request); } /* ** Close the file opened by CAopen or CAlistopen. */ void CAclose() { if (CAfp) { (void)fclose(CAfp); CAfp = NULL; } if (CApathname[0]) { (void)unlink(CApathname); CApathname[0] = '\0'; } } inn-1.7.2/lib/resource.c0100644000175100001440000000211706443103542013371 0ustar mdusers/* $Revision: 1.3 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include "macros.h" #if defined(RES_RUSAGE) #include #include #define TIMEVALasDOUBLE(t) \ ((double)(t).tv_sec + ((double)(t).tv_usec) / 1000000.0) int GetResourceUsage(usertime, systime) double *usertime; double *systime; { struct rusage R; if (getrusage(RUSAGE_SELF, &R) < 0) return -1; *usertime = TIMEVALasDOUBLE(R.ru_utime); *systime = TIMEVALasDOUBLE(R.ru_stime); return 0; } #endif /* defined(RES_RUSAGE) */ #if defined(RES_TIMES) #include #include #if !defined(HZ) #define HZ 60 #endif /* !defined(HZ) */ #define CPUTIMEasDOUBLE(t1, t2) ((double)(t1 + t2) / (double)HZ) int GetResourceUsage(usertime, systime) double *usertime; double *systime; { struct tms T; if (times(&T) == -1) return -1; *usertime = CPUTIMEasDOUBLE(T.tms_utime, T.tms_cutime); *systime = CPUTIMEasDOUBLE(T.tms_stime, T.tms_cstime); return 0; } #endif /* defined(RES_TIMES) */ inn-1.7.2/lib/memmove.c0100644000175100001440000000717706443103542013222 0ustar mdusers/* $Revision: 1.1 $ ** ** This file has been modified to get it to compile more easily ** on pre-4.4BSD systems. Rich $alz, June 1991. */ #include #include #include "configdata.h" #include "clibrary.h" #define const /* NULL */ #define void char #define size_t int #define NULL 0 #define MEMMOVE /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if 0 #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)bcopy.c 5.8 (Berkeley) 6/23/90"; #endif /* LIBC_SCCS and not lint */ #include #include #endif /* * sizeof(word) MUST BE A POWER OF TWO * SO THAT wmask BELOW IS ALL ONES */ typedef int word; /* "word" used for optimal copy speed */ #define wsize sizeof(word) #define wmask (wsize - 1) /* * Copy a block of memory, handling overlap. * This is the routine that actually implements * (the portable versions of) bcopy, memcpy, and memmove. */ #ifdef MEMCOPY void * memcpy(dst0, src0, length) #else #ifdef MEMMOVE void * memmove(dst0, src0, length) #else void bcopy(src0, dst0, length) #endif #endif char *dst0; const char *src0; register size_t length; { register char *dst = dst0; register const char *src = src0; register size_t t; if (length == 0 || dst == src) /* nothing to do */ goto retval; /* * Macros: loop-t-times; and loop-t-times, t>0 */ #define TLOOP(s) if (t) TLOOP1(s) #define TLOOP1(s) do { s; } while (--t) if ((unsigned long)dst < (unsigned long)src) { /* * Copy forward. */ t = (int)src; /* only need low bits */ if ((t | (int)dst) & wmask) { /* * Try to align operands. This cannot be done * unless the low bits match. */ if ((t ^ (int)dst) & wmask || length < wsize) t = length; else t = wsize - (t & wmask); length -= t; TLOOP1(*dst++ = *src++); } /* * Copy whole words, then mop up any trailing bytes. */ t = length / wsize; TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize); t = length & wmask; TLOOP(*dst++ = *src++); } else { /* * Copy backwards. Otherwise essentially the same. * Alignment works as before, except that it takes * (t&wmask) bytes to align, not wsize-(t&wmask). */ src += length; dst += length; t = (int)src; if ((t | (int)dst) & wmask) { if ((t ^ (int)dst) & wmask || length <= wsize) t = length; else t &= wmask; length -= t; TLOOP1(*--dst = *--src); } t = length / wsize; TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src); t = length & wmask; TLOOP(*--dst = *--src); } retval: #ifdef MEMCOPY return(dst0); #else #ifdef MEMMOVE return(dst0); #else return; #endif #endif } inn-1.7.2/lib/findheader.c0100644000175100001440000000137106443103542013634 0ustar mdusers/* $Revision: 1.8 $ ** */ #include #include #include "configdata.h" #include "clibrary.h" #include #include "libinn.h" #include "macros.h" /* ** Find a header in an article. */ char * HeaderFind(Article, Header, size) char *Article; char *Header; register int size; { register char *p; for (p = Article; ; ) { /* Match first character, then colon, then whitespace (don't * delete that line -- meet the RFC!) then compare the rest * of the word. */ if (p[size] == ':' && ISWHITE(p[size + 1]) && caseEQn(p, Header, (SIZE_T)size)) { for (p += size; *++p != '\n' && ISWHITE(*p); ) continue; return p; } if ((p = strchr(p, '\n')) == NULL || *++p == '\n') return NULL; } } inn-1.7.2/lib/strerror.c0100644000175100001440000000101606443103542013421 0ustar mdusers/* $Revision: 1.2 $ ** ** Only is needed; the others are just to get the right sprintf() ** declaration, sigh. */ #include #include #include "configdata.h" #include "clibrary.h" #include /* ** Return a string representation of errno. */ char * strerror(e) int e; { extern int sys_nerr; extern char *sys_errlist[]; static char buff[30]; if (e >= 0 && e < sys_nerr) return sys_errlist[e]; (void)sprintf(buff, "Error code %d\n", e); return buff; } inn-1.7.2/lib/makellib.sh0100644000175100001440000000113306443103542013507 0ustar mdusers#! /bin/sh ## $Revision: 1.2 $ ## ## Make a lint library for INN. Usage: ## makellib